Skip to content

The BridgeAuthGuard returns RFC 6750-compliant WWW-Authenticate response headers so your frontend can distinguish between error types and handle them appropriately.

WWW-Authenticate errorMeaningRecommended action
missing_tokenNo Authorization header was sentRedirect to login
expired_tokenToken signature is valid but past expiryAttempt silent refresh, then redirect
invalid_tokenToken is malformed, tampered, or uses an unknown keyRedirect to login
src/lib/api.ts
import { auth } from '@nebulr-group/bridge-react'; // or bridge-svelte
async function apiFetch(endpoint: string, options: RequestInit = {}) {
const token = auth.getAccessToken();
const response = await fetch(`http://localhost:3000${endpoint}`, {
...options,
headers: {
...options.headers,
...(token ? { Authorization: `Bearer ${token}` } : {}),
'Content-Type': 'application/json',
},
});
if (response.status === 401) {
const wwwAuth = response.headers.get('WWW-Authenticate') ?? '';
if (wwwAuth.includes('expired_token')) {
try {
await auth.refresh();
const newToken = auth.getAccessToken();
return fetch(`http://localhost:3000${endpoint}`, {
...options,
headers: {
...options.headers,
Authorization: `Bearer ${newToken}`,
'Content-Type': 'application/json',
},
}).then((r) => r.json());
} catch {
auth.login();
return;
}
}
// missing_token or invalid_token — redirect to login
auth.login();
return;
}
if (!response.ok) {
throw new Error(`API error: ${response.status}`);
}
return response.json();
}

Returned when token is missing, expired, or invalid. Includes RFC 6750 WWW-Authenticate header:

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer error="expired_token", error_description="The access token has expired"
{
"statusCode": 401,
"error": "Unauthorized",
"message": "The access token has expired"
}

Auth type rejection (e.g., API token sent to a @AcceptAuth('jwt') endpoint):

{
"statusCode": 401,
"error": "Unauthorized",
"message": "auth type not accepted"
}

Returned when authenticated but lacking required role, privilege, or feature flag:

Role check failed:

{
"statusCode": 403,
"error": "Forbidden",
"message": "Role 'ADMIN' required"
}

Privilege check failed:

{
"statusCode": 403,
"error": "Forbidden",
"message": "Privilege 'USER_READ' required"
}

Feature flag not enabled:

{
"statusCode": 403,
"error": "Forbidden",
"message": "Feature flag 'beta-access' is not enabled"
}

Thrown by JwksService when token verification fails. Error codes:

CodeMeaning
TOKEN_EXPIREDJWT has expired
TOKEN_INVALIDJWT is malformed or invalid
JWKS_NO_MATCHNo matching key found in JWKS endpoint
CLAIM_VALIDATION_FAILEDToken claim validation failed (e.g., wrong issuer or audience)
APP_MISMATCHAPI token was issued for a different app ID
UNKNOWN_ERRORUnexpected verification error

These are mapped to RFC 6750 WWW-Authenticate errors by the guard:

Error CodeRFC 6750 ErrorDescription
TOKEN_EXPIREDexpired_tokenThe access token has expired
TOKEN_INVALIDinvalid_tokenThe access token is invalid
JWKS_NO_MATCHinvalid_tokenThe access token signature could not be verified
CLAIM_VALIDATION_FAILEDinvalid_tokenThe access token claim validation failed
APP_MISMATCHinvalid_tokenThe access token was issued for a different application

Thrown by BridgeHttpService when a downstream HTTP call returns a non-2xx response:

class BridgeHttpError extends Error {
readonly status: number; // HTTP status code
readonly url: string; // Request URL
}
try {
await this.bridgeHttp.get('http://service-b/data', token);
} catch (error) {
if (error instanceof BridgeHttpError) {
console.log(error.status); // e.g., 404
console.log(error.url); // 'http://service-b/data'
}
}