UNPKG

better-auth

Version:

The most comprehensive authentication framework for TypeScript.

46 lines (45 loc) 1.66 kB
import { getJwksAdapter } from "./adapter.mjs"; import { getCurrentAuthContext } from "@better-auth/core/context"; import { base64 } from "@better-auth/utils/base64"; import { importJWK, jwtVerify } from "jose"; //#region src/plugins/jwt/verify.ts /** * Verify a JWT token using the JWKS public keys * Returns the payload if valid, null otherwise */ async function verifyJWT(token, options) { const ctx = await getCurrentAuthContext(); try { const parts = token.split("."); if (parts.length !== 3) return null; const headerStr = new TextDecoder().decode(base64.decode(parts[0])); const kid = JSON.parse(headerStr).kid; if (!kid) { ctx.context.logger.debug("JWT missing kid in header"); return null; } const keys = await getJwksAdapter(ctx.context.adapter, options).getAllKeys(ctx); if (!keys || keys.length === 0) { ctx.context.logger.debug("No JWKS keys available"); return null; } const key = keys.find((k) => k.id === kid); if (!key) { ctx.context.logger.debug(`No JWKS key found for kid: ${kid}`); return null; } const cryptoKey = await importJWK(JSON.parse(key.publicKey), key.alg ?? options?.jwks?.keyPairConfig?.alg ?? "EdDSA"); const baseURLOrigin = typeof ctx.context.options.baseURL === "string" ? ctx.context.options.baseURL : void 0; const { payload } = await jwtVerify(token, cryptoKey, { issuer: options?.jwt?.issuer ?? baseURLOrigin, audience: options?.jwt?.audience ?? baseURLOrigin }); if (!payload.sub || !payload.aud) return null; return payload; } catch (error) { ctx.context.logger.debug("JWT verification failed", error); return null; } } //#endregion export { verifyJWT };