Guides
Verify JWTs (TypeScript)
Validate Avnology ID access tokens locally using @avnology/backend's JWTVerifier.
Verify JWTs in TypeScript
When a user's access token lands in your backend, you have two options:
- Call
POST /v1/oauth/introspect-- simple, network hop per request. - Verify locally with cached JWKS -- sub-millisecond, no hop.
This guide does option 2. Use @avnology/backend's JWTVerifier.
Install
npm install @avnology/backendMinimum viable verifier
The verifier:
- Fetches
/.well-known/jwks.jsonon first call, caches it for 5 minutes. - On a
kidmiss (post-rotation) refreshes the JWKS once, with a 30-second cooldown to prevent JWKS DoS. - Enforces
iss,aud(if set),exp,nbf, and 30 seconds of clock skew tolerance. - Returns a strongly-typed
AvnologyClaimsobject. No Ory / Kratos / Hydra terminology leaks.
Use in Express middleware
import express from "express";
import { JWTVerifier } from "@avnology/backend";
const app = express();
const verifier = new JWTVerifier({
issuer: "https://api-id.avnology.net",
Or use the prebuilt middleware in @avnology/express:
import { requireAuth } from "@avnology/express";
app.use(requireAuth({
issuer: "https://api-id.avnology.net",
audience: "my-api",
}));Use in Next.js middleware
// middleware.ts
import { NextResponse, type NextRequest } from "next/server";
import { JWTVerifier } from "@avnology/backend";
const verifier = new JWTVerifier({
issuer: "https://api-id.avnology.net",
audience:
The @avnology/nextjs package wraps this pattern with avnologyMiddleware().
Claim reference
interface AvnologyClaims {
subject: string; // sub -- identity ID
userId: string; // alias for subject
organizationId?: string; // org_... when scoped
sessionId?: string; // ses_...
Common failure modes
| Error | Cause | Fix |
|---|---|---|
JWKSNoMatchingKey | Token kid not in JWKS | Ensure the verifier's issuer matches the token's iss |
JWTExpired | exp in past | Refresh the token via the SDK refreshToken() helper |
JWTClaimValidationFailed: audience | Wrong aud | Check your OAuth client's configured audience |
| Network timeout on JWKS | Gateway unreachable | Front the verifier with a CDN or lengthen cacheMaxAgeMs |