@kiavi/kiavi-js
Ce contenu n’est pas encore disponible dans votre langue.
0.2.0Server-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.
Install
Section titled “Install”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:
npx kiavi-js initThis 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.
Minimum viable integration
Section titled “Minimum viable integration”Three things, in order:
- Construct one
KiaviClientat module load with your auth base URL and expected JWT audience. - Extract the bearer token from the incoming request.
- Call
verifyToken(). Reject the request if it returnsnull.
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 handlerimport { 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.
When to use verifyToken vs verifySession
Section titled “When to use verifyToken vs verifySession”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.
Options
Section titled “Options”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,trueuses the built-in console logger. A function receives structured log entries.
Methods
Section titled “Methods”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 aboveJWTPayload, payload returned byverifyToken()(fields above)SessionPayload, payload returned byverifySession()KiaviClientOptionsKiaviTokenErrorKiaviDebugLogger
Do / do not
Section titled “Do / do not”Do:
- Construct one
KiaviClientat 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-browseron the web or@kiavi/kiavi-react-nativeon 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. Anullreturn 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.