@authrim/server 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/README.md +610 -0
  2. package/dist/adapters/express.cjs +3 -0
  3. package/dist/adapters/express.cjs.map +1 -0
  4. package/dist/adapters/express.d.cts +75 -0
  5. package/dist/adapters/express.d.ts +75 -0
  6. package/dist/adapters/express.js +3 -0
  7. package/dist/adapters/express.js.map +1 -0
  8. package/dist/adapters/fastify.cjs +3 -0
  9. package/dist/adapters/fastify.cjs.map +1 -0
  10. package/dist/adapters/fastify.d.cts +101 -0
  11. package/dist/adapters/fastify.d.ts +101 -0
  12. package/dist/adapters/fastify.js +3 -0
  13. package/dist/adapters/fastify.js.map +1 -0
  14. package/dist/adapters/hono.cjs +2 -0
  15. package/dist/adapters/hono.cjs.map +1 -0
  16. package/dist/adapters/hono.d.cts +85 -0
  17. package/dist/adapters/hono.d.ts +85 -0
  18. package/dist/adapters/hono.js +2 -0
  19. package/dist/adapters/hono.js.map +1 -0
  20. package/dist/adapters/koa.cjs +3 -0
  21. package/dist/adapters/koa.cjs.map +1 -0
  22. package/dist/adapters/koa.d.cts +75 -0
  23. package/dist/adapters/koa.d.ts +75 -0
  24. package/dist/adapters/koa.js +3 -0
  25. package/dist/adapters/koa.js.map +1 -0
  26. package/dist/adapters/nestjs.cjs +3 -0
  27. package/dist/adapters/nestjs.cjs.map +1 -0
  28. package/dist/adapters/nestjs.d.cts +126 -0
  29. package/dist/adapters/nestjs.d.ts +126 -0
  30. package/dist/adapters/nestjs.js +3 -0
  31. package/dist/adapters/nestjs.js.map +1 -0
  32. package/dist/chunk-7POGA5LZ.cjs +3 -0
  33. package/dist/chunk-7POGA5LZ.cjs.map +1 -0
  34. package/dist/chunk-N3ONRO35.js +2 -0
  35. package/dist/chunk-N3ONRO35.js.map +1 -0
  36. package/dist/chunk-O2ALCNXB.cjs +2 -0
  37. package/dist/chunk-O2ALCNXB.cjs.map +1 -0
  38. package/dist/chunk-OS567YCE.js +3 -0
  39. package/dist/chunk-OS567YCE.js.map +1 -0
  40. package/dist/chunk-TPROSFE7.cjs +2 -0
  41. package/dist/chunk-TPROSFE7.cjs.map +1 -0
  42. package/dist/chunk-XOFM2JHF.js +2 -0
  43. package/dist/chunk-XOFM2JHF.js.map +1 -0
  44. package/dist/config-I0GIVJA_.d.cts +364 -0
  45. package/dist/config-I0GIVJA_.d.ts +364 -0
  46. package/dist/index.cjs +3 -0
  47. package/dist/index.cjs.map +1 -0
  48. package/dist/index.d.cts +791 -0
  49. package/dist/index.d.ts +791 -0
  50. package/dist/index.js +3 -0
  51. package/dist/index.js.map +1 -0
  52. package/dist/providers/index.cjs +2 -0
  53. package/dist/providers/index.cjs.map +1 -0
  54. package/dist/providers/index.d.cts +79 -0
  55. package/dist/providers/index.d.ts +79 -0
  56. package/dist/providers/index.js +2 -0
  57. package/dist/providers/index.js.map +1 -0
  58. package/dist/types-CzpMdWFR.d.cts +435 -0
  59. package/dist/types-D7gjcvs9.d.ts +435 -0
  60. package/package.json +119 -0
