@authrim/server は、token validation、DPoP、JWKS、イントロスペクション、失効、Step-Up、設定エラー向けの構造化されたエラーシステムを提供します。validateToken() は通常のtoken validation失敗を { data: null, error } として返します。Framework adapterとhelper utilityは、HTTPレスポンス構築のために AuthrimServerError のmetadataを使います。
HTTP response metadataが必要な処理では 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 }
| プロパティ | 型 | 説明 |
|---|
code | string | 機械可読なエラーコード(下記テーブル参照) |
message | string | 人間が読めるエラー説明 |
meta | AuthrimServerErrorMeta | 分類メタデータ |
| プロパティ | 型 | 説明 |
|---|
httpStatus | number | レスポンスに推奨されるHTTPステータスコード |
transient | boolean | エラーが一時的で自然に解消する可能性があるかどうか |
retryable | boolean | オペレーションを安全にリトライできるかどうか |
wwwAuthenticateError | string | undefined | WWW-Authenticate ヘッダー用のエラーコード(RFC 6750) |
| コード | HTTPステータス | 一時的 | リトライ可 | 説明 |
|---|
invalid_token | 401 | いいえ | いいえ | トークンが無効(一般的な検証失敗) |
token_expired | 401 | いいえ | いいえ | トークンが期限切れ(expクレーム) |
token_not_yet_valid | 401 | いいえ | いいえ | トークンがまだ有効ではない(nbfクレーム) |
token_malformed | 401 | いいえ | いいえ | トークンをデコードまたはパースできない |
signature_invalid | 401 | いいえ | いいえ | JWT署名の検証に失敗 |
algorithm_mismatch | 401 | いいえ | いいえ | トークンのアルゴリズムが期待されるアルゴリズムと一致しない |
| コード | HTTPステータス | 一時的 | リトライ可 | 説明 |
|---|
invalid_issuer | 401 | いいえ | いいえ | トークンのissuerが期待される値と一致しない |
invalid_audience | 401 | いいえ | いいえ | トークンのaudienceに期待される値が含まれていない |
| コード | HTTPステータス | 一時的 | リトライ可 | 説明 |
|---|
jwks_fetch_error | 502 | はい | はい | JWKSドキュメントの取得に失敗 |
jwks_key_not_found | 401 | いいえ | いいえ | トークンのkidに一致するキーがJWKSに見つからない |
jwks_key_ambiguous | 401 | いいえ | いいえ | トークンのkidに一致するキーが複数存在する |
jwks_key_import_error | 500 | いいえ | いいえ | 署名検証用のJWKインポートに失敗 |
| コード | HTTPステータス | 一時的 | リトライ可 | 説明 |
|---|
dpop_proof_missing | 401 | いいえ | いいえ | DPoPプルーフヘッダーが欠落 |
dpop_proof_invalid | 401 | いいえ | いいえ | DPoPプルーフが不正または無効 |
dpop_proof_signature_invalid | 401 | いいえ | いいえ | DPoPプルーフの署名検証に失敗 |
dpop_method_mismatch | 401 | いいえ | いいえ | DPoPプルーフ内のHTTPメソッドがリクエストと一致しない |
dpop_uri_mismatch | 401 | いいえ | いいえ | DPoPプルーフ内のURIがリクエストURLと一致しない |
dpop_ath_mismatch | 401 | いいえ | いいえ | DPoPプルーフ内のアクセストークンハッシュが一致しない |
dpop_binding_mismatch | 401 | いいえ | いいえ | DPoPプルーフのキーがトークンバインディングと一致しない |
dpop_iat_expired | 401 | いいえ | いいえ | DPoPプルーフのiatが古すぎる |
dpop_nonce_required | 401 | いいえ | いいえ | サーバーがDPoP nonceを要求しているが提供されていない |
| コード | HTTPステータス | 一時的 | リトライ可 | 説明 |
|---|
introspection_error | 502 | はい | はい | トークンイントロスペクションリクエストが失敗 |
revocation_error | 502 | はい | はい | トークン失効リクエストが失敗 |
| コード | HTTPステータス | 一時的 | リトライ可 | 説明 |
|---|
configuration_error | 500 | いいえ | いいえ | 無効なSDK設定 |
provider_error | 500 | いいえ | いいえ | プロバイダー実装エラー |
| コード | HTTPステータス | 一時的 | リトライ可 | 説明 |
|---|
network_error | 502 | はい | はい | ネットワークリクエストが失敗 |
timeout_error | 504 | はい | はい | リクエストがタイムアウト |
RFC 6750準拠の WWW-Authenticate ヘッダー値を生成します:
import { buildWwwAuthenticateHeader } from '@authrim/server';
const header = buildWwwAuthenticateHeader(error, 'my-api');
// Bearer realm="my-api", error="invalid_token", error_description="Token has expired"
オプション:
| オプション | 型 | 説明 |
|---|
realm | string | ヘッダーのRealm値 |
HTTPレスポンスに適したJSONエラーボディを生成します:
import { buildErrorResponse } from '@authrim/server';
const body = buildErrorResponse(error);
// error: 'invalid_token',
// error_description: 'Token has expired'
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'
すべてのフレームワークアダプターは、ロギングとモニタリングのための onError コールバックを受け付けます:
import { authrimMiddleware } from '@authrim/server/adapters/express';
authrimMiddleware(server, {
// Log to your monitoring service
httpStatus: error.httpStatus,
metrics.increment('auth.error', { code: error.code });
} 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) });
一時的エラー(ネットワーク障害、JWKSフェッチ失敗)はリトライ可能です。meta.transient と meta.retryable フラグを使用してリトライロジックを構築してください:
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));
| カテゴリ | 一時的 | リトライ可 | 対処方法 |
|---|
| JWT検証 | いいえ | いいえ | 即座に401を返す |
| Issuer/Audience | いいえ | いいえ | 即座に401を返す |
| DPoP | いいえ | いいえ | 即座に401を返す |
| JWKSフェッチ | はい | はい | バックオフでリトライ |
| オペレーション(イントロスペクション/失効) | はい | はい | バックオフでリトライ |
| ネットワーク | はい | はい | バックオフでリトライ |
| 設定 | いいえ | いいえ | 設定を修正して再起動 |