Token Verification
Overview
Section titled “Overview”Access tokens are HS256 JWTs signed with the project’s signing_key. Verification is local — no network call to the auth service. This keeps latency low and eliminates a single point of failure for request authorization.
Verification
Section titled “Verification”const secret = new TextEncoder().encode(process.env.JWT_SECRET);
async function verifyAccessToken(token: string) { const { payload } = await jwtVerify(token, secret); return { userId: payload.sub as string, email: payload.email as string, role: payload.role as string, status: payload.status as string, emailVerified: payload.email_verified as boolean, };}What to Check
Section titled “What to Check”After verification, inspect the claims:
Status Check
Section titled “Status Check”if (payload.status === 'blocked') { // Clear cookies, return 403}Role Check (Admin Routes)
Section titled “Role Check (Admin Routes)”if (payload.role !== 'admin') { return new Response('Forbidden', { status: 403 });}PIN Privilege Check
Section titled “PIN Privilege Check”const privileges: string[] = payload.privileges || [];if (!privileges.includes('edit')) { return new Response('Forbidden', { status: 403 });}Token Fallback Strategy
Section titled “Token Fallback Strategy”When checking cookies, try the short-lived access token first, then fall back to the refresh token for verification-only scenarios:
const jar = await cookies();const token = jar.get('yourapp_access_token')?.value || jar.get('yourapp_auth_token')?.value;Error Handling
Section titled “Error Handling”The jose library throws specific errors:
| Error | Meaning | Action |
|---|---|---|
JWTExpired | Token past exp | Attempt refresh |
JWSSignatureVerificationFailed | Wrong signing key | Return 401, clear cookies |
JWTClaimValidationFailed | Invalid claims | Return 401, clear cookies |
try { const { payload } = await jwtVerify(token, secret); // Valid} catch (e) { if (e instanceof errors.JWTExpired) { // Try refresh } else { // Invalid token — clear auth state }}Library
Section titled “Library”We use jose — the standard JavaScript JWT library. It works in Node.js, Cloudflare Workers, Deno, and browsers.
pnpm add jose