@@ -0,0 +1,791 @@
1
+ import { A as AuthrimServer, a as AuthenticateRequest, b as AuthenticateResult, J as JwtHeader, P as ParsedJwt, S as StandardClaims, C as ClaimsValidationOptions, c as ClaimsValidationResult, T as TokenValidationOptions, d as TokenValidationResult, I as IntrospectionRequest, e as IntrospectionResponse, R as RevocationRequest, D as DPoPValidationOptions, f as DPoPValidationResult } from './types-D7gjcvs9.js';
2
+ export { g as AccessTokenClaims, h as AuthenticateError, i as AuthenticateSuccess, j as ConfirmationClaim, k as DPoPProofHeader, l as DPoPProofPayload, m as IdTokenClaims, M as MiddlewareOptions, V as ValidatedToken, n as createAuthrimServer } from './types-D7gjcvs9.js';
3
+ import { C as CachedJwk, H as HttpProvider, a as CryptoProvider, b as ClockProvider, c as CacheProvider } from './config-I0GIVJA_.js';
4
+ export { A as AuthrimServerConfig, E as EcPublicJwk, J as JwkKeyType, d as JwkKeyUse, e as JwkSet, f as JwkSigningAlgorithm, M as MemoryCacheOptions, O as OkpPublicJwk, P as PublicJwk, R as ResolvedAuthrimServerConfig, g as RsaPublicJwk } from './config-I0GIVJA_.js';
5
+
6
+ /**
7
+ * Authrim Server SDK Error Types
8
+ *
9
+ * These error codes are specific to server-side token validation and DPoP operations.
10
+ */
11
+ /**
12
+ * Server SDK error codes
13
+ */
14
+ type AuthrimServerErrorCode = 'invalid_token' | 'token_expired' | 'token_not_yet_valid' | 'token_malformed' | 'signature_invalid' | 'algorithm_mismatch' | 'invalid_issuer' | 'invalid_audience' | 'jwks_fetch_error' | 'jwks_key_not_found' | 'jwks_key_ambiguous' | 'jwks_key_import_error' | 'dpop_proof_missing' | 'dpop_proof_invalid' | 'dpop_proof_signature_invalid' | 'dpop_method_mismatch' | 'dpop_uri_mismatch' | 'dpop_ath_mismatch' | 'dpop_binding_mismatch' | 'dpop_iat_expired' | 'dpop_nonce_required' | 'introspection_error' | 'revocation_error' | 'configuration_error' | 'provider_error' | 'network_error' | 'timeout_error';
15
+ /**
16
+ * Error metadata for recovery information
17
+ */
18
+ interface AuthrimServerErrorMeta {
19
+ /** HTTP status code to return */
20
+ httpStatus: number;
21
+ /** Whether this is a transient error */
22
+ transient: boolean;
23
+ /** Whether automatic retry is possible */
24
+ retryable: boolean;
25
+ /** WWW-Authenticate error attribute */
26
+ wwwAuthenticateError?: string;
27
+ }
28
+ /**
29
+ * Options for creating an AuthrimServerError
30
+ */
31
+ interface AuthrimServerErrorOptions {
32
+ details?: Record<string, unknown>;
33
+ cause?: Error;
34
+ }
35
+ /**
36
+ * Authrim Server SDK Error class
37
+ */
38
+ declare class AuthrimServerError extends Error {
39
+ /** Error code for programmatic handling */
40
+ readonly code: AuthrimServerErrorCode;
41
+ /** Additional error details */
42
+ readonly details?: Record<string, unknown>;
43
+ /** Underlying cause */
44
+ readonly cause?: Error;
45
+ constructor(code: AuthrimServerErrorCode, message: string, options?: AuthrimServerErrorOptions);
46
+ /**
47
+ * Get error metadata for HTTP response
48
+ */
49
+ get meta(): AuthrimServerErrorMeta;
50
+ }
51
+ /**
52
+ * Get error metadata for a given error code
53
+ */
54
+ declare function getServerErrorMeta(code: AuthrimServerErrorCode): AuthrimServerErrorMeta;
55
+
56
+ /**
57
+ * Session Management Type Definitions
58
+ *
59
+ * OpenID Connect Back-Channel Logout 1.0
60
+ * https://openid.net/specs/openid-connect-backchannel-1_0.html
61
+ */
62
+ /**
63
+ * Logout token claims (for back-channel logout)
64
+ *
65
+ * Per OIDC Back-Channel Logout 1.0 Section 2.4, the logout token MUST contain:
66
+ * - iss: Issuer Identifier
67
+ * - aud: Audience (one or more)
68
+ * - iat: Issued At
69
+ * - exp: Expiration Time
70
+ * - jti: JWT ID (unique identifier)
71
+ * - events: MUST contain "http://schemas.openid.net/event/backchannel-logout" key
72
+ * - sub and/or sid: At least one MUST be present
73
+ *
74
+ * The logout token MUST NOT contain:
75
+ * - nonce claim (to prevent confusion with ID tokens)
76
+ */
77
+ interface LogoutTokenClaims {
78
+ /** Issuer */
79
+ iss: string;
80
+ /** Subject (optional, but either sub or sid must be present) */
81
+ sub?: string;
82
+ /** Audience (one or more client_ids) */
83
+ aud: string | string[];
84
+ /** Issued at time (Unix timestamp) */
85
+ iat: number;
86
+ /** Expiration time (Unix timestamp) - REQUIRED per Section 2.4 */
87
+ exp: number;
88
+ /** JWT ID (unique identifier for replay protection) */
89
+ jti: string;
90
+ /**
91
+ * Events claim
92
+ * MUST contain the back-channel logout event with an empty object value
93
+ */
94
+ events: {
95
+ 'http://schemas.openid.net/event/backchannel-logout': Record<string, never>;
96
+ };
97
+ /** Session ID (optional, but either sub or sid must be present) */
98
+ sid?: string;
99
+ }
100
+
101
+ /**
102
+ * Core Authentication Function (Framework-Agnostic)
103
+ *
104
+ * This function is the ONLY authentication logic.
105
+ * Framework adapters are thin wrappers that:
106
+ * 1. Extract headers/method/url from framework-specific request
107
+ * 2. Call authenticateRequest()
108
+ * 3. Attach result to framework-specific context
109
+ *
110
+ * Header normalization:
111
+ * - All header names are normalized to lowercase internally
112
+ * - If multiple Authorization headers exist, only the first is used
113
+ * - DPoP header lookup is case-insensitive
114
+ */
115
+
116
+ /**
117
+ * Authenticate a request
118
+ *
119
+ * @param server - AuthrimServer instance
120
+ * @param request - Framework-agnostic request
121
+ * @returns Authentication result
122
+ */
123
+ declare function authenticateRequest(server: AuthrimServer, request: AuthenticateRequest): Promise<AuthenticateResult>;
124
+
125
+ /**
126
+ * JWKS Key Selection Algorithm
127
+ *
128
+ * This algorithm MUST be implemented identically across all language SDKs.
129
+ *
130
+ * 1. If token header contains `kid`:
131
+ * a. Find key where key.kid === header.kid AND key.use === 'sig' (or undefined)
132
+ * b. If not found AND cache is stale, refresh JWKS and retry ONCE
133
+ * c. If still not found, return error: jwks_key_not_found
134
+ *
135
+ * 2. If no `kid` in token header:
136
+ * a. Filter keys by: key.alg === header.alg AND key.use === 'sig' (or undefined)
137
+ * b. If exactly ONE key matches, use it
138
+ * c. If ZERO or MORE THAN ONE keys match, return error: jwks_key_ambiguous
139
+ *
140
+ * 3. Algorithm mismatch:
141
+ * - If key.alg is present AND key.alg !== header.alg, skip the key
142
+ *
143
+ * 4. Cache behavior:
144
+ * - Default TTL: 1 hour
145
+ * - Stale-while-revalidate: NOT implemented (fail-closed)
146
+ * - Thundering herd: Use single-flight pattern (one concurrent fetch per issuer)
147
+ *
148
+ * 5. Cache-Control header:
149
+ * - SHOULD be respected if present
150
+ * - max-age takes precedence over default TTL
151
+ */
152
+
153
+ /**
154
+ * Key selection result
155
+ */
156
+ interface KeySelectionResult {
157
+ key: CachedJwk | null;
158
+ error: AuthrimServerError | null;
159
+ needsRefresh: boolean;
160
+ }
161
+ /**
162
+ * Select a key by kid (Key ID)
163
+ *
164
+ * @param keys - Available keys
165
+ * @param kid - Key ID from token header
166
+ * @param alg - Algorithm from token header
167
+ * @returns KeySelectionResult
168
+ */
169
+ declare function selectKeyByKid(keys: CachedJwk[], kid: string, alg: string): KeySelectionResult;
170
+ /**
171
+ * Select a key by algorithm (when no kid is present)
172
+ *
173
+ * @param keys - Available keys
174
+ * @param alg - Algorithm from token header
175
+ * @returns KeySelectionResult
176
+ */
177
+ declare function selectKeyByAlgorithm(keys: CachedJwk[], alg: string): KeySelectionResult;
178
+ /**
179
+ * Select a key from JWKS based on token header
180
+ *
181
+ * @param keys - Available keys
182
+ * @param header - JWT header
183
+ * @returns KeySelectionResult
184
+ */
185
+ declare function selectKey(keys: CachedJwk[], header: JwtHeader): KeySelectionResult;
186
+
187
+ /**
188
+ * JWKS Manager
189
+ *
190
+ * Handles JWKS fetching, caching, and key rotation.
191
+ */
192
+
193
+ /**
194
+ * JWKS Manager configuration
195
+ */
196
+ interface JwksManagerConfig {
197
+ /** JWKS endpoint URL */
198
+ jwksUri: string;
199
+ /** Cache TTL in milliseconds */
200
+ cacheTtlMs: number;
201
+ /** HTTP provider */
202
+ http: HttpProvider;
203
+ /** Crypto provider */
204
+ crypto: CryptoProvider;
205
+ /** Clock provider */
206
+ clock: ClockProvider;
207
+ /** Cache provider */
208
+ cache: CacheProvider<CachedJwk[]>;
209
+ /**
210
+ * Optional callback for key import warnings
211
+ * Called when a key fails to import (may be encryption key, unsupported algorithm, etc.)
212
+ */
213
+ onKeyImportWarning?: (warning: KeyImportWarning) => void;
214
+ /**
215
+ * Allow redirects to different hosts (default: false)
216
+ *
217
+ * SECURITY: By default, JWKS fetches will fail if redirected to a different host
218
+ * to prevent SSRF attacks. Only enable this if you explicitly trust the issuer
219
+ * to redirect to arbitrary hosts.
220
+ */
221
+ allowCrossOriginRedirect?: boolean;
222
+ }
223
+ /**
224
+ * Key import warning information
225
+ */
226
+ interface KeyImportWarning {
227
+ /** Key ID (if present) */
228
+ kid?: string;
229
+ /** Key type */
230
+ kty: string;
231
+ /** Algorithm (if present) */
232
+ alg?: string;
233
+ /** Reason for failure */
234
+ reason: 'unsupported_algorithm' | 'import_failed' | 'unknown_key_type';
235
+ /** Error message */
236
+ message: string;
237
+ }
238
+ /**
239
+ * JWKS Manager
240
+ *
241
+ * Features:
242
+ * - Automatic JWKS fetching and caching
243
+ * - Key rotation handling (retry on kid not found)
244
+ * - Single-flight pattern (one concurrent fetch per issuer)
245
+ * - Cache-Control header support
246
+ */
247
+ declare class JwksManager {
248
+ private readonly config;
249
+ private readonly cacheKey;
250
+ private inFlight;
251
+ constructor(config: JwksManagerConfig);
252
+ /**
253
+ * Get a key for verifying a JWT
254
+ *
255
+ * Implements the key selection algorithm with automatic refresh on key not found.
256
+ *
257
+ * @param header - JWT header
258
+ * @returns Selected key or error
259
+ */
260
+ getKey(header: JwtHeader): Promise<KeySelectionResult>;
261
+ /**
262
+ * Get cached keys or fetch if not available
263
+ */
264
+ private getKeys;
265
+ /**
266
+ * Fetch JWKS and cache keys
267
+ *
268
+ * Uses single-flight pattern to prevent thundering herd.
269
+ */
270
+ private fetchAndCacheKeys;
271
+ /**
272
+ * Actually fetch and cache keys
273
+ */
274
+ private doFetchAndCache;
275
+ /**
276
+ * Determine the algorithm for a JWK
277
+ */
278
+ private determineAlgorithm;
279
+ /**
280
+ * Maximum cache TTL (24 hours) to prevent overflow and unreasonable cache times
281
+ */
282
+ private static readonly MAX_CACHE_TTL_MS;
283
+ /**
284
+ * Parse Cache-Control header for max-age
285
+ *
286
+ * @param header - Cache-Control header value
287
+ * @returns TTL in milliseconds
288
+ */
289
+ private parseCacheControl;
290
+ /**
291
+ * Invalidate cached keys
292
+ */
293
+ invalidate(): void;
294
+ }
295
+
296
+ /**
297
+ * JWT Signature Verification
298
+ *
299
+ * RFC 7519 - JSON Web Token (JWT)
300
+ *
301
+ * This module handles ONLY cryptographic signature verification.
302
+ * Claims validation is handled separately in validate-claims.ts.
303
+ */
304
+
305
+ /**
306
+ * Parse a JWT without verification
307
+ *
308
+ * @param token - JWT string
309
+ * @returns Parsed JWT structure
310
+ * @throws Error if JWT format is invalid
311
+ * @throws InsecureAlgorithmError if JWT uses alg: none
312
+ */
313
+ declare function parseJwt<T = Record<string, unknown>>(token: string): ParsedJwt<T>;
314
+ /**
315
+ * Verify JWT signature
316
+ *
317
+ * @param token - JWT string
318
+ * @param key - CryptoKey for verification
319
+ * @param crypto - Crypto provider
320
+ * @returns Parsed JWT if signature is valid, null otherwise
321
+ */
322
+ declare function verifyJwtSignature<T = Record<string, unknown>>(token: string, key: CryptoKey, crypto: CryptoProvider): Promise<ParsedJwt<T> | null>;
323
+
324
+ /**
325
+ * JWT Claims Validation
326
+ *
327
+ * RFC 7519 - JSON Web Token (JWT)
328
+ *
329
+ * This module handles claims validation (iss, aud, exp, nbf, iat).
330
+ * Signature verification is handled separately in verify-jwt.ts.
331
+ */
332
+
333
+ /**
334
+ * Validate JWT claims
335
+ *
336
+ * Validates:
337
+ * - iss (issuer) - must match expected issuer
338
+ * - aud (audience) - must include expected audience
339
+ * - exp (expiration) - must not be expired (with tolerance)
340
+ * - nbf (not before) - must be past nbf (with tolerance)
341
+ * - iat (issued at) - must not be in the future (with tolerance)
342
+ *
343
+ * For ID Token validation (OIDC Core 1.0 Section 3.1.3.7), set:
344
+ * - requireExp: true
345
+ * - requireIat: true
346
+ *
347
+ * @param payload - JWT payload containing claims
348
+ * @param options - Validation options
349
+ * @returns Validation result
350
+ */
351
+ declare function validateClaims(payload: StandardClaims, options: ClaimsValidationOptions): ClaimsValidationResult;
352
+ /**
353
+ * Calculate time remaining until token expiration
354
+ *
355
+ * @param exp - Expiration timestamp (Unix seconds)
356
+ * @param now - Current timestamp (Unix seconds)
357
+ * @returns Seconds until expiration, or undefined if no exp claim
358
+ */
359
+ declare function getExpiresIn(exp: number | undefined, now: number): number | undefined;
360
+
361
+ /**
362
+ * Token Validator
363
+ *
364
+ * Orchestrates JWT signature verification and claims validation.
365
+ */
366
+
367
+ /**
368
+ * Token Validator configuration
369
+ */
370
+ interface TokenValidatorConfig {
371
+ /** JWKS Manager */
372
+ jwksManager: JwksManager;
373
+ /** Crypto provider */
374
+ crypto: CryptoProvider;
375
+ /** Clock provider */
376
+ clock: ClockProvider;
377
+ /** Validation options */
378
+ options: TokenValidationOptions;
379
+ }
380
+ /**
381
+ * Token Validator
382
+ *
383
+ * Combines JWKS key retrieval, signature verification, and claims validation.
384
+ */
385
+ declare class TokenValidator {
386
+ private readonly config;
387
+ constructor(config: TokenValidatorConfig);
388
+ /**
389
+ * Validate a JWT access token
390
+ *
391
+ * Steps:
392
+ * 1. Parse JWT structure
393
+ * 2. Get signing key from JWKS
394
+ * 3. Verify signature
395
+ * 4. Validate claims (iss, aud, exp, nbf, iat)
396
+ *
397
+ * @param token - JWT string
398
+ * @returns Validation result
399
+ */
400
+ validate(token: string): Promise<TokenValidationResult>;
401
+ /**
402
+ * Validate required scopes
403
+ */
404
+ private validateScopes;
405
+ }
406
+
407
+ /**
408
+ * Token Introspection (RFC 7662)
409
+ *
410
+ * OAuth 2.0 Token Introspection
411
+ */
412
+
413
+ /**
414
+ * Introspection client configuration
415
+ */
416
+ interface IntrospectionClientConfig {
417
+ /** Introspection endpoint URL */
418
+ endpoint: string;
419
+ /** Client ID */
420
+ clientId: string;
421
+ /** Client secret */
422
+ clientSecret: string;
423
+ /** HTTP provider */
424
+ http: HttpProvider;
425
+ }
426
+ /**
427
+ * Token Introspection Client
428
+ *
429
+ * Calls the authorization server's introspection endpoint to check token validity.
430
+ */
431
+ declare class IntrospectionClient {
432
+ private readonly config;
433
+ constructor(config: IntrospectionClientConfig);
434
+ /**
435
+ * Introspect a token
436
+ *
437
+ * @param request - Introspection request
438
+ * @returns Introspection response
439
+ */
440
+ introspect(request: IntrospectionRequest): Promise<IntrospectionResponse>;
441
+ }
442
+
443
+ /**
444
+ * Token Revocation (RFC 7009)
445
+ *
446
+ * OAuth 2.0 Token Revocation
447
+ */
448
+
449
+ /**
450
+ * Revocation client configuration
451
+ */
452
+ interface RevocationClientConfig {
453
+ /** Revocation endpoint URL */
454
+ endpoint: string;
455
+ /** Client ID */
456
+ clientId: string;
457
+ /** Client secret */
458
+ clientSecret: string;
459
+ /** HTTP provider */
460
+ http: HttpProvider;
461
+ }
462
+ /**
463
+ * Token Revocation Client
464
+ *
465
+ * Calls the authorization server's revocation endpoint to invalidate tokens.
466
+ */
467
+ declare class RevocationClient {
468
+ private readonly config;
469
+ constructor(config: RevocationClientConfig);
470
+ /**
471
+ * Revoke a token
472
+ *
473
+ * Note: Per RFC 7009, a successful response (200) does not guarantee
474
+ * the token was revoked. The server may silently ignore invalid tokens.
475
+ *
476
+ * @param request - Revocation request
477
+ */
478
+ revoke(request: RevocationRequest): Promise<void>;
479
+ }
480
+
481
+ /**
482
+ * DPoP Proof Validator (RFC 9449)
483
+ *
484
+ * IMPORTANT: This SDK validates DPoP proofs STATELESSLY.
485
+ *
486
+ * What this SDK validates:
487
+ * - Proof signature (embedded JWK in header)
488
+ * - htm (HTTP method) matches request
489
+ * - htu (HTTP URI) matches request
490
+ * - ath (access token hash) if present
491
+ * - cnf.jkt binding (thumbprint matches)
492
+ * - iat is within acceptable window
493
+ *
494
+ * What this SDK does NOT validate:
495
+ * - jti uniqueness (replay detection)
496
+ * → MUST be implemented by the resource server if required
497
+ * → Recommended: Store jti with TTL = proof lifetime + clock tolerance
498
+ *
499
+ * Nonce handling:
500
+ * - If server returns use_dpop_nonce error, SDK returns dpop_nonce_required
501
+ * - Application is responsible for retry with nonce
502
+ */
503
+
504
+ /**
505
+ * DPoP Proof Validator
506
+ */
507
+ declare class DPoPValidator {
508
+ private readonly crypto;
509
+ private readonly clock;
510
+ constructor(crypto: CryptoProvider, clock: ClockProvider);
511
+ /**
512
+ * Validate a DPoP proof
513
+ *
514
+ * @param proof - DPoP proof JWT
515
+ * @param options - Validation options
516
+ * @returns Validation result
517
+ */
518
+ validate(proof: string, options: DPoPValidationOptions): Promise<DPoPValidationResult>;
519
+ /**
520
+ * Validate DPoP header
521
+ */
522
+ private validateHeader;
523
+ /**
524
+ * Validate DPoP payload structure
525
+ */
526
+ private validatePayloadStructure;
527
+ /**
528
+ * Verify DPoP proof signature
529
+ */
530
+ private verifySignature;
531
+ /**
532
+ * Validate access token hash (ath claim)
533
+ *
534
+ * Per RFC 9449 Section 4.2:
535
+ * When the DPoP proof is used with an access token, the ath claim MUST be present
536
+ * and contain the base64url-encoded SHA-256 hash of the access token.
537
+ */
538
+ private validateAccessTokenHash;
539
+ }
540
+
541
+ /**
542
+ * JWK Thumbprint (RFC 7638)
543
+ *
544
+ * Computes a hash of a JWK for use as a key identifier.
545
+ */
546
+
547
+ /**
548
+ * Calculate JWK thumbprint
549
+ *
550
+ * Per RFC 7638, the thumbprint is computed as:
551
+ * 1. Construct a JSON object with only the required members, in lexicographic order
552
+ * 2. Compute SHA-256 hash of the UTF-8 encoding of the JSON
553
+ * 3. Base64url encode the hash
554
+ *
555
+ * @param jwk - JSON Web Key
556
+ * @param crypto - Crypto provider
557
+ * @returns Base64url-encoded thumbprint
558
+ */
559
+ declare function calculateJwkThumbprint(jwk: JsonWebKey, crypto: CryptoProvider): Promise<string>;
560
+ /**
561
+ * Verify that a JWK thumbprint matches the expected value
562
+ *
563
+ * @param jwk - JSON Web Key to verify
564
+ * @param expectedThumbprint - Expected thumbprint value
565
+ * @param crypto - Crypto provider
566
+ * @returns true if thumbprints match
567
+ */
568
+ declare function verifyJwkThumbprint(jwk: JsonWebKey, expectedThumbprint: string, crypto: CryptoProvider): Promise<boolean>;
569
+
570
+ /**
571
+ * Base64URL Encoding/Decoding Utilities
572
+ *
573
+ * RFC 4648 Section 5 - Base64 Encoding with URL and Filename Safe Alphabet
574
+ */
575
+ /**
576
+ * Encode bytes to base64url string
577
+ *
578
+ * @param data - Bytes to encode
579
+ * @returns Base64url-encoded string (no padding)
580
+ */
581
+ declare function base64UrlEncode(data: Uint8Array): string;
582
+ /**
583
+ * Decode base64url string to bytes
584
+ *
585
+ * @param str - Base64url-encoded string
586
+ * @returns Decoded bytes
587
+ */
588
+ declare function base64UrlDecode(str: string): Uint8Array;
589
+ /**
590
+ * Encode string to base64url
591
+ *
592
+ * @param str - String to encode (UTF-8)
593
+ * @returns Base64url-encoded string
594
+ */
595
+ declare function base64UrlEncodeString(str: string): string;
596
+ /**
597
+ * Decode base64url to string
598
+ *
599
+ * @param str - Base64url-encoded string
600
+ * @returns Decoded string (UTF-8)
601
+ */
602
+ declare function base64UrlDecodeString(str: string): string;
603
+
604
+ /**
605
+ * HTTP Error Response Utilities
606
+ *
607
+ * Helpers for building OAuth 2.0 / RFC 6750 compliant error responses.
608
+ */
609
+
610
+ /**
611
+ * OAuth 2.0 error response body
612
+ */
613
+ interface ErrorResponseBody {
614
+ error: string;
615
+ error_description?: string;
616
+ }
617
+ /**
618
+ * Build an error response body from an AuthrimServerError
619
+ *
620
+ * @param error - The error to convert
621
+ * @returns Error response body
622
+ */
623
+ declare function buildErrorResponse(error: AuthrimServerError): ErrorResponseBody;
624
+ /**
625
+ * Build WWW-Authenticate header value (RFC 6750)
626
+ *
627
+ * @param error - The error
628
+ * @param realm - Optional realm value
629
+ * @param scheme - Authentication scheme ('Bearer' or 'DPoP')
630
+ * @returns WWW-Authenticate header value
631
+ */
632
+ declare function buildWwwAuthenticateHeader(error: AuthrimServerError, realm?: string, scheme?: 'Bearer' | 'DPoP'): string;
633
+ /**
634
+ * Build error headers for HTTP response
635
+ *
636
+ * @param error - The error
637
+ * @param options - Options for header building
638
+ * @returns Headers object
639
+ */
640
+ declare function buildErrorHeaders(error: AuthrimServerError, options?: {
641
+ realm?: string;
642
+ scheme?: 'Bearer' | 'DPoP';
643
+ dpopNonce?: string;
644
+ }): Record<string, string>;
645
+
646
+ /**
647
+ * Back-Channel Logout Validator
648
+ *
649
+ * Implements OpenID Connect Back-Channel Logout 1.0
650
+ * https://openid.net/specs/openid-connect-backchannel-1_0.html
651
+ *
652
+ * Back-channel logout allows the OP to notify RPs of logout events
653
+ * via direct HTTP calls (server-to-server).
654
+ *
655
+ * NOTE: This validator performs claims validation only.
656
+ * JWT signature verification MUST be performed separately using JWKS.
657
+ */
658
+
659
+ /**
660
+ * Back-channel logout event URI
661
+ */
662
+ declare const BACKCHANNEL_LOGOUT_EVENT = "http://schemas.openid.net/event/backchannel-logout";
663
+ /**
664
+ * Back-channel logout validation error codes
665
+ */
666
+ type BackChannelLogoutErrorCode = 'invalid_format' | 'insecure_algorithm' | 'invalid_issuer' | 'invalid_audience' | 'invalid_events' | 'token_expired' | 'iat_too_old' | 'not_yet_valid' | 'missing_sub_and_sid' | 'sub_mismatch' | 'sid_mismatch' | 'missing_jti' | 'nonce_present';
667
+ /**
668
+ * Options for validating a logout token
669
+ */
670
+ interface BackChannelLogoutValidationOptions {
671
+ /** Expected issuer */
672
+ issuer: string;
673
+ /** Expected audience (client_id) */
674
+ audience: string;
675
+ /** Maximum age in seconds (default: 60) */
676
+ maxAge?: number;
677
+ /** Clock skew tolerance in seconds (default: 30) */
678
+ clockSkew?: number;
679
+ /** Expected session ID (optional) */
680
+ expectedSid?: string;
681
+ /** Expected subject (optional) */
682
+ expectedSub?: string;
683
+ }
684
+ /**
685
+ * Result of back-channel logout token validation
686
+ */
687
+ interface BackChannelLogoutValidationResult {
688
+ /** Whether the token is valid */
689
+ valid: boolean;
690
+ /** Validated claims (if valid) */
691
+ claims?: LogoutTokenClaims;
692
+ /** JWT header (if valid) */
693
+ header?: JwtHeader;
694
+ /** Error message (if invalid) */
695
+ error?: string;
696
+ /** Error code (if invalid) */
697
+ errorCode?: BackChannelLogoutErrorCode;
698
+ }
699
+ /**
700
+ * Back-Channel Logout Validator
701
+ *
702
+ * Validates logout_token JWTs per OIDC Back-Channel Logout 1.0.
703
+ *
704
+ * ## Security Notes
705
+ *
706
+ * 1. **JWT Signature Verification**: This class performs claims validation only.
707
+ * JWT signature verification MUST be performed separately using JWKS
708
+ * before calling validate(). The caller MUST reject tokens with alg: none.
709
+ *
710
+ * 2. **Algorithm Validation**: Per Section 2.6, "alg with the value none MUST NOT
711
+ * be used". This validator explicitly rejects alg: none tokens.
712
+ *
713
+ * 3. **JTI Replay Protection**: This validator checks for jti presence only.
714
+ * The application MUST implement jti replay protection by:
715
+ * - Storing used jti values (at least until token expiry + clock skew)
716
+ * - Rejecting tokens with previously-used jti values
717
+ *
718
+ * 4. **Expiration Validation**: Per Section 2.4, exp is REQUIRED. This validator
719
+ * checks that the token has not expired (with clock skew tolerance).
720
+ *
721
+ * Usage (Node.js server receiving back-channel logout request):
722
+ * ```typescript
723
+ * // 1. Receive logout_token from POST body
724
+ * const logoutToken = req.body.logout_token;
725
+ *
726
+ * // 2. Verify JWT signature using JWKS (MUST reject alg: none)
727
+ * const jwks = await jwksManager.getJwks();
728
+ * const verified = await verifyJwtSignature(logoutToken, key, crypto);
729
+ * if (!verified) {
730
+ * return res.status(400).send('Invalid signature');
731
+ * }
732
+ *
733
+ * // 3. Validate claims (includes alg: none rejection)
734
+ * const validator = new BackChannelLogoutValidator();
735
+ * const result = validator.validate(logoutToken, {
736
+ * issuer: 'https://op.example.com',
737
+ * audience: 'my-client-id'
738
+ * });
739
+ *
740
+ * if (!result.valid) {
741
+ * return res.status(400).send('Invalid logout token');
742
+ * }
743
+ *
744
+ * // 4. Check for jti replay (application responsibility)
745
+ * if (await jtiStore.has(result.claims.jti)) {
746
+ * return res.status(400).send('Token replay detected');
747
+ * }
748
+ * await jtiStore.set(result.claims.jti, true, result.claims.exp + clockSkew);
749
+ *
750
+ * // 5. Perform logout for sub and/or sid
751
+ * await logoutUser(result.claims.sub, result.claims.sid);
752
+ * ```
753
+ */
754
+ declare class BackChannelLogoutValidator {
755
+ /**
756
+ * Validate a logout_token
757
+ *
758
+ * Per OIDC Back-Channel Logout 1.0 Section 2.4 and 2.6, the logout_token MUST:
759
+ * - Be a valid JWT with alg != "none"
760
+ * - Contain iss, aud, iat, exp, jti claims
761
+ * - Contain events claim with back-channel logout event
762
+ * - Contain either sub or sid (or both)
763
+ * - NOT contain a nonce claim
764
+ * - NOT be expired (exp validation)
765
+ *
766
+ * @param logoutToken - JWT logout token to validate
767
+ * @param options - Validation options
768
+ * @returns Validation result
769
+ */
770
+ validate(logoutToken: string, options: BackChannelLogoutValidationOptions): BackChannelLogoutValidationResult;
771
+ /**
772
+ * Extract claims from a logout token without validation
773
+ *
774
+ * Useful for inspecting the token before/during validation.
775
+ *
776
+ * @param logoutToken - JWT logout token
777
+ * @returns Claims or null if invalid format
778
+ */
779
+ extractClaims(logoutToken: string): LogoutTokenClaims | null;
780
+ /**
781
+ * Extract header from a logout token without validation
782
+ *
783
+ * Useful for getting kid to select the correct JWKS key.
784
+ *
785
+ * @param logoutToken - JWT logout token
786
+ * @returns Header or null if invalid format
787
+ */
788
+ extractHeader(logoutToken: string): JwtHeader | null;
789
+ }
790
+
791
+ export { AuthenticateRequest, AuthenticateResult, AuthrimServer, AuthrimServerError, type AuthrimServerErrorCode, type AuthrimServerErrorMeta, type AuthrimServerErrorOptions, BACKCHANNEL_LOGOUT_EVENT, type BackChannelLogoutErrorCode, type BackChannelLogoutValidationOptions, type BackChannelLogoutValidationResult, BackChannelLogoutValidator, ClaimsValidationOptions, ClaimsValidationResult, DPoPValidationOptions, DPoPValidationResult, DPoPValidator, IntrospectionClient, type IntrospectionClientConfig, IntrospectionRequest, IntrospectionResponse, JwksManager, type JwksManagerConfig, JwtHeader, type KeyImportWarning, type LogoutTokenClaims, ParsedJwt, RevocationClient, type RevocationClientConfig, RevocationRequest, StandardClaims, TokenValidationOptions, TokenValidationResult, TokenValidator, type TokenValidatorConfig, authenticateRequest, base64UrlDecode, base64UrlDecodeString, base64UrlEncode, base64UrlEncodeString, buildErrorHeaders, buildErrorResponse, buildWwwAuthenticateHeader, calculateJwkThumbprint, getExpiresIn, getServerErrorMeta, parseJwt, selectKey, selectKeyByAlgorithm, selectKeyByKid, validateClaims, verifyJwkThumbprint, verifyJwtSignature };