Overview

@guacamole_hbai/auth is the server-side Node client. Your application signs people in with any conformant OIDC library — this library is not in the sign-in path. It covers the surface either side: provisioning people, issuing enrolment invitations, and receiving the signed events that say a session should no longer be trusted.

npm install @guacamole_hbai/auth

Node 18+, ESM, TypeScript types included. Zero runtime dependencies — fetch and node:crypto do everything, including RS256 verification, so there is no jose to keep in step with whatever your OIDC stack already pins.

Someone else sits down. Your app finds out.

A complete, verified security-event endpoint:

import { Guacamole, SESSION_REVOKED, subjectOf } from "@guacamole_hbai/auth";

const gid = new Guacamole({
  apiKey: process.env.GUACAMOLE_API_KEY!,
  tenant: "acme",
  baseUrl: "https://guacamole.ai",
});

const receiver = gid.receiver({ audience: "https://app.acme.com" });

receiver.on(SESSION_REVOKED, async (event, claims) => {
  await sessions.revokeAllFor(subjectOf(claims));
});

export const POST = receiver.handler();

handler() reads the raw body, fetches and caches the provider's signing keys, verifies the token, refuses a replay, dispatches to your callback, and answers with the status the provider's retry policy depends on. It never throws.

export const POST is the Next.js, Hono, Bun, Deno and Workers route — there is no framework-named subpath to install. For Express, Connect, Fastify and raw node:http, use receiver.nodeHandler().

Then tell the provider where to send them

await gid.streams.ensure({
  endpointUrl: `${process.env.PUBLIC_APP_URL}/api/events`,
  receiver,
});

Passing the receiver rather than an aud string means the one value that has to agree in two places cannot disagree. ensure is an upsert, so there is no conflict to catch.

What is here

gid.subjects create, get by externalId or sub, list, iterate, suspend, deactivate, erase
gid.enrollments invitations — one call, returns the hosted link — and a one-shot status check
gid.credentials list and revoke passkeys
gid.identifications hosted 1:N lookup. Issues no token and signs nobody in
gid.audit the authentication log
gid.streams register and test your security-event channel
gid.receiver(…) verify and dispatch delivered events
verifyClaims(…) the acr check no OIDC library does for you
gid.tokens.verify(…) the whole ID-token check, where there is no OIDC library at all

Where to go next

  • Receiving events — the receiver in full: replay stores, status codes, what each event means.
  • Verifying tokens — the acr check, and the whole check where you have no OIDC library.
  • Managing people — subjects, enrolment, identification, the audit log.
  • Reference — every export, grouped.