@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.
- package/README.md +610 -0
- package/dist/adapters/express.cjs +3 -0
- package/dist/adapters/express.cjs.map +1 -0
- package/dist/adapters/express.d.cts +75 -0
- package/dist/adapters/express.d.ts +75 -0
- package/dist/adapters/express.js +3 -0
- package/dist/adapters/express.js.map +1 -0
- package/dist/adapters/fastify.cjs +3 -0
- package/dist/adapters/fastify.cjs.map +1 -0
- package/dist/adapters/fastify.d.cts +101 -0
- package/dist/adapters/fastify.d.ts +101 -0
- package/dist/adapters/fastify.js +3 -0
- package/dist/adapters/fastify.js.map +1 -0
- package/dist/adapters/hono.cjs +2 -0
- package/dist/adapters/hono.cjs.map +1 -0
- package/dist/adapters/hono.d.cts +85 -0
- package/dist/adapters/hono.d.ts +85 -0
- package/dist/adapters/hono.js +2 -0
- package/dist/adapters/hono.js.map +1 -0
- package/dist/adapters/koa.cjs +3 -0
- package/dist/adapters/koa.cjs.map +1 -0
- package/dist/adapters/koa.d.cts +75 -0
- package/dist/adapters/koa.d.ts +75 -0
- package/dist/adapters/koa.js +3 -0
- package/dist/adapters/koa.js.map +1 -0
- package/dist/adapters/nestjs.cjs +3 -0
- package/dist/adapters/nestjs.cjs.map +1 -0
- package/dist/adapters/nestjs.d.cts +126 -0
- package/dist/adapters/nestjs.d.ts +126 -0
- package/dist/adapters/nestjs.js +3 -0
- package/dist/adapters/nestjs.js.map +1 -0
- package/dist/chunk-7POGA5LZ.cjs +3 -0
- package/dist/chunk-7POGA5LZ.cjs.map +1 -0
- package/dist/chunk-N3ONRO35.js +2 -0
- package/dist/chunk-N3ONRO35.js.map +1 -0
- package/dist/chunk-O2ALCNXB.cjs +2 -0
- package/dist/chunk-O2ALCNXB.cjs.map +1 -0
- package/dist/chunk-OS567YCE.js +3 -0
- package/dist/chunk-OS567YCE.js.map +1 -0
- package/dist/chunk-TPROSFE7.cjs +2 -0
- package/dist/chunk-TPROSFE7.cjs.map +1 -0
- package/dist/chunk-XOFM2JHF.js +2 -0
- package/dist/chunk-XOFM2JHF.js.map +1 -0
- package/dist/config-I0GIVJA_.d.cts +364 -0
- package/dist/config-I0GIVJA_.d.ts +364 -0
- package/dist/index.cjs +3 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +791 -0
- package/dist/index.d.ts +791 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/index.cjs +2 -0
- package/dist/providers/index.cjs.map +1 -0
- package/dist/providers/index.d.cts +79 -0
- package/dist/providers/index.d.ts +79 -0
- package/dist/providers/index.js +2 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/types-CzpMdWFR.d.cts +435 -0
- package/dist/types-D7gjcvs9.d.ts +435 -0
- 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 };
|