# jwt ## Purpose Provides minimal JWT decoding utilities for extracting and validating ID-token claims on the client side. Signature verification requires fetching the authorization server's JWKS endpoint and is deliberately out of scope — this module focuses on the claim-level checks that can be performed without cryptographic key material: issuer, audience, expiry, and nonce. Separating JWT decoding from signature verification follows the principle of least authority: most OAuth 2.0 client use-cases need only claim extraction for session management, and those that require full verification can layer a JWKS-backed verifier on top. ## Features - `decodeJwt` — splits a JWT and base64url-decodes the header and payload; returns typed `JwtHeader` and `IdTokenClaims`. - `validateIdTokenClaims` — verifies `iss`, `aud`, `exp` (with configurable clock skew), and optional `nonce`. - Throws `OAuthClientError(INVALID_ID_TOKEN)` with structured context on every failure path. ## Usage: Basic Example ```ts import { decodeJwt } from "@suaveplan/oauth-client/utils/jwt"; const { header, claims } = decodeJwt(tokenSet.idToken!); console.log(claims.sub); // subject identifier console.log(claims.email); // user email (if present) ``` ## Usage: Advanced Example ```ts import { decodeJwt, validateIdTokenClaims } from "@suaveplan/oauth-client/utils/jwt"; const { claims } = decodeJwt(tokenSet.idToken!); validateIdTokenClaims(claims, { issuer: "https://accounts.google.com", audience: "my-client-id", nonce: storedNonce, clockSkewSeconds: 60, }); // Safe to trust claims after validation passes const userId = claims.sub; ``` ## API Reference ### `decodeJwt(token: string): { header: JwtHeader; claims: IdTokenClaims; raw: { header: string; payload: string; signature: string } }` Decodes a JWT string without verifying its signature. - **Throws** `OAuthClientError(INVALID_ID_TOKEN)` when the token does not have exactly three `.`-delimited parts or when either the header or payload is not valid base64url-encoded JSON. ### `validateIdTokenClaims(claims: IdTokenClaims, options): void` Validates standard OIDC ID-token claims. - `options.issuer` — expected `iss` value; must match exactly. - `options.audience` — expected `aud` value; must be present in the `aud` array. - `options.nonce?` — when provided, must match `claims.nonce`. - `options.clockSkewSeconds?` — tolerance for clock drift, defaults to 30. - `options.nowSeconds?` — override for the current time (seconds since epoch); useful in tests. - **Throws** `OAuthClientError(INVALID_ID_TOKEN)` for any failed check. ## Implementation Notes The `decodeJwt` function uses `base64UrlDecode` from the `pkce` utility to avoid introducing a second base64url implementation. The `TextDecoder` API is universally available in all targeted runtimes. Claims are typed as `IdTokenClaims` which uses an index signature `[key: string]: unknown` to allow non-standard claims without compromising the strict types of standard fields. Clock-skew tolerance applies only to the `exp` check (not `iat`) to avoid accepting tokens from the future.