@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 @@
1
+ {"version":3,"sources":["../src/providers-impl/fetch-http.ts","../src/utils/base64url.ts","../src/providers-impl/web-crypto.ts","../src/providers-impl/system-clock.ts","../src/providers-impl/memory-cache.ts"],"names":["fetchHttpProvider","input","init","base64UrlEncode","data","base64","binary","byte","base64UrlDecode","str","paddingNeeded","bytes","i","base64UrlEncodeString","base64UrlDecodeString","ALGORITHM_PARAMS","getVerifyParams","alg","params","getThumbprintMembers","jwk","kty","webCryptoProvider","crypto","key","signature","hash","members","json","systemClock","memoryCache","options","ttlMs","maxSize","cache","cleanup","now","keysToDelete","entry","excess","keysIterator","result","value","entryTtlMs","oldestKey","expiresAt"],"mappings":"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","file":"chunk-OS567YCE.js","sourcesContent":["/**\r\n * Fetch-based HTTP Provider Implementation\r\n *\r\n * Uses globalThis.fetch for maximum runtime compatibility.\r\n */\r\n\r\nimport type { HttpProvider } from '../providers/http.js';\r\n\r\n/**\r\n * Create a fetch-based HTTP provider\r\n *\r\n * This implementation uses the global fetch API which is available in:\r\n * - Node.js 18+\r\n * - Bun\r\n * - Deno\r\n * - Cloudflare Workers\r\n * - Vercel Edge Functions\r\n * - All modern browsers\r\n *\r\n * @returns HttpProvider implementation\r\n */\r\nexport function fetchHttpProvider(): HttpProvider {\r\n return {\r\n fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response> {\r\n return globalThis.fetch(input, init);\r\n },\r\n };\r\n}\r\n","/**\r\n * Base64URL Encoding/Decoding Utilities\r\n *\r\n * RFC 4648 Section 5 - Base64 Encoding with URL and Filename Safe Alphabet\r\n */\r\n\r\n/**\r\n * Encode bytes to base64url string\r\n *\r\n * @param data - Bytes to encode\r\n * @returns Base64url-encoded string (no padding)\r\n */\r\nexport function base64UrlEncode(data: Uint8Array): string {\r\n // Convert to base64\r\n let base64: string;\r\n if (typeof Buffer !== 'undefined') {\r\n // Node.js\r\n base64 = Buffer.from(data).toString('base64');\r\n } else {\r\n // Browser/Edge runtime\r\n const binary = Array.from(data)\r\n .map((byte) => String.fromCharCode(byte))\r\n .join('');\r\n base64 = btoa(binary);\r\n }\r\n\r\n // Convert to base64url (replace + with -, / with _, remove padding)\r\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\r\n}\r\n\r\n/**\r\n * Decode base64url string to bytes\r\n *\r\n * @param str - Base64url-encoded string\r\n * @returns Decoded bytes\r\n */\r\nexport function base64UrlDecode(str: string): Uint8Array {\r\n // Convert from base64url to base64\r\n let base64 = str.replace(/-/g, '+').replace(/_/g, '/');\r\n\r\n // Add padding if needed\r\n const paddingNeeded = (4 - (base64.length % 4)) % 4;\r\n base64 += '='.repeat(paddingNeeded);\r\n\r\n // Decode\r\n if (typeof Buffer !== 'undefined') {\r\n // Node.js\r\n return new Uint8Array(Buffer.from(base64, 'base64'));\r\n } else {\r\n // Browser/Edge runtime\r\n const binary = atob(base64);\r\n const bytes = new Uint8Array(binary.length);\r\n for (let i = 0; i < binary.length; i++) {\r\n bytes[i] = binary.charCodeAt(i);\r\n }\r\n return bytes;\r\n }\r\n}\r\n\r\n/**\r\n * Encode string to base64url\r\n *\r\n * @param str - String to encode (UTF-8)\r\n * @returns Base64url-encoded string\r\n */\r\nexport function base64UrlEncodeString(str: string): string {\r\n return base64UrlEncode(new TextEncoder().encode(str));\r\n}\r\n\r\n/**\r\n * Decode base64url to string\r\n *\r\n * @param str - Base64url-encoded string\r\n * @returns Decoded string (UTF-8)\r\n */\r\nexport function base64UrlDecodeString(str: string): string {\r\n return new TextDecoder().decode(base64UrlDecode(str));\r\n}\r\n","/**\r\n * Web Crypto API Provider Implementation\r\n *\r\n * Uses crypto.subtle for cryptographic operations.\r\n */\r\n\r\nimport type { CryptoProvider } from '../providers/crypto.js';\r\nimport { base64UrlEncode } from '../utils/base64url.js';\r\n\r\n/**\r\n * Algorithm parameters mapping\r\n */\r\nconst ALGORITHM_PARAMS: Record<string, AlgorithmIdentifier | RsaHashedImportParams | EcKeyImportParams> = {\r\n // RSA PKCS#1 v1.5\r\n RS256: { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-256' },\r\n RS384: { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-384' },\r\n RS512: { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-512' },\r\n // RSA-PSS\r\n PS256: { name: 'RSA-PSS', hash: 'SHA-256' },\r\n PS384: { name: 'RSA-PSS', hash: 'SHA-384' },\r\n PS512: { name: 'RSA-PSS', hash: 'SHA-512' },\r\n // ECDSA\r\n ES256: { name: 'ECDSA', namedCurve: 'P-256' },\r\n ES384: { name: 'ECDSA', namedCurve: 'P-384' },\r\n ES512: { name: 'ECDSA', namedCurve: 'P-521' },\r\n};\r\n\r\n/**\r\n * Get verification algorithm parameters\r\n */\r\nfunction getVerifyParams(alg: string): AlgorithmIdentifier | RsaPssParams | EcdsaParams {\r\n const params = ALGORITHM_PARAMS[alg];\r\n if (!params) {\r\n throw new Error(`Unsupported algorithm: ${alg}`);\r\n }\r\n\r\n if (alg.startsWith('PS')) {\r\n // RSA-PSS requires salt length\r\n const hashLength = { PS256: 32, PS384: 48, PS512: 64 }[alg] ?? 32;\r\n return { name: 'RSA-PSS', saltLength: hashLength };\r\n }\r\n\r\n if (alg.startsWith('ES')) {\r\n const hashName = { ES256: 'SHA-256', ES384: 'SHA-384', ES512: 'SHA-512' }[alg] ?? 'SHA-256';\r\n return { name: 'ECDSA', hash: hashName };\r\n }\r\n\r\n return params;\r\n}\r\n\r\n/**\r\n * Get required key members for thumbprint calculation (RFC 7638)\r\n */\r\nfunction getThumbprintMembers(jwk: JsonWebKey): Record<string, unknown> {\r\n const kty = jwk.kty;\r\n\r\n switch (kty) {\r\n case 'RSA':\r\n return { e: jwk.e, kty: jwk.kty, n: jwk.n };\r\n case 'EC':\r\n return { crv: jwk.crv, kty: jwk.kty, x: jwk.x, y: jwk.y };\r\n case 'OKP':\r\n return { crv: jwk.crv, kty: jwk.kty, x: jwk.x };\r\n default:\r\n throw new Error(`Unsupported key type for thumbprint: ${kty}`);\r\n }\r\n}\r\n\r\n/**\r\n * Create a Web Crypto API-based crypto provider\r\n *\r\n * This implementation uses crypto.subtle which is available in:\r\n * - Node.js 18+\r\n * - Bun\r\n * - Deno\r\n * - Cloudflare Workers\r\n * - Vercel Edge Functions\r\n * - All modern browsers\r\n *\r\n * @returns CryptoProvider implementation\r\n */\r\nexport function webCryptoProvider(): CryptoProvider {\r\n const crypto = globalThis.crypto;\r\n\r\n return {\r\n async verifySignature(\r\n alg: string,\r\n key: CryptoKey,\r\n signature: Uint8Array,\r\n data: Uint8Array\r\n ): Promise<boolean> {\r\n const params = getVerifyParams(alg);\r\n return crypto.subtle.verify(params, key, signature as BufferSource, data as BufferSource);\r\n },\r\n\r\n async importJwk(jwk: JsonWebKey, alg: string): Promise<CryptoKey> {\r\n const params = ALGORITHM_PARAMS[alg];\r\n if (!params) {\r\n throw new Error(`Unsupported algorithm: ${alg}`);\r\n }\r\n return crypto.subtle.importKey('jwk', jwk, params, true, ['verify']);\r\n },\r\n\r\n async sha256(data: string | Uint8Array): Promise<Uint8Array> {\r\n const bytes = typeof data === 'string' ? new TextEncoder().encode(data) : data;\r\n const hash = await crypto.subtle.digest('SHA-256', bytes as BufferSource);\r\n return new Uint8Array(hash);\r\n },\r\n\r\n async calculateThumbprint(jwk: JsonWebKey): Promise<string> {\r\n // Get required members in lexicographic order (RFC 7638)\r\n const members = getThumbprintMembers(jwk);\r\n const json = JSON.stringify(members, Object.keys(members).sort());\r\n const hash = await this.sha256(json);\r\n return base64UrlEncode(hash);\r\n },\r\n };\r\n}\r\n","/**\r\n * System Clock Provider Implementation\r\n *\r\n * Uses Date.now() for time operations.\r\n */\r\n\r\nimport type { ClockProvider } from '../providers/clock.js';\r\n\r\n/**\r\n * Create a system clock provider\r\n *\r\n * Uses Date.now() which is available in all JavaScript runtimes.\r\n *\r\n * @returns ClockProvider implementation\r\n */\r\nexport function systemClock(): ClockProvider {\r\n return {\r\n nowSeconds(): number {\r\n return Math.floor(Date.now() / 1000);\r\n },\r\n\r\n nowMs(): number {\r\n return Date.now();\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Create a mock clock provider for testing\r\n *\r\n * @param initialTime - Initial time in milliseconds\r\n * @returns ClockProvider with time control methods\r\n */\r\nexport function mockClock(\r\n initialTime: number = Date.now()\r\n): ClockProvider & { advance(ms: number): void; setTime(ms: number): void } {\r\n let currentTime = initialTime;\r\n\r\n return {\r\n nowSeconds(): number {\r\n return Math.floor(currentTime / 1000);\r\n },\r\n\r\n nowMs(): number {\r\n return currentTime;\r\n },\r\n\r\n advance(ms: number): void {\r\n currentTime += ms;\r\n },\r\n\r\n setTime(ms: number): void {\r\n currentTime = ms;\r\n },\r\n };\r\n}\r\n","/**\r\n * In-Memory Cache Provider Implementation\r\n *\r\n * Simple TTL-based cache with optional size limits.\r\n */\r\n\r\nimport type { CacheProvider } from '../providers/cache.js';\r\nimport type { MemoryCacheOptions } from '../types/config.js';\r\n\r\n/**\r\n * Cache entry with expiration\r\n */\r\ninterface CacheEntry<T> {\r\n value: T;\r\n expiresAt: number;\r\n}\r\n\r\n/**\r\n * Create an in-memory cache provider\r\n *\r\n * Features:\r\n * - TTL-based expiration\r\n * - Optional size limits with LRU eviction\r\n * - Lazy cleanup on access\r\n *\r\n * @param options - Cache configuration options\r\n * @returns CacheProvider implementation\r\n */\r\nexport function memoryCache<T>(options: MemoryCacheOptions = {}): CacheProvider<T> {\r\n const { ttlMs = 3600_000, maxSize = 1000 } = options;\r\n const cache = new Map<string, CacheEntry<T>>();\r\n\r\n /**\r\n * Remove expired entries and enforce size limit\r\n */\r\n function cleanup(): void {\r\n const now = Date.now();\r\n const keysToDelete: string[] = [];\r\n\r\n for (const [key, entry] of cache.entries()) {\r\n if (entry.expiresAt <= now) {\r\n keysToDelete.push(key);\r\n }\r\n }\r\n\r\n for (const key of keysToDelete) {\r\n cache.delete(key);\r\n }\r\n\r\n // Enforce max size (LRU: oldest entries first in Map iteration order)\r\n if (cache.size > maxSize) {\r\n const excess = cache.size - maxSize;\r\n const keysIterator = cache.keys();\r\n for (let i = 0; i < excess; i++) {\r\n const result = keysIterator.next();\r\n if (!result.done) {\r\n cache.delete(result.value);\r\n }\r\n }\r\n }\r\n }\r\n\r\n return {\r\n get(key: string): T | undefined {\r\n const entry = cache.get(key);\r\n if (!entry) {\r\n return undefined;\r\n }\r\n\r\n // Check expiration\r\n if (entry.expiresAt <= Date.now()) {\r\n cache.delete(key);\r\n return undefined;\r\n }\r\n\r\n // Move to end for LRU\r\n cache.delete(key);\r\n cache.set(key, entry);\r\n\r\n return entry.value;\r\n },\r\n\r\n set(key: string, value: T, entryTtlMs?: number): void {\r\n // If key already exists, just update it\r\n if (cache.has(key)) {\r\n cache.delete(key); // Remove to reset LRU position\r\n } else if (cache.size >= maxSize) {\r\n // Need to make room for new entry\r\n cleanup();\r\n // If still at max after cleanup, remove oldest\r\n if (cache.size >= maxSize) {\r\n const oldestKey = cache.keys().next().value;\r\n if (oldestKey !== undefined) {\r\n cache.delete(oldestKey);\r\n }\r\n }\r\n }\r\n\r\n const expiresAt = Date.now() + (entryTtlMs ?? ttlMs);\r\n cache.set(key, { value, expiresAt });\r\n },\r\n\r\n delete(key: string): void {\r\n cache.delete(key);\r\n },\r\n\r\n clear(): void {\r\n cache.clear();\r\n },\r\n };\r\n}\r\n"]}
@@ -0,0 +1,2 @@
1
+ 'use strict';var u=class extends Error{constructor(t,a,e){super(a),this.name="AuthrimServerError",this.code=t,this.details=e?.details,this.cause=e?.cause;}get meta(){return c(this.code)}},h={invalid_token:{httpStatus:401,transient:false,retryable:false,wwwAuthenticateError:"invalid_token"},token_expired:{httpStatus:401,transient:false,retryable:false,wwwAuthenticateError:"invalid_token"},token_not_yet_valid:{httpStatus:401,transient:false,retryable:false,wwwAuthenticateError:"invalid_token"},token_malformed:{httpStatus:401,transient:false,retryable:false,wwwAuthenticateError:"invalid_token"},signature_invalid:{httpStatus:401,transient:false,retryable:false,wwwAuthenticateError:"invalid_token"},algorithm_mismatch:{httpStatus:401,transient:false,retryable:false,wwwAuthenticateError:"invalid_token"},invalid_issuer:{httpStatus:401,transient:false,retryable:false,wwwAuthenticateError:"invalid_token"},invalid_audience:{httpStatus:401,transient:false,retryable:false,wwwAuthenticateError:"invalid_token"},jwks_fetch_error:{httpStatus:503,transient:true,retryable:true},jwks_key_not_found:{httpStatus:401,transient:true,retryable:true,wwwAuthenticateError:"invalid_token"},jwks_key_ambiguous:{httpStatus:401,transient:false,retryable:false,wwwAuthenticateError:"invalid_token"},jwks_key_import_error:{httpStatus:500,transient:false,retryable:false},dpop_proof_missing:{httpStatus:401,transient:false,retryable:false,wwwAuthenticateError:"invalid_token"},dpop_proof_invalid:{httpStatus:401,transient:false,retryable:false,wwwAuthenticateError:"invalid_token"},dpop_proof_signature_invalid:{httpStatus:401,transient:false,retryable:false,wwwAuthenticateError:"invalid_token"},dpop_method_mismatch:{httpStatus:401,transient:false,retryable:false,wwwAuthenticateError:"invalid_token"},dpop_uri_mismatch:{httpStatus:401,transient:false,retryable:false,wwwAuthenticateError:"invalid_token"},dpop_ath_mismatch:{httpStatus:401,transient:false,retryable:false,wwwAuthenticateError:"invalid_token"},dpop_binding_mismatch:{httpStatus:401,transient:false,retryable:false,wwwAuthenticateError:"invalid_token"},dpop_iat_expired:{httpStatus:401,transient:false,retryable:false,wwwAuthenticateError:"invalid_token"},dpop_nonce_required:{httpStatus:401,transient:true,retryable:true,wwwAuthenticateError:"use_dpop_nonce"},introspection_error:{httpStatus:503,transient:true,retryable:true},revocation_error:{httpStatus:503,transient:true,retryable:true},configuration_error:{httpStatus:500,transient:false,retryable:false},provider_error:{httpStatus:500,transient:false,retryable:false},network_error:{httpStatus:503,transient:true,retryable:true},timeout_error:{httpStatus:504,transient:true,retryable:true}};function c(r){return h[r]}function _(r,t){let a=t.toLowerCase();for(let[e,n]of Object.entries(r))if(e.toLowerCase()===a)return Array.isArray(n)?n[0]:n}function f(r){if(!r)return null;let t=r.split(" ");if(t.length!==2)return null;let[a,e]=t;if(!a||!e)return null;let n=a.toLowerCase();return n==="bearer"?{scheme:"Bearer",token:e}:n==="dpop"?{scheme:"DPoP",token:e}:null}async function v(r,t){let a=_(t.headers,"Authorization"),e=f(a);if(!e)return {data:null,error:{code:"invalid_token",message:"Missing or invalid Authorization header",httpStatus:401}};let{scheme:n,token:d}=e,o=await r.validateToken(d);if(o.error){let s=new u(o.error.code,o.error.message).meta;return {data:null,error:{code:o.error.code,message:o.error.message,httpStatus:s.httpStatus}}}let i=o.data;if(!i)return {data:null,error:{code:"invalid_token",message:"Token validation failed",httpStatus:401}};let p=i.claims.cnf?.jkt!==void 0;if(n==="DPoP"||p){let s=_(t.headers,"DPoP");if(!s)return {data:null,error:{code:"dpop_proof_missing",message:"DPoP proof required but not provided",httpStatus:401}};let l=await r.validateDPoP(s,{method:t.method,uri:t.url,accessToken:d,expectedThumbprint:i.claims.cnf?.jkt});if(!l.valid)return {data:null,error:{code:l.errorCode??"dpop_proof_invalid",message:l.errorMessage??"Invalid DPoP proof",httpStatus:401}}}return {data:{claims:i,tokenType:p?"DPoP":"Bearer"},error:null}}exports.a=u;exports.b=c;exports.c=v;//# sourceMappingURL=chunk-TPROSFE7.cjs.map
2
+ //# sourceMappingURL=chunk-TPROSFE7.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/types/errors.ts","../src/middleware/authenticate.ts"],"names":["AuthrimServerError","code","message","options","getServerErrorMeta","ERROR_META_MAP","getHeader","headers","name","lowerName","key","value","parseAuthorizationHeader","header","parts","scheme","token","normalizedScheme","authenticateRequest","server","request","authHeader","parsed","validationResult","errorMeta","claims","hasDPoPBinding","dpopHeader","dpopResult"],"mappings":"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","file":"chunk-TPROSFE7.cjs","sourcesContent":["/**\r\n * Authrim Server SDK Error Types\r\n *\r\n * These error codes are specific to server-side token validation and DPoP operations.\r\n */\r\n\r\n/**\r\n * Server SDK error codes\r\n */\r\nexport type AuthrimServerErrorCode =\r\n // JWT validation errors\r\n | 'invalid_token'\r\n | 'token_expired'\r\n | 'token_not_yet_valid'\r\n | 'token_malformed'\r\n | 'signature_invalid'\r\n | 'algorithm_mismatch'\r\n // Issuer/Audience validation\r\n | 'invalid_issuer'\r\n | 'invalid_audience'\r\n // JWKS errors\r\n | 'jwks_fetch_error'\r\n | 'jwks_key_not_found'\r\n | 'jwks_key_ambiguous'\r\n | 'jwks_key_import_error'\r\n // DPoP errors\r\n | 'dpop_proof_missing'\r\n | 'dpop_proof_invalid'\r\n | 'dpop_proof_signature_invalid'\r\n | 'dpop_method_mismatch'\r\n | 'dpop_uri_mismatch'\r\n | 'dpop_ath_mismatch'\r\n | 'dpop_binding_mismatch'\r\n | 'dpop_iat_expired'\r\n | 'dpop_nonce_required'\r\n // Token introspection/revocation errors\r\n | 'introspection_error'\r\n | 'revocation_error'\r\n // Configuration errors\r\n | 'configuration_error'\r\n | 'provider_error'\r\n // Network errors\r\n | 'network_error'\r\n | 'timeout_error';\r\n\r\n/**\r\n * Error metadata for recovery information\r\n */\r\nexport interface AuthrimServerErrorMeta {\r\n /** HTTP status code to return */\r\n httpStatus: number;\r\n /** Whether this is a transient error */\r\n transient: boolean;\r\n /** Whether automatic retry is possible */\r\n retryable: boolean;\r\n /** WWW-Authenticate error attribute */\r\n wwwAuthenticateError?: string;\r\n}\r\n\r\n/**\r\n * Options for creating an AuthrimServerError\r\n */\r\nexport interface AuthrimServerErrorOptions {\r\n details?: Record<string, unknown>;\r\n cause?: Error;\r\n}\r\n\r\n/**\r\n * Authrim Server SDK Error class\r\n */\r\nexport class AuthrimServerError extends Error {\r\n /** Error code for programmatic handling */\r\n readonly code: AuthrimServerErrorCode;\r\n\r\n /** Additional error details */\r\n readonly details?: Record<string, unknown>;\r\n\r\n /** Underlying cause */\r\n readonly cause?: Error;\r\n\r\n constructor(\r\n code: AuthrimServerErrorCode,\r\n message: string,\r\n options?: AuthrimServerErrorOptions\r\n ) {\r\n super(message);\r\n this.name = 'AuthrimServerError';\r\n this.code = code;\r\n this.details = options?.details;\r\n this.cause = options?.cause;\r\n }\r\n\r\n /**\r\n * Get error metadata for HTTP response\r\n */\r\n get meta(): AuthrimServerErrorMeta {\r\n return getServerErrorMeta(this.code);\r\n }\r\n}\r\n\r\n/**\r\n * Error metadata mapping for each error code\r\n */\r\nconst ERROR_META_MAP: Record<AuthrimServerErrorCode, AuthrimServerErrorMeta> = {\r\n // JWT validation errors\r\n invalid_token: {\r\n httpStatus: 401,\r\n transient: false,\r\n retryable: false,\r\n wwwAuthenticateError: 'invalid_token',\r\n },\r\n token_expired: {\r\n httpStatus: 401,\r\n transient: false,\r\n retryable: false,\r\n wwwAuthenticateError: 'invalid_token',\r\n },\r\n token_not_yet_valid: {\r\n httpStatus: 401,\r\n transient: false,\r\n retryable: false,\r\n wwwAuthenticateError: 'invalid_token',\r\n },\r\n token_malformed: {\r\n httpStatus: 401,\r\n transient: false,\r\n retryable: false,\r\n wwwAuthenticateError: 'invalid_token',\r\n },\r\n signature_invalid: {\r\n httpStatus: 401,\r\n transient: false,\r\n retryable: false,\r\n wwwAuthenticateError: 'invalid_token',\r\n },\r\n algorithm_mismatch: {\r\n httpStatus: 401,\r\n transient: false,\r\n retryable: false,\r\n wwwAuthenticateError: 'invalid_token',\r\n },\r\n\r\n // Issuer/Audience validation\r\n invalid_issuer: {\r\n httpStatus: 401,\r\n transient: false,\r\n retryable: false,\r\n wwwAuthenticateError: 'invalid_token',\r\n },\r\n invalid_audience: {\r\n httpStatus: 401,\r\n transient: false,\r\n retryable: false,\r\n wwwAuthenticateError: 'invalid_token',\r\n },\r\n\r\n // JWKS errors\r\n jwks_fetch_error: {\r\n httpStatus: 503,\r\n transient: true,\r\n retryable: true,\r\n },\r\n jwks_key_not_found: {\r\n httpStatus: 401,\r\n transient: true,\r\n retryable: true,\r\n wwwAuthenticateError: 'invalid_token',\r\n },\r\n jwks_key_ambiguous: {\r\n httpStatus: 401,\r\n transient: false,\r\n retryable: false,\r\n wwwAuthenticateError: 'invalid_token',\r\n },\r\n jwks_key_import_error: {\r\n httpStatus: 500,\r\n transient: false,\r\n retryable: false,\r\n },\r\n\r\n // DPoP errors\r\n dpop_proof_missing: {\r\n httpStatus: 401,\r\n transient: false,\r\n retryable: false,\r\n wwwAuthenticateError: 'invalid_token',\r\n },\r\n dpop_proof_invalid: {\r\n httpStatus: 401,\r\n transient: false,\r\n retryable: false,\r\n wwwAuthenticateError: 'invalid_token',\r\n },\r\n dpop_proof_signature_invalid: {\r\n httpStatus: 401,\r\n transient: false,\r\n retryable: false,\r\n wwwAuthenticateError: 'invalid_token',\r\n },\r\n dpop_method_mismatch: {\r\n httpStatus: 401,\r\n transient: false,\r\n retryable: false,\r\n wwwAuthenticateError: 'invalid_token',\r\n },\r\n dpop_uri_mismatch: {\r\n httpStatus: 401,\r\n transient: false,\r\n retryable: false,\r\n wwwAuthenticateError: 'invalid_token',\r\n },\r\n dpop_ath_mismatch: {\r\n httpStatus: 401,\r\n transient: false,\r\n retryable: false,\r\n wwwAuthenticateError: 'invalid_token',\r\n },\r\n dpop_binding_mismatch: {\r\n httpStatus: 401,\r\n transient: false,\r\n retryable: false,\r\n wwwAuthenticateError: 'invalid_token',\r\n },\r\n dpop_iat_expired: {\r\n httpStatus: 401,\r\n transient: false,\r\n retryable: false,\r\n wwwAuthenticateError: 'invalid_token',\r\n },\r\n dpop_nonce_required: {\r\n httpStatus: 401,\r\n transient: true,\r\n retryable: true,\r\n wwwAuthenticateError: 'use_dpop_nonce',\r\n },\r\n\r\n // Token introspection/revocation errors\r\n introspection_error: {\r\n httpStatus: 503,\r\n transient: true,\r\n retryable: true,\r\n },\r\n revocation_error: {\r\n httpStatus: 503,\r\n transient: true,\r\n retryable: true,\r\n },\r\n\r\n // Configuration errors\r\n configuration_error: {\r\n httpStatus: 500,\r\n transient: false,\r\n retryable: false,\r\n },\r\n provider_error: {\r\n httpStatus: 500,\r\n transient: false,\r\n retryable: false,\r\n },\r\n\r\n // Network errors\r\n network_error: {\r\n httpStatus: 503,\r\n transient: true,\r\n retryable: true,\r\n },\r\n timeout_error: {\r\n httpStatus: 504,\r\n transient: true,\r\n retryable: true,\r\n },\r\n};\r\n\r\n/**\r\n * Get error metadata for a given error code\r\n */\r\nexport function getServerErrorMeta(code: AuthrimServerErrorCode): AuthrimServerErrorMeta {\r\n return ERROR_META_MAP[code];\r\n}\r\n","/**\r\n * Core Authentication Function (Framework-Agnostic)\r\n *\r\n * This function is the ONLY authentication logic.\r\n * Framework adapters are thin wrappers that:\r\n * 1. Extract headers/method/url from framework-specific request\r\n * 2. Call authenticateRequest()\r\n * 3. Attach result to framework-specific context\r\n *\r\n * Header normalization:\r\n * - All header names are normalized to lowercase internally\r\n * - If multiple Authorization headers exist, only the first is used\r\n * - DPoP header lookup is case-insensitive\r\n */\r\n\r\nimport type { AuthrimServer } from '../core/client.js';\r\nimport type { AuthenticateRequest, AuthenticateResult } from './types.js';\r\nimport { AuthrimServerError } from '../types/errors.js';\r\n\r\n/**\r\n * Get header value (case-insensitive)\r\n */\r\nfunction getHeader(\r\n headers: Record<string, string | string[] | undefined>,\r\n name: string\r\n): string | undefined {\r\n const lowerName = name.toLowerCase();\r\n\r\n for (const [key, value] of Object.entries(headers)) {\r\n if (key.toLowerCase() === lowerName) {\r\n if (Array.isArray(value)) {\r\n return value[0];\r\n }\r\n return value;\r\n }\r\n }\r\n\r\n return undefined;\r\n}\r\n\r\n/**\r\n * Parse Authorization header\r\n *\r\n * @param header - Authorization header value\r\n * @returns Parsed token and type\r\n */\r\nfunction parseAuthorizationHeader(\r\n header: string | undefined\r\n): { scheme: 'Bearer' | 'DPoP'; token: string } | null {\r\n if (!header) {\r\n return null;\r\n }\r\n\r\n const parts = header.split(' ');\r\n if (parts.length !== 2) {\r\n return null;\r\n }\r\n\r\n const [scheme, token] = parts;\r\n if (!scheme || !token) {\r\n return null;\r\n }\r\n\r\n const normalizedScheme = scheme.toLowerCase();\r\n if (normalizedScheme === 'bearer') {\r\n return { scheme: 'Bearer', token };\r\n }\r\n if (normalizedScheme === 'dpop') {\r\n return { scheme: 'DPoP', token };\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Authenticate a request\r\n *\r\n * @param server - AuthrimServer instance\r\n * @param request - Framework-agnostic request\r\n * @returns Authentication result\r\n */\r\nexport async function authenticateRequest(\r\n server: AuthrimServer,\r\n request: AuthenticateRequest\r\n): Promise<AuthenticateResult> {\r\n // Parse Authorization header\r\n const authHeader = getHeader(request.headers, 'Authorization');\r\n const parsed = parseAuthorizationHeader(authHeader);\r\n\r\n if (!parsed) {\r\n return {\r\n data: null,\r\n error: {\r\n code: 'invalid_token',\r\n message: 'Missing or invalid Authorization header',\r\n httpStatus: 401,\r\n },\r\n };\r\n }\r\n\r\n const { scheme, token } = parsed;\r\n\r\n // Validate token\r\n const validationResult = await server.validateToken(token);\r\n\r\n if (validationResult.error) {\r\n const errorMeta = new AuthrimServerError(\r\n validationResult.error.code as any,\r\n validationResult.error.message\r\n ).meta;\r\n\r\n return {\r\n data: null,\r\n error: {\r\n code: validationResult.error.code,\r\n message: validationResult.error.message,\r\n httpStatus: errorMeta.httpStatus,\r\n },\r\n };\r\n }\r\n\r\n const claims = validationResult.data;\r\n if (!claims) {\r\n return {\r\n data: null,\r\n error: {\r\n code: 'invalid_token',\r\n message: 'Token validation failed',\r\n httpStatus: 401,\r\n },\r\n };\r\n }\r\n\r\n // Check if token is DPoP-bound\r\n const hasDPoPBinding = claims.claims.cnf?.jkt !== undefined;\r\n\r\n // If using DPoP scheme or token has DPoP binding, validate DPoP proof\r\n if (scheme === 'DPoP' || hasDPoPBinding) {\r\n const dpopHeader = getHeader(request.headers, 'DPoP');\r\n\r\n if (!dpopHeader) {\r\n return {\r\n data: null,\r\n error: {\r\n code: 'dpop_proof_missing',\r\n message: 'DPoP proof required but not provided',\r\n httpStatus: 401,\r\n },\r\n };\r\n }\r\n\r\n const dpopResult = await server.validateDPoP(dpopHeader, {\r\n method: request.method,\r\n uri: request.url,\r\n accessToken: token,\r\n expectedThumbprint: claims.claims.cnf?.jkt,\r\n });\r\n\r\n if (!dpopResult.valid) {\r\n return {\r\n data: null,\r\n error: {\r\n code: dpopResult.errorCode ?? 'dpop_proof_invalid',\r\n message: dpopResult.errorMessage ?? 'Invalid DPoP proof',\r\n httpStatus: 401,\r\n },\r\n };\r\n }\r\n }\r\n\r\n return {\r\n data: {\r\n claims,\r\n tokenType: hasDPoPBinding ? 'DPoP' : 'Bearer',\r\n },\r\n error: null,\r\n };\r\n}\r\n"]}
@@ -0,0 +1,2 @@
1
+ function o(r){return r.replace(/[\x00-\x08\x0A-\x1F\x7F]/g,"").replace(/\\/g,"\\\\").replace(/"/g,'\\"').substring(0,256)}function a(r){return {error:r.meta.wwwAuthenticateError??"server_error",error_description:r.message}}function s(r,e,t="Bearer"){let n=[t];e&&n.push(`realm="${o(e)}"`);let i=r.meta.wwwAuthenticateError;return i&&(n.push(`error="${o(i)}"`),n.push(`error_description="${o(r.message)}"`)),n.join(", ")}function c(r,e={}){let t={"Content-Type":"application/json"};return r.meta.httpStatus===401&&(t["WWW-Authenticate"]=s(r,e.realm,e.scheme??"Bearer")),r.code==="dpop_nonce_required"&&e.dpopNonce&&(t["DPoP-Nonce"]=e.dpopNonce),t}export{a,s as b,c};//# sourceMappingURL=chunk-XOFM2JHF.js.map
2
+ //# sourceMappingURL=chunk-XOFM2JHF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/error-response.ts"],"names":["sanitizeHeaderValue","value","buildErrorResponse","error","buildWwwAuthenticateHeader","realm","scheme","parts","wwwError","buildErrorHeaders","options","headers"],"mappings":"AA2BA,SAASA,CAAAA,CAAoBC,CAAAA,CAAuB,CAClD,OAAOA,CAAAA,CAMJ,OAAA,CAAQ,2BAAA,CAA6B,EAAE,CAAA,CAEvC,OAAA,CAAQ,KAAA,CAAO,MAAM,CAAA,CAErB,OAAA,CAAQ,IAAA,CAAM,KAAK,CAAA,CAEnB,SAAA,CAAU,CAAA,CAAG,GAAG,CACrB,CAQO,SAASC,CAAAA,CAAmBC,CAAAA,CAA8C,CAC/E,OAAO,CACL,KAAA,CAAOA,CAAAA,CAAM,IAAA,CAAK,oBAAA,EAAwB,cAAA,CAC1C,iBAAA,CAAmBA,CAAAA,CAAM,OAC3B,CACF,CAUO,SAASC,CAAAA,CACdD,CAAAA,CACAE,CAAAA,CACAC,CAAAA,CAA4B,QAAA,CACpB,CACR,IAAMC,CAAAA,CAAkB,CAACD,CAAM,CAAA,CAE3BD,CAAAA,EAEFE,CAAAA,CAAM,IAAA,CAAK,CAAA,OAAA,EAAUP,CAAAA,CAAoBK,CAAK,CAAC,CAAA,CAAA,CAAG,CAAA,CAGpD,IAAMG,EAAWL,CAAAA,CAAM,IAAA,CAAK,oBAAA,CAC5B,OAAIK,CAAAA,GAEFD,CAAAA,CAAM,IAAA,CAAK,CAAA,OAAA,EAAUP,CAAAA,CAAoBQ,CAAQ,CAAC,CAAA,CAAA,CAAG,CAAA,CAErDD,CAAAA,CAAM,IAAA,CAAK,CAAA,mBAAA,EAAsBP,CAAAA,CAAoBG,CAAAA,CAAM,OAAO,CAAC,CAAA,CAAA,CAAG,CAAA,CAAA,CAGjEI,CAAAA,CAAM,IAAA,CAAK,IAAI,CACxB,CASO,SAASE,CAAAA,CACdN,CAAAA,CACAO,CAAAA,CAII,GACoB,CACxB,IAAMC,CAAAA,CAAkC,CACtC,cAAA,CAAgB,kBAClB,CAAA,CAGA,OAAIR,CAAAA,CAAM,IAAA,CAAK,UAAA,GAAe,GAAA,GAC5BQ,CAAAA,CAAQ,kBAAkB,CAAA,CAAIP,CAAAA,CAC5BD,CAAAA,CACAO,CAAAA,CAAQ,KAAA,CACRA,CAAAA,CAAQ,MAAA,EAAU,QACpB,CAAA,CAAA,CAIEP,CAAAA,CAAM,IAAA,GAAS,qBAAA,EAAyBO,CAAAA,CAAQ,SAAA,GAClDC,CAAAA,CAAQ,YAAY,CAAA,CAAID,CAAAA,CAAQ,WAG3BC,CACT","file":"chunk-XOFM2JHF.js","sourcesContent":["/**\r\n * HTTP Error Response Utilities\r\n *\r\n * Helpers for building OAuth 2.0 / RFC 6750 compliant error responses.\r\n */\r\n\r\nimport { AuthrimServerError } from '../types/errors.js';\r\n\r\n/**\r\n * OAuth 2.0 error response body\r\n */\r\nexport interface ErrorResponseBody {\r\n error: string;\r\n error_description?: string;\r\n}\r\n\r\n/**\r\n * Sanitize a string value for use in HTTP header quoted-string\r\n *\r\n * Per RFC 7230 Section 3.2.6, a quoted-string consists of:\r\n * - DQUOTE *( qdtext / quoted-pair ) DQUOTE\r\n * - qdtext = HTAB / SP / %x21 / %x23-5B / %x5D-7E / obs-text\r\n * - quoted-pair = \"\\\" ( HTAB / SP / VCHAR / obs-text )\r\n *\r\n * We escape backslash and double-quote, and remove control characters.\r\n * CRITICAL: Must remove CR (\\r, 0x0D) and LF (\\n, 0x0A) to prevent header injection.\r\n */\r\nfunction sanitizeHeaderValue(value: string): string {\r\n return value\r\n // Remove ALL control characters except tab (0x09):\r\n // - 0x00-0x08: NUL through BS\r\n // - 0x0A-0x1F: LF (0x0A), VT (0x0B), FF (0x0C), CR (0x0D), SO through US\r\n // - 0x7F: DEL\r\n // Note: Tab (0x09) is allowed per RFC 7230\r\n .replace(/[\\x00-\\x08\\x0A-\\x1F\\x7F]/g, '')\r\n // Escape backslash first\r\n .replace(/\\\\/g, '\\\\\\\\')\r\n // Escape double quotes\r\n .replace(/\"/g, '\\\\\"')\r\n // Limit length to prevent header size issues\r\n .substring(0, 256);\r\n}\r\n\r\n/**\r\n * Build an error response body from an AuthrimServerError\r\n *\r\n * @param error - The error to convert\r\n * @returns Error response body\r\n */\r\nexport function buildErrorResponse(error: AuthrimServerError): ErrorResponseBody {\r\n return {\r\n error: error.meta.wwwAuthenticateError ?? 'server_error',\r\n error_description: error.message,\r\n };\r\n}\r\n\r\n/**\r\n * Build WWW-Authenticate header value (RFC 6750)\r\n *\r\n * @param error - The error\r\n * @param realm - Optional realm value\r\n * @param scheme - Authentication scheme ('Bearer' or 'DPoP')\r\n * @returns WWW-Authenticate header value\r\n */\r\nexport function buildWwwAuthenticateHeader(\r\n error: AuthrimServerError,\r\n realm?: string,\r\n scheme: 'Bearer' | 'DPoP' = 'Bearer'\r\n): string {\r\n const parts: string[] = [scheme];\r\n\r\n if (realm) {\r\n // Sanitize realm to prevent header injection\r\n parts.push(`realm=\"${sanitizeHeaderValue(realm)}\"`);\r\n }\r\n\r\n const wwwError = error.meta.wwwAuthenticateError;\r\n if (wwwError) {\r\n // wwwError is from a controlled set, but sanitize for safety\r\n parts.push(`error=\"${sanitizeHeaderValue(wwwError)}\"`);\r\n // Sanitize error message to prevent header injection\r\n parts.push(`error_description=\"${sanitizeHeaderValue(error.message)}\"`);\r\n }\r\n\r\n return parts.join(', ');\r\n}\r\n\r\n/**\r\n * Build error headers for HTTP response\r\n *\r\n * @param error - The error\r\n * @param options - Options for header building\r\n * @returns Headers object\r\n */\r\nexport function buildErrorHeaders(\r\n error: AuthrimServerError,\r\n options: {\r\n realm?: string;\r\n scheme?: 'Bearer' | 'DPoP';\r\n dpopNonce?: string;\r\n } = {}\r\n): Record<string, string> {\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n };\r\n\r\n // Add WWW-Authenticate for 401 errors\r\n if (error.meta.httpStatus === 401) {\r\n headers['WWW-Authenticate'] = buildWwwAuthenticateHeader(\r\n error,\r\n options.realm,\r\n options.scheme ?? 'Bearer'\r\n );\r\n }\r\n\r\n // Add DPoP-Nonce for nonce-required errors\r\n if (error.code === 'dpop_nonce_required' && options.dpopNonce) {\r\n headers['DPoP-Nonce'] = options.dpopNonce;\r\n }\r\n\r\n return headers;\r\n}\r\n"]}
@@ -0,0 +1,364 @@
1
+ /**
2
+ * HTTP Provider Interface
3
+ *
4
+ * Platform-agnostic HTTP client abstraction.
5
+ * This interface uses the standard fetch API signature for maximum compatibility.
6
+ */
7
+ /**
8
+ * HTTP Provider interface
9
+ *
10
+ * Implementations should:
11
+ * - Use the platform's native fetch or equivalent
12
+ * - Handle timeout via AbortSignal
13
+ * - Propagate network errors appropriately
14
+ *
15
+ * This interface follows the standard fetch API signature to ensure
16
+ * compatibility across all runtime environments (Node.js, Bun, Deno,
17
+ * Cloudflare Workers, Vercel Edge Functions).
18
+ */
19
+ interface HttpProvider {
20
+ /**
21
+ * Make an HTTP request
22
+ *
23
+ * @param input - URL or Request object
24
+ * @param init - Request options
25
+ * @returns Promise resolving to a Response
26
+ * @throws Error on network failure or timeout
27
+ */
28
+ fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
29
+ }
30
+
31
+ /**
32
+ * Crypto Provider Interface
33
+ *
34
+ * Platform-agnostic cryptographic operations abstraction for server-side JWT operations.
35
+ * Implementations must be injected - @authrim/server does not use crypto.subtle directly.
36
+ */
37
+ /**
38
+ * Crypto Provider interface
39
+ *
40
+ * Implementations should:
41
+ * - Use cryptographically secure operations
42
+ * - Support RSA and ECDSA signature verification
43
+ * - Implement JWK import for public keys
44
+ * - Calculate JWK thumbprints per RFC 7638
45
+ */
46
+ interface CryptoProvider {
47
+ /**
48
+ * Verify a digital signature
49
+ *
50
+ * @param alg - JWA algorithm (e.g., 'RS256', 'ES256')
51
+ * @param key - CryptoKey for verification
52
+ * @param signature - Signature bytes
53
+ * @param data - Data that was signed
54
+ * @returns Promise resolving to true if signature is valid
55
+ */
56
+ verifySignature(alg: string, key: CryptoKey, signature: Uint8Array, data: Uint8Array): Promise<boolean>;
57
+ /**
58
+ * Import a JWK as a CryptoKey
59
+ *
60
+ * @param jwk - JSON Web Key
61
+ * @param alg - Algorithm to use with the key
62
+ * @returns Promise resolving to a CryptoKey
63
+ */
64
+ importJwk(jwk: JsonWebKey, alg: string): Promise<CryptoKey>;
65
+ /**
66
+ * Compute SHA-256 hash
67
+ *
68
+ * @param data - String or bytes to hash
69
+ * @returns Promise resolving to hash bytes
70
+ */
71
+ sha256(data: string | Uint8Array): Promise<Uint8Array>;
72
+ /**
73
+ * Calculate JWK Thumbprint (RFC 7638)
74
+ *
75
+ * @param jwk - JSON Web Key (public key)
76
+ * @returns Promise resolving to base64url-encoded thumbprint
77
+ */
78
+ calculateThumbprint(jwk: JsonWebKey): Promise<string>;
79
+ }
80
+
81
+ /**
82
+ * Clock Provider Interface
83
+ *
84
+ * Abstraction for time operations to enable testing and custom time sources.
85
+ */
86
+ /**
87
+ * Clock Provider interface
88
+ *
89
+ * Implementations should:
90
+ * - Return consistent, monotonic time values
91
+ * - Use the system clock in production
92
+ * - Allow time manipulation in tests
93
+ */
94
+ interface ClockProvider {
95
+ /**
96
+ * Get current Unix timestamp in seconds
97
+ *
98
+ * @returns Current time as Unix timestamp (seconds since epoch)
99
+ */
100
+ nowSeconds(): number;
101
+ /**
102
+ * Get current time in milliseconds
103
+ *
104
+ * @returns Current time in milliseconds since epoch
105
+ */
106
+ nowMs(): number;
107
+ }
108
+
109
+ /**
110
+ * Cache Provider Interface
111
+ *
112
+ * Generic caching abstraction for JWKS and other cacheable data.
113
+ */
114
+ /**
115
+ * Cache Provider interface
116
+ *
117
+ * Implementations should:
118
+ * - Support TTL-based expiration
119
+ * - Be thread-safe in concurrent environments
120
+ * - Handle memory limits gracefully
121
+ *
122
+ * @template T - Type of cached values
123
+ */
124
+ interface CacheProvider<T> {
125
+ /**
126
+ * Get a cached value
127
+ *
128
+ * @param key - Cache key
129
+ * @returns Cached value or undefined if not found/expired
130
+ */
131
+ get(key: string): T | undefined;
132
+ /**
133
+ * Set a cached value
134
+ *
135
+ * @param key - Cache key
136
+ * @param value - Value to cache
137
+ * @param ttlMs - Time-to-live in milliseconds (optional, uses default if not provided)
138
+ */
139
+ set(key: string, value: T, ttlMs?: number): void;
140
+ /**
141
+ * Delete a cached value
142
+ *
143
+ * @param key - Cache key
144
+ */
145
+ delete(key: string): void;
146
+ /**
147
+ * Clear all cached values (optional)
148
+ *
149
+ * May be a no-op in some implementations (e.g., distributed caches).
150
+ */
151
+ clear?(): void;
152
+ }
153
+
154
+ /**
155
+ * JWK (JSON Web Key) Type Definitions
156
+ *
157
+ * Based on RFC 7517 (JSON Web Key) and RFC 7518 (JSON Web Algorithms)
158
+ */
159
+ /**
160
+ * Key type (RFC 7517 Section 6.1)
161
+ */
162
+ type JwkKeyType = 'EC' | 'RSA' | 'oct' | 'OKP';
163
+ /**
164
+ * Key use (RFC 7517 Section 4.2)
165
+ */
166
+ type JwkKeyUse = 'sig' | 'enc';
167
+ /**
168
+ * Key operations (RFC 7517 Section 4.3)
169
+ */
170
+ type JwkKeyOps = 'sign' | 'verify' | 'encrypt' | 'decrypt' | 'wrapKey' | 'unwrapKey' | 'deriveKey' | 'deriveBits';
171
+ /**
172
+ * Supported signing algorithms (RFC 7518)
173
+ */
174
+ type JwkSigningAlgorithm = 'RS256' | 'RS384' | 'RS512' | 'PS256' | 'PS384' | 'PS512' | 'ES256' | 'ES384' | 'ES512' | 'EdDSA';
175
+ /**
176
+ * EC curve names (RFC 7518 Section 6.2.1.1)
177
+ */
178
+ type EcCurve = 'P-256' | 'P-384' | 'P-521';
179
+ /**
180
+ * OKP curve names (RFC 8037)
181
+ */
182
+ type OkpCurve = 'Ed25519' | 'Ed448' | 'X25519' | 'X448';
183
+ /**
184
+ * Base JWK properties (RFC 7517 Section 4)
185
+ */
186
+ interface JwkBase {
187
+ /** Key Type (required) */
188
+ kty: JwkKeyType;
189
+ /** Public Key Use */
190
+ use?: JwkKeyUse;
191
+ /** Key Operations */
192
+ key_ops?: JwkKeyOps[];
193
+ /** Algorithm */
194
+ alg?: JwkSigningAlgorithm;
195
+ /** Key ID */
196
+ kid?: string;
197
+ /** X.509 URL */
198
+ x5u?: string;
199
+ /** X.509 Certificate Chain */
200
+ x5c?: string[];
201
+ /** X.509 Certificate SHA-1 Thumbprint */
202
+ x5t?: string;
203
+ /** X.509 Certificate SHA-256 Thumbprint */
204
+ 'x5t#S256'?: string;
205
+ }
206
+ /**
207
+ * RSA Public Key (RFC 7518 Section 6.3)
208
+ */
209
+ interface RsaPublicJwk extends JwkBase {
210
+ kty: 'RSA';
211
+ /** Modulus */
212
+ n: string;
213
+ /** Exponent */
214
+ e: string;
215
+ }
216
+ /**
217
+ * EC Public Key (RFC 7518 Section 6.2)
218
+ */
219
+ interface EcPublicJwk extends JwkBase {
220
+ kty: 'EC';
221
+ /** Curve */
222
+ crv: EcCurve;
223
+ /** X Coordinate */
224
+ x: string;
225
+ /** Y Coordinate */
226
+ y: string;
227
+ }
228
+ /**
229
+ * OKP (Octet Key Pair) Public Key (RFC 8037)
230
+ */
231
+ interface OkpPublicJwk extends JwkBase {
232
+ kty: 'OKP';
233
+ /** Curve */
234
+ crv: OkpCurve;
235
+ /** Public Key */
236
+ x: string;
237
+ }
238
+ /**
239
+ * Public JWK (union type)
240
+ */
241
+ type PublicJwk = RsaPublicJwk | EcPublicJwk | OkpPublicJwk;
242
+ /**
243
+ * JWK Set (RFC 7517 Section 5)
244
+ */
245
+ interface JwkSet {
246
+ keys: PublicJwk[];
247
+ }
248
+ /**
249
+ * Internal representation of a cached JWK with metadata
250
+ */
251
+ interface CachedJwk {
252
+ jwk: PublicJwk;
253
+ cryptoKey: CryptoKey;
254
+ }
255
+
256
+ /**
257
+ * Configuration Type Definitions
258
+ */
259
+
260
+ /**
261
+ * AuthrimServer configuration options
262
+ */
263
+ interface AuthrimServerConfig {
264
+ /**
265
+ * Expected token issuer(s)
266
+ * This is compared against the `iss` claim in tokens
267
+ */
268
+ issuer: string | string[];
269
+ /**
270
+ * Expected audience(s) for this resource server
271
+ * This is compared against the `aud` claim in tokens
272
+ */
273
+ audience: string | string[];
274
+ /**
275
+ * JWKS endpoint URL
276
+ * If not provided, will be discovered from `{issuer}/.well-known/openid-configuration`
277
+ */
278
+ jwksUri?: string;
279
+ /**
280
+ * Clock tolerance in seconds for exp, nbf, iat validation
281
+ * @default 60
282
+ */
283
+ clockToleranceSeconds?: number;
284
+ /**
285
+ * JWKS cache TTL in milliseconds
286
+ * @default 3600000 (1 hour)
287
+ */
288
+ jwksRefreshIntervalMs?: number;
289
+ /**
290
+ * Token introspection endpoint
291
+ * Required for introspection operations
292
+ */
293
+ introspectionEndpoint?: string;
294
+ /**
295
+ * Token revocation endpoint
296
+ * Required for revocation operations
297
+ */
298
+ revocationEndpoint?: string;
299
+ /**
300
+ * Client credentials for introspection/revocation
301
+ */
302
+ clientCredentials?: {
303
+ clientId: string;
304
+ clientSecret: string;
305
+ };
306
+ /**
307
+ * HTTP provider for network requests
308
+ * @default fetchHttpProvider()
309
+ */
310
+ http?: HttpProvider;
311
+ /**
312
+ * Crypto provider for cryptographic operations
313
+ * @default webCryptoProvider()
314
+ */
315
+ crypto?: CryptoProvider;
316
+ /**
317
+ * Clock provider for time operations
318
+ * @default systemClock()
319
+ */
320
+ clock?: ClockProvider;
321
+ /**
322
+ * JWKS cache provider
323
+ * @default memoryCache()
324
+ */
325
+ jwksCache?: CacheProvider<CachedJwk[]>;
326
+ /**
327
+ * Require HTTPS for issuer and JWKS URI
328
+ * Set to false to allow HTTP in development environments
329
+ * @default true
330
+ */
331
+ requireHttps?: boolean;
332
+ }
333
+ /**
334
+ * Resolved configuration with all defaults applied
335
+ */
336
+ interface ResolvedAuthrimServerConfig {
337
+ issuer: string[];
338
+ audience: string[];
339
+ jwksUri?: string;
340
+ clockToleranceSeconds: number;
341
+ jwksRefreshIntervalMs: number;
342
+ introspectionEndpoint?: string;
343
+ revocationEndpoint?: string;
344
+ clientCredentials?: {
345
+ clientId: string;
346
+ clientSecret: string;
347
+ };
348
+ http: HttpProvider;
349
+ crypto: CryptoProvider;
350
+ clock: ClockProvider;
351
+ jwksCache: CacheProvider<CachedJwk[]>;
352
+ requireHttps: boolean;
353
+ }
354
+ /**
355
+ * Memory cache options
356
+ */
357
+ interface MemoryCacheOptions {
358
+ /** Default TTL in milliseconds */
359
+ ttlMs?: number;
360
+ /** Maximum number of entries */
361
+ maxSize?: number;
362
+ }
363
+
364
+ export type { AuthrimServerConfig as A, CachedJwk as C, EcPublicJwk as E, HttpProvider as H, JwkKeyType as J, MemoryCacheOptions as M, OkpPublicJwk as O, PublicJwk as P, ResolvedAuthrimServerConfig as R, CryptoProvider as a, ClockProvider as b, CacheProvider as c, JwkKeyUse as d, JwkSet as e, JwkSigningAlgorithm as f, RsaPublicJwk as g };