@authrim/server provides a structured error system for token validation, DPoP, JWKS, introspection, revocation, Step-Up, and configuration failures. validateToken() returns normal token-validation failures as { data: null, error }; framework adapters and helper utilities use AuthrimServerError metadata to build HTTP responses.
Operations that need HTTP response metadata use AuthrimServerError:
import { AuthrimServerError } from ' @authrim/server ' ;
const result = await server . validateToken (accessToken);
const error = new AuthrimServerError (
result . error . code as any ,
console . log (error . code ); // e.g., 'token_expired'
console . log (error . message ); // Human-readable description
console . log (error . meta ); // { httpStatus, transient, retryable, wwwAuthenticateError }
Property Type Description codestringMachine-readable error code (see table below) messagestringHuman-readable error description metaAuthrimServerErrorMetaClassification metadata
Property Type Description httpStatusnumberRecommended HTTP status code for the response transientbooleanWhether the error is temporary and may resolve on its own retryablebooleanWhether the operation can be safely retried wwwAuthenticateErrorstring | undefinedError code for the WWW-Authenticate header (RFC 6750)
Code HTTP Status Transient Retryable Description invalid_token401 No No Token is invalid (general validation failure) token_expired401 No No Token has expired (exp claim) token_not_yet_valid401 No No Token is not yet valid (nbf claim) token_malformed401 No No Token cannot be decoded or parsed signature_invalid401 No No JWT signature verification failed algorithm_mismatch401 No No Token algorithm does not match expected algorithms
Code HTTP Status Transient Retryable Description invalid_issuer401 No No Token issuer does not match expected issuer invalid_audience401 No No Token audience does not include expected audience
Code HTTP Status Transient Retryable Description jwks_fetch_error502 Yes Yes Failed to fetch the JWKS document jwks_key_not_found401 No No No matching key found in JWKS for the token’s kid jwks_key_ambiguous401 No No Multiple keys match the token’s kid jwks_key_import_error500 No No Failed to import a JWK for signature verification
Code HTTP Status Transient Retryable Description dpop_proof_missing401 No No DPoP proof header is missing dpop_proof_invalid401 No No DPoP proof is malformed or invalid dpop_proof_signature_invalid401 No No DPoP proof signature verification failed dpop_method_mismatch401 No No HTTP method in DPoP proof does not match request dpop_uri_mismatch401 No No URI in DPoP proof does not match request URL dpop_ath_mismatch401 No No Access token hash in DPoP proof does not match dpop_binding_mismatch401 No No DPoP proof key does not match token binding dpop_iat_expired401 No No DPoP proof iat is too old dpop_nonce_required401 No No Server requires a DPoP nonce but none was provided
Code HTTP Status Transient Retryable Description introspection_error502 Yes Yes Token introspection request failed revocation_error502 Yes Yes Token revocation request failed
Code HTTP Status Transient Retryable Description configuration_error500 No No Invalid SDK configuration provider_error500 No No Provider implementation error
Code HTTP Status Transient Retryable Description network_error502 Yes Yes Network request failed timeout_error504 Yes Yes Request timed out
Generates an RFC 6750 compliant WWW-Authenticate header value:
import { buildWwwAuthenticateHeader } from ' @authrim/server ' ;
const header = buildWwwAuthenticateHeader (error , ' my-api ' );
// Bearer realm="my-api", error="invalid_token", error_description="Token has expired"
Options:
Option Type Description realmstringRealm value for the header
Generates a JSON error body suitable for HTTP responses:
import { buildErrorResponse } from ' @authrim/server ' ;
const body = buildErrorResponse (error);
// error: 'invalid_token',
// error_description: 'Token has expired'
Generates response headers including WWW-Authenticate:
import { buildErrorHeaders } from ' @authrim/server ' ;
const headers = buildErrorHeaders (error , { realm: ' my-api ' } );
// 'WWW-Authenticate': 'Bearer realm="my-api", error="invalid_token", ...',
// 'Content-Type': 'application/json'
All framework adapters accept an onError callback for logging and monitoring:
import { authrimMiddleware } from ' @authrim/server/adapters/express ' ;
authrimMiddleware (server, {
// Log to your monitoring service
httpStatus: error . httpStatus ,
metrics . increment ( ' auth.error ' , { code: error . code });
Middleware Error Behavior
When using the required middleware (e.g., authrimMiddleware), the adapter automatically returns the correct HTTP status code and WWW-Authenticate header. The onError callback is for observability only — it does not change the response.
} from ' @authrim/server ' ;
app . get ( ' /api/resource ' , async ( req , res ) => {
const token = req . headers . authorization ?. replace ( ' Bearer ' , '' ) ?? '' ;
const result = await server . validateToken (token);
const error = new AuthrimServerError (
result . error . code as any ,
const headers = buildErrorHeaders (error , { realm: ' my-api ' } );
const body = buildErrorResponse (error);
return res . status (error . meta . httpStatus ) . set (headers) . json (body);
res . json ({ data: getResource (result . data . claims . sub ) });
import { AuthrimServerError, buildErrorResponse } from ' @authrim/server ' ;
app . get ( ' /api/resource ' , async ( c ) => {
const token = c . req . header ( ' authorization ' ) ?. replace ( ' Bearer ' , '' ) ?? '' ;
const result = await server . validateToken (token);
const error = new AuthrimServerError (
result . error . code as any ,
return c . json ( buildErrorResponse (error), error . meta . httpStatus );
return c . json ({ data: getResource (result . data . claims . sub ) });
Transient errors (network issues, JWKS fetch failures) can be retried. Use the meta.transient and meta.retryable flags to build retry logic:
import { AuthrimServerError } from ' @authrim/server ' ;
async function validateWithRetry (
) : Promise < ValidatedToken > {
let lastError : AuthrimServerError | undefined ;
for ( let attempt = 0 ; attempt <= maxRetries; attempt ++ ) {
const result = await server . validateToken (token);
const error = new AuthrimServerError (
result . error . code as any ,
// Only retry transient, retryable errors
if ( ! error . meta . retryable || attempt === maxRetries) {
// Exponential backoff: 100ms, 200ms, 400ms
const delay = 100 * Math . pow ( 2 , attempt);
await new Promise ( ( resolve ) => setTimeout (resolve , delay));
Do Not Retry Non-Transient Errors
Errors like invalid_token, token_expired, and signature_invalid are not transient — the same input will always produce the same error. Only retry when error.meta.retryable is true.
Category Transient Retryable Action JWT Validation No No Return 401 immediately Issuer/Audience No No Return 401 immediately DPoP No No Return 401 immediately JWKS Fetch Yes Yes Retry with backoff Operations (introspection/revocation) Yes Yes Retry with backoff Network Yes Yes Retry with backoff Configuration No No Fix configuration and restart