トークン検証
概要
トークン検証は@authrim/serverの中核機能です。validateToken()メソッドは、JWTの解析、署名鍵の取得、署名の検証、すべての標準クレームのチェックという完全な検証パイプラインを実行します。
validateToken API
const result = await authrim.validateToken(token, options?);パラメータ
| パラメータ | 型 | 説明 |
|---|---|---|
token | string | 生のJWTアクセストークン(Bearerプレフィックスなし) |
options | TokenValidationOptions | オプションの検証オプション |
TokenValidationOptions
interface TokenValidationOptions { requiredScopes?: string[]; requiredClaims?: string[];}| オプション | 型 | 説明 |
|---|---|---|
requiredScopes | string[] | トークンのscopeクレームに存在する必要があるスコープ |
requiredClaims | string[] | トークンペイロードに存在する必要があるクレーム名 |
戻り値: ValidatedToken
interface ValidatedToken { claims: AccessTokenClaims; token: string; tokenType: 'Bearer' | 'DPoP'; expiresIn?: number;}| フィールド | 型 | 説明 |
|---|---|---|
claims | AccessTokenClaims | 解析・検証済みのJWTクレーム |
token | string | 元のトークン文字列 |
tokenType | 'Bearer' | 'DPoP' | クレームに基づいて検出されたトークンタイプ |
expiresIn | number | undefined | トークンの有効期限までの秒数(expから計算) |
AccessTokenClaims
interface AccessTokenClaims { iss: string; sub: string; aud: string | string[]; exp: number; iat: number; nbf?: number; jti?: string; scope?: string; client_id?: string; cnf?: { jkt?: string }; [key: string]: unknown; // Custom claims}検証パイプライン
SDKは以下のパイプラインでトークンを検証します。トークンが受け入れられるには、各ステップをパスする必要があります。
flowchart TD
A["JWT文字列を受信"] --> B["サイズチェック
(最大 8 KB)"]
B --> C["JWTを解析
(Header + Payload + Signature)"]
C --> D["アルゴリズムチェック
(alg: none を拒否)"]
D --> E["署名鍵を取得
(JWKS by kid)"]
E --> F["署名を検証
(RS/PS/ES/EdDSA)"]
F --> G["issを検証
(タイミングセーフ)"]
G --> H["audを検証
(タイミングセーフ)"]
H --> I["expを検証
(+ クロック許容値)"]
I --> J["nbfを検証
(+ クロック許容値)"]
J --> K["iatを検証
(未来でないこと)"]
K --> L["必要なスコープをチェック"]
L --> M["必要なクレームをチェック"]
M --> N["トークンタイプを検出
(Bearer vs DPoP)"]
N --> O["ValidatedTokenを返却"]
いずれかのステップが失敗した場合、SDKは特定のエラーをスローします。以下のエラータイプセクションを参照してください。
サポートされるアルゴリズム
SDKは署名検証に以下のJWSアルゴリズムをサポートしています:
| アルゴリズム | 鍵タイプ | 曲線 / サイズ | 説明 |
|---|---|---|---|
| RS256 | RSA | 2048+ビット | RSASSA-PKCS1-v1_5 with SHA-256 |
| RS384 | RSA | 2048+ビット | RSASSA-PKCS1-v1_5 with SHA-384 |
| RS512 | RSA | 2048+ビット | RSASSA-PKCS1-v1_5 with SHA-512 |
| PS256 | RSA | 2048+ビット | RSASSA-PSS with SHA-256 |
| PS384 | RSA | 2048+ビット | RSASSA-PSS with SHA-384 |
| PS512 | RSA | 2048+ビット | RSASSA-PSS with SHA-512 |
| ES256 | EC | P-256 | ECDSA with SHA-256 |
| ES384 | EC | P-384 | ECDSA with SHA-384 |
| ES512 | EC | P-521 | ECDSA with SHA-512 |
| EdDSA | OKP | Ed25519 | Edwards-curve Digital Signature |
クレーム検証の詳細
発行者(iss)
issクレームは、設定されたissuer値のいずれかと正確に一致する必要があります。比較にはサイドチャネル攻撃を防止するためにタイミングセーフアルゴリズムが使用されます。
// Single issuerconst authrim = new AuthrimServer({ issuer: 'https://auth.example.com', audience: 'https://api.example.com',});
// Multiple issuersconst authrim = new AuthrimServer({ issuer: [ 'https://auth.example.com', 'https://auth.partner.com', ], audience: 'https://api.example.com',});オーディエンス(aud)
audクレームには、設定されたaudience値の少なくとも1つが含まれている必要があります。audクレームは単一の文字列または文字列の配列です。すべての比較はタイミングセーフです。
// Token with aud: "https://api.example.com" — matches// Token with aud: ["https://api.example.com", "other"] — matches// Token with aud: "https://other.example.com" — rejected有効期限(exp)
expクレームは、現在時刻にclockToleranceSecondsを加えた値と照合されます:
token is valid if: exp + clockToleranceSeconds > nowデフォルトの許容値60秒では、最大60秒前に期限切れになったトークンでも受け入れられます。
有効開始時刻(nbf)
存在する場合、nbfクレームは現在時刻からclockToleranceSecondsを引いた値と照合されます:
token is valid if: nbf - clockToleranceSeconds <= now発行時刻(iat)
iatクレームは、トークンが未来に発行されていないことをサニティチェックします(クロック許容値を考慮):
token is valid if: iat - clockToleranceSeconds <= nowスコープ検証
requiredScopesオプションを使用して必要なスコープを適用します:
// Require specific scopesconst result = await authrim.validateToken(token, { requiredScopes: ['read:users', 'write:users'],});SDKは、指定されたすべてのスコープがトークンのscopeクレーム(スペース区切り文字列)に存在するかをチェックします。必要なスコープが1つでも欠けている場合、InsufficientScopeErrorがスローされます。
BearerとDPoPの自動検出
SDKはcnf(confirmation)クレームに基づいてトークンタイプを自動検出します:
- トークンに
cnf.jkt(JWK Thumbprint)が含まれている場合、トークンはDPoPとして分類されます - それ以外の場合、トークンは
Bearerとして分類されます
const result = await authrim.validateToken(token);
if (result.tokenType === 'DPoP') { // This token is sender-constrained — validate the DPoP proof too await authrim.validateDPoP(dpopProof, { accessTokenHash: computeHash(token), expectedThumbprint: result.claims.cnf!.jkt!, method: 'GET', url: 'https://api.example.com/resource', });}完全なDPoP検証については、DPoP検証を参照してください。
コード例
基本的なトークン検証
import { AuthrimServer } from '@authrim/server';
const authrim = new AuthrimServer({ issuer: 'https://auth.example.com', audience: 'https://api.example.com',});await authrim.init();
try { const result = await authrim.validateToken(accessToken); console.log('User:', result.claims.sub); console.log('Scopes:', result.claims.scope); console.log('Expires in:', result.expiresIn, 'seconds');} catch (error) { console.error('Token validation failed:', error.message);}必要なスコープ付き
try { const result = await authrim.validateToken(accessToken, { requiredScopes: ['read:orders', 'write:orders'], }); // Token is valid and has both scopes} catch (error) { if (error.name === 'InsufficientScopeError') { // Token is valid but missing required scopes — return 403 return res.status(403).json({ error: 'insufficient_scope' }); } // Token is invalid — return 401 return res.status(401).json({ error: 'invalid_token' });}カスタムクレームへのアクセス
トークンには、認可サーバーによって追加されたカスタムクレーム(ロール、テナントIDなど)が含まれる場合があります。claimsオブジェクトを通じてアクセスします:
const result = await authrim.validateToken(accessToken);
// Access custom claims with type assertionconst roles = result.claims['roles'] as string[];const tenantId = result.claims['tenant_id'] as string;
// Or use a type parameter for full type safetyinterface MyTokenClaims extends AccessTokenClaims { roles: string[]; tenant_id: string;}
const claims = result.claims as MyTokenClaims;console.log(claims.roles); // ['admin', 'user']console.log(claims.tenant_id); // 'tenant-123'エラータイプ
| エラー | 説明 | HTTPステータス |
|---|---|---|
InsecureAlgorithmError | トークンがalg: noneまたはサポートされていないアルゴリズムを使用 | 401 |
InvalidSignatureError | 署名検証が失敗 | 401 |
TokenExpiredError | トークンのexpクレームが経過(クロック許容値を超過) | 401 |
TokenNotYetValidError | トークンのnbfクレームが未来(クロック許容値を超過) | 401 |
InvalidIssuerError | トークンのissが設定された発行者と一致しない | 401 |
InvalidAudienceError | トークンのaudが設定されたオーディエンスと一致しない | 401 |
InsufficientScopeError | トークンに必要なスコープが1つ以上不足 | 403 |
MissingClaimError | トークンに必要なクレームが不足 | 401 |
JwksError | JWKSの取得または処理に失敗 | 500 |
TokenSizeLimitError | トークンが8 KBサイズ制限を超過 | 401 |
次のステップ
- DPoP検証 — DPoPプルーフ検証による送信者制約トークンの検証
- JWKS管理 — 鍵のディスカバリ、キャッシュ、ローテーションの内部構造
- イントロスペクションと失効 — 認可サーバーでのトークンの問い合わせと失効
- セキュリティに関する考慮事項 — 本番セキュリティチェックリストとベストプラクティス