Ga naar inhoud

@kiavi/kiavi-js

Deze inhoud is nog niet vertaald.

Current version: 0.2.0

Server-side verification for APIs that sit behind a Kiavi auth server. Use this package on the backend (Node, Bun, Deno, edge runtimes) to check that an incoming request is from a real, signed-in user.

This page mirrors the llm-docs.md that ships with the installed package, that file is the authoritative source. If anything here ever drifts, trust the package version.

Terminal window
pnpm add @kiavi/kiavi-js

(Or npm install, yarn add, bun add, they all work.)

Then run the init command to install the version-pinned integration guide for AI coding agents into your repo:

Terminal window
npx kiavi-js init

This writes .kiavi/kiavi-js.md and adds a reference block to your AGENTS.md (or CLAUDE.md). Re-run on every upgrade. See AI agent docs for the full explanation.

Three things, in order:

  1. Construct one KiaviClient at module load with your auth base URL and expected JWT audience.
  2. Extract the bearer token from the incoming request.
  3. Call verifyToken(). Reject the request if it returns null.
lib/auth.ts
import { KiaviClient } from '@kiavi/kiavi-js'
export const kiavi = new KiaviClient(
'https://auth.your-domain.com',
'my-api-audience', // must match the audience the auth server is configured to issue
)
// in a middleware / request handler
import { kiavi } from './lib/auth'
const authHeader = request.headers.get('authorization') ?? ''
const token = authHeader.replace(/^Bearer /i, '')
const user = await kiavi.verifyToken(token)
if (!user) {
return new Response('Unauthorized', { status: 401 })
}
// user.sub, user.email, user.app_id, etc. are now trusted.

That is the full happy path. verifyToken() is offline after the initial JWKS fetch , you can call it freely on every request without worrying about latency or coupling to the auth server.

verifyToken() is the default. It’s offline (no network hop after the initial JWKS fetch), checks signature / issuer / audience / expiration, and is what you want for essentially every normal request.

What it doesn’t know is anything that changed on the server after the token was issued: a revoked session or a disabled user. Those only become visible to verifyToken when the current token expires and the client has to mint a new one, so the staleness window is roughly “one access-token lifetime.”

Kiavi currently issues access tokens with a 10-minute lifetime, so in practice the worst case is that a revoked session stays usable for up to 10 minutes after revocation. If that’s acceptable for the operation you’re protecting, stick with verifyToken(). If it isn’t, use verifySession() below.

verifySession() round-trips to the auth server on every call, so it always sees live state. Reach for it when that staleness window is unacceptable for the operation at hand, e.g. high-value money movement, permissions changes, anything where a just-revoked session absolutely must not go through. The cost is an extra network hop per request and a hard dependency on the auth server being reachable.

Rule of thumb: use verifyToken() everywhere; use verifySession() only on the handful of endpoints where the trade-off is worth it, and cache its result for the duration of the request if you call it more than once.

new KiaviClient('https://auth.your-domain.com', 'my-api-audience', {
debug: true, // logs to console.debug; pass a function to route logs elsewhere
})
  • debug?: boolean | KiaviDebugLogger, true uses the built-in console logger. A function receives structured log entries.

verifyToken(token: string): Promise<JWTPayload | null>

Section titled “verifyToken(token: string): Promise<JWTPayload | null>”

Verifies a JWT from an Authorization: Bearer header. Checks signature, issuer, audience, and expiration against cached JWKS. Returns the decoded payload on success or null on any failure. Never throws.

The returned payload contains:

type JWTPayload = {
sub: string // user ID
email: string
emailVerified?: boolean
name?: string | null
app_id?: string
app_slug?: string
auth_method?: string
iss: string
aud: string | string[]
exp: number
iat: number
}

verifySession(cookieHeader: string): Promise<SessionPayload | null>

Section titled “verifySession(cookieHeader: string): Promise<SessionPayload | null>”

Alternative verification path for routes that receive a session cookie directly instead of a bearer token (same-site rendered routes). Forwards the cookie header to the auth server and returns the resolved session, or null if missing/invalid. Never throws.

Unlike verifyToken(), this makes a network round-trip on every call. Use only when the staleness trade-off above is unacceptable. Cache the result for the duration of a single request if you call it more than once.

Exported from @kiavi/kiavi-js:

  • KiaviClient, the class above
  • JWTPayload, payload returned by verifyToken() (fields above)
  • SessionPayload, payload returned by verifySession()
  • KiaviClientOptions
  • KiaviTokenError
  • KiaviDebugLogger

Do:

  • Construct one KiaviClient at module load and reuse it across requests. The JWKS cache lives on the instance.
  • Call verifyToken() on every protected request, it’s offline and cheap.
  • Trust the claims in the returned payload. They’ve been signature-verified against the auth server’s JWKS.
  • Pair this with @kiavi/kiavi-browser on the web or @kiavi/kiavi-react-native on mobile to obtain the tokens this server SDK verifies.

Do not:

  • Do not call verifySession() on every request just because it’s “more secure” , it adds a network hop and creates a hard dependency on the auth server being up. Save it for the operations where the 10-minute staleness window genuinely matters.
  • Do not catch and rethrow exceptions from verifyToken(), it never throws. A null return is the entire failure surface.
  • Do not look users up in your own database to “double-check” the token. The JWT signature is the proof; you only need to look the user up if you store app-specific data.