vouchly 0.0.0 → 0.1.1
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 +323 -3
- package/dist/index.d.mts +365 -0
- package/dist/index.mjs +722 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +54 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["TIMEOUT"],"sources":["../src/cache/hash.ts","../src/cache/memory.ts","../src/discovery/module.ts","../src/error/constants.ts","../src/error/module.ts","../src/introspection/module.ts","../src/issuer/match.ts","../src/key/cached.ts","../src/key/jwks.ts","../src/key/discovery.ts","../src/key/policy.ts","../src/key/module.ts","../src/key/static.ts","../src/token/module.ts","../src/verifier/binding.ts","../src/verifier/module.ts"],"sourcesContent":["export async function hashToken(token: string): Promise<string> {\n const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(token));\n\n let output = '';\n for (const byte of new Uint8Array(digest)) {\n output += byte.toString(16).padStart(2, '0');\n }\n\n return output;\n}\n","import type { ITokenCache, MemoryTokenCacheOptions, TokenCacheEntry } from './types';\n\ntype MemoryTokenCacheItem = {\n entry: TokenCacheEntry,\n expiresAt: number,\n};\n\nexport class MemoryTokenCache implements ITokenCache {\n protected max: number;\n\n // Map iteration follows insertion order, so the first key is the least recently used.\n protected items: Map<string, MemoryTokenCacheItem>;\n\n constructor(options: MemoryTokenCacheOptions = {}) {\n const max = options.max ?? 10_000;\n if (!Number.isSafeInteger(max) || max < 1) {\n throw new TypeError('The token cache max must be an integer of at least 1.');\n }\n\n this.max = max;\n this.items = new Map();\n }\n\n async get(key: string): Promise<TokenCacheEntry | undefined> {\n const item = this.items.get(key);\n if (!item) {\n return undefined;\n }\n\n this.items.delete(key);\n\n if (item.expiresAt <= Date.now()) {\n return undefined;\n }\n\n this.items.set(key, item);\n\n return structuredClone(item.entry);\n }\n\n async set(key: string, entry: TokenCacheEntry, ttl: number): Promise<void> {\n this.items.delete(key);\n\n if (!(ttl > 0)) {\n return;\n }\n\n this.items.set(key, {\n entry: structuredClone(entry),\n expiresAt: Date.now() + (ttl * 1000),\n });\n\n while (this.items.size > this.max) {\n const oldest = this.items.keys().next();\n if (oldest.done) {\n break;\n }\n\n this.items.delete(oldest.value);\n }\n }\n}\n","import type { DiscoveryOptions, ProviderMetadata } from './types';\n\nconst CACHE_MAX_AGE = 600;\nconst TIMEOUT = 10_000;\nconst FAILURE_COOLDOWN = 30_000;\n\ntype MetadataItem = {\n metadata: ProviderMetadata,\n fetchedAt: number,\n};\n\n// Keyed by fetch implementation, then by the configured issuer string, so\n// two verifiers with different fetch functions never share an answer.\nconst items = new WeakMap<typeof fetch, Map<string, MetadataItem>>();\nconst flights = new WeakMap<typeof fetch, Map<string, Promise<ProviderMetadata>>>();\nconst failures = new WeakMap<typeof fetch, Map<string, number>>();\n\nfunction scope<T>(store: WeakMap<typeof fetch, Map<string, T>>, fetchFn: typeof globalThis.fetch) : Map<string, T> {\n let map = store.get(fetchFn);\n if (!map) {\n map = new Map();\n store.set(fetchFn, map);\n }\n\n return map;\n}\n\nfunction isRecord(input: unknown) : input is Record<string, unknown> {\n return typeof input === 'object' && input !== null && !Array.isArray(input);\n}\n\nfunction isURL(input: unknown) : input is string {\n return typeof input === 'string' && URL.canParse(input);\n}\n\nasync function load(issuer: string, fetchFn: typeof globalThis.fetch) : Promise<ProviderMetadata> {\n const url = `${issuer.replace(/\\/$/, '')}/.well-known/openid-configuration`;\n\n const response = await fetchFn(url, {\n headers: { accept: 'application/json' },\n signal: AbortSignal.timeout(TIMEOUT),\n });\n\n if (!response.ok) {\n throw new Error(`The provider metadata request answered ${response.status}.`);\n }\n\n const body : unknown = await response.json();\n if (!isRecord(body)) {\n throw new Error('The provider metadata is not a JSON object.');\n }\n\n // OIDC Discovery 1.0, section 4.3.\n if (body.issuer !== issuer) {\n throw new Error('The provider metadata names another issuer.');\n }\n\n const metadata : ProviderMetadata = { issuer: body.issuer };\n\n if (typeof body.jwks_uri !== 'undefined') {\n if (!isURL(body.jwks_uri)) {\n throw new Error('The provider metadata has an invalid jwks_uri.');\n }\n\n metadata.jwks_uri = body.jwks_uri;\n }\n\n if (typeof body.introspection_endpoint !== 'undefined') {\n if (!isURL(body.introspection_endpoint)) {\n throw new Error('The provider metadata has an invalid introspection_endpoint.');\n }\n\n metadata.introspection_endpoint = body.introspection_endpoint;\n }\n\n return metadata;\n}\n\n/**\n * Reads `<issuer>/.well-known/openid-configuration`. The issuer must come\n * from configuration, never from a token. Answers are reused for\n * cacheMaxAge seconds; after a failure, the issuer is not asked again for\n * 30 seconds and calls fail fast instead.\n */\nexport async function fetchProviderMetadata(\n issuer: string,\n fetchFn: typeof globalThis.fetch,\n options: DiscoveryOptions = {},\n) : Promise<ProviderMetadata> {\n const cacheMaxAge = options.cacheMaxAge ?? CACHE_MAX_AGE;\n\n const cached = scope(items, fetchFn);\n const item = cached.get(issuer);\n if (item && Date.now() - item.fetchedAt < cacheMaxAge * 1000) {\n return structuredClone(item.metadata);\n }\n\n const failed = scope(failures, fetchFn);\n const failedAt = failed.get(issuer);\n if (typeof failedAt === 'number') {\n if (Date.now() - failedAt < FAILURE_COOLDOWN) {\n throw new Error('The provider metadata failed to load recently, not trying again yet.');\n }\n\n failed.delete(issuer);\n }\n\n const pending = scope(flights, fetchFn);\n let flight = pending.get(issuer);\n if (!flight) {\n flight = load(issuer, fetchFn)\n .then((metadata) => {\n cached.set(issuer, { metadata, fetchedAt: Date.now() });\n return metadata;\n }, (e: unknown) => {\n failed.set(issuer, Date.now());\n throw e;\n })\n .finally(() => {\n pending.delete(issuer);\n });\n\n pending.set(issuer, flight);\n }\n\n return structuredClone(await flight);\n}\n","export enum VouchlyErrorCode {\n TOKEN_MALFORMED = 'token_malformed',\n TOKEN_EXPIRED = 'token_expired',\n TOKEN_INACTIVE = 'token_inactive',\n ISSUER_UNTRUSTED = 'issuer_untrusted',\n KEY_UNAVAILABLE = 'key_unavailable',\n SIGNATURE_INVALID = 'signature_invalid',\n CLAIM_INVALID = 'claim_invalid',\n INTROSPECTION_FAILED = 'introspection_failed',\n BINDING_MISMATCH = 'binding_mismatch',\n}\n\nexport const VOUCHLY_ERROR_MARKER = Symbol.for('vouchly.error');\n","import type { VouchlyErrorCode } from './constants';\nimport { VOUCHLY_ERROR_MARKER } from './constants';\nimport type { VouchlyErrorOptions } from './types';\n\nexport class VouchlyError extends Error {\n readonly code: VouchlyErrorCode;\n\n readonly status?: number;\n\n readonly [VOUCHLY_ERROR_MARKER] = true;\n\n constructor(code: VouchlyErrorCode, message?: string, options?: VouchlyErrorOptions) {\n super(message || code, typeof options?.cause === 'undefined' ? undefined : { cause: options.cause });\n\n this.name = 'VouchlyError';\n this.code = code;\n\n if (typeof options?.status === 'number') {\n this.status = options.status;\n }\n }\n}\n\nexport function isVouchlyError(input: unknown): input is VouchlyError {\n if (typeof input !== 'object' || input === null) {\n return false;\n }\n\n return (input as Record<symbol, unknown>)[VOUCHLY_ERROR_MARKER] === true;\n}\n","import type { JWTPayload } from 'jose';\nimport { fetchProviderMetadata } from '../discovery';\nimport { VouchlyError, VouchlyErrorCode, isVouchlyError } from '../error';\nimport type { Issuer } from '../issuer';\nimport type { IntrospectionResponse } from './types';\n\nconst TIMEOUT = 10_000;\n\nfunction fail(message: string, cause?: unknown) : VouchlyError {\n return new VouchlyError(VouchlyErrorCode.INTROSPECTION_FAILED, message, typeof cause === 'undefined' ? undefined : { cause });\n}\n\n/**\n * application/x-www-form-urlencoded, as RFC 6749 2.3.1 asks for client credentials.\n */\nfunction formEncode(value: string) : string {\n return new URLSearchParams([['', value]]).toString().slice(1);\n}\n\nasync function resolveEndpoint(issuer: Issuer, fetchFn: typeof globalThis.fetch) : Promise<string> {\n if (issuer.introspection?.endpoint) {\n return issuer.introspection.endpoint;\n }\n\n // A function issuer has no configured URL; the token's own `iss` is never fetched.\n if (typeof issuer.issuer !== 'string') {\n throw fail('The issuer has no introspection endpoint.');\n }\n\n let endpoint : string | undefined;\n try {\n endpoint = (await fetchProviderMetadata(issuer.issuer, fetchFn)).introspection_endpoint;\n } catch (e) {\n throw fail('The introspection endpoint could not be discovered.', e);\n }\n\n if (!endpoint) {\n throw fail('The issuer advertises no introspection endpoint.');\n }\n\n return endpoint;\n}\n\nasync function resolveAuthorization(issuer: Issuer, retry: boolean) : Promise<string | undefined> {\n const authorization = issuer.introspection?.authorization;\n if (!authorization) {\n return undefined;\n }\n\n if (typeof authorization === 'function') {\n try {\n return await authorization({ retry });\n } catch (e) {\n throw fail('The introspection authorization could not be resolved.', e);\n }\n }\n\n return `Basic ${btoa(`${formEncode(authorization.clientId)}:${formEncode(authorization.clientSecret)}`)}`;\n}\n\nfunction isResponse(input: unknown) : input is IntrospectionResponse {\n return typeof input === 'object' && input !== null && !Array.isArray(input);\n}\n\nasync function send(\n token: string,\n endpoint: string,\n authorization: string | undefined,\n fetchFn: typeof globalThis.fetch,\n) : Promise<Response> {\n const headers : Record<string, string> = {\n 'content-type': 'application/x-www-form-urlencoded',\n accept: 'application/json',\n };\n if (typeof authorization === 'string') {\n headers.authorization = authorization;\n }\n\n try {\n return await fetchFn(endpoint, {\n method: 'POST',\n headers,\n body: new URLSearchParams({ token }).toString(),\n signal: AbortSignal.timeout(TIMEOUT),\n });\n } catch (e) {\n throw fail('The introspection request failed.', e);\n }\n}\n\nasync function request(token: string, issuer: Issuer, fetchFn: typeof globalThis.fetch) : Promise<JWTPayload> {\n const endpoint = await resolveEndpoint(issuer, fetchFn);\n\n let response = await send(token, endpoint, await resolveAuthorization(issuer, false), fetchFn);\n\n // A function may hold a token that expired since it was minted; it gets\n // one chance to mint a fresh one. Client credentials would only repeat.\n if (response.status === 401 && typeof issuer.introspection?.authorization === 'function') {\n await response.body?.cancel().catch(() => undefined);\n response = await send(token, endpoint, await resolveAuthorization(issuer, true), fetchFn);\n }\n\n if (!response.ok) {\n await response.body?.cancel().catch(() => undefined);\n throw new VouchlyError(\n VouchlyErrorCode.INTROSPECTION_FAILED,\n `The introspection endpoint answered ${response.status}.`,\n { status: response.status },\n );\n }\n\n let body : unknown;\n try {\n body = JSON.parse(await response.text());\n } catch (e) {\n throw fail('The introspection response is not JSON.', e);\n }\n\n if (!isResponse(body)) {\n throw fail('The introspection response is not a JSON object.');\n }\n\n if (body.active !== true) {\n throw new VouchlyError(VouchlyErrorCode.TOKEN_INACTIVE, 'The token is not active.');\n }\n\n return body as JWTPayload;\n}\n\n/**\n * RFC 7662: asks the issuer's introspection endpoint about a token and\n * answers the response as its claims. Claim rules are the caller's.\n */\nexport async function introspect(\n token: string,\n issuer: Issuer,\n fetchFn: typeof globalThis.fetch,\n) : Promise<JWTPayload> {\n try {\n return await request(token, issuer, fetchFn);\n } catch (e) {\n if (isVouchlyError(e)) {\n throw e;\n }\n\n throw fail('The introspection failed.', e);\n }\n}\n","import type { JWTPayload } from 'jose';\nimport type { Issuer } from './types';\n\n/**\n * Whether an issuer config trusts a token by its UNVERIFIED claims. This only\n * selects a config: verification still runs against it afterwards. A\n * function matcher counts only when it returns exactly `true`; one that\n * throws, or returns anything else (a Promise included), does not match.\n */\nexport function matchIssuer(issuer: Issuer, claims: JWTPayload) : boolean {\n if (typeof issuer.issuer === 'string') {\n return typeof claims.iss === 'string' && claims.iss === issuer.issuer;\n }\n\n try {\n return issuer.issuer(claims) === true;\n } catch {\n return false;\n }\n}\n\n/**\n * The index of the first issuer that trusts the claims, or -1.\n */\nexport function selectIssuer(issuers: Issuer[], claims: JWTPayload) : number {\n for (const [index, issuer] of issuers.entries()) {\n if (matchIssuer(issuer, claims)) {\n return index;\n }\n }\n\n return -1;\n}\n","import type { JWK } from 'jose';\nimport type { CachedKeysOptions, KeySource, KeySourceContext } from './types';\n\ntype CachedKeysItem = {\n jwk: JWK,\n expiresAt: number,\n};\n\nexport function cachedKeys(\n load: (context: KeySourceContext) => Promise<JWK>,\n options: CachedKeysOptions,\n) : KeySource {\n const ttl = options.ttl ?? 300;\n const timeout = options.timeout ?? 10;\n const max = options.max ?? 100;\n\n if (!Number.isFinite(ttl) || ttl < 0) {\n throw new TypeError('The key cache ttl must be a finite, non-negative number of seconds.');\n }\n\n if (!Number.isSafeInteger(max) || max < 1) {\n throw new TypeError('The key cache max must be an integer of at least 1.');\n }\n\n // setTimeout clamps a delay above 2^31 - 1 ms to 1 ms\n if (!Number.isFinite(timeout) || timeout <= 0 || timeout * 1000 > 2_147_483_647) {\n throw new TypeError('The key cache timeout must be a positive number of seconds, at most 2147483.');\n }\n\n // Map iteration follows insertion order, so the first key is the oldest.\n const items = new Map<string, CachedKeysItem>();\n const flights = new Map<string, Promise<JWK>>();\n\n return async (context) => {\n const key = options.key(context);\n\n const item = items.get(key);\n if (item) {\n if (item.expiresAt > Date.now()) {\n return structuredClone(item.jwk);\n }\n\n items.delete(key);\n }\n\n const pending = flights.get(key);\n if (pending) {\n return structuredClone(await pending);\n }\n\n let timer: ReturnType<typeof setTimeout> | undefined;\n const deadline = new Promise<never>((_resolve, reject) => {\n timer = setTimeout(() => {\n reject(new Error('Loading the key timed out.'));\n }, timeout * 1000);\n });\n\n // A stalled load must not pin every later lookup of the key: the\n // flight settles at the deadline, and a load finishing after it is\n // dropped instead of stored.\n const flight : Promise<JWK> = Promise.race([\n Promise.resolve().then(() => load(context)),\n deadline,\n ])\n .then((jwk) => {\n if (ttl > 0) {\n items.delete(key);\n items.set(key, {\n jwk: structuredClone(jwk),\n expiresAt: Date.now() + (ttl * 1000),\n });\n\n while (items.size > max) {\n const oldest = items.keys().next();\n if (oldest.done) {\n break;\n }\n\n items.delete(oldest.value);\n }\n }\n\n return jwk;\n })\n .finally(() => {\n clearTimeout(timer);\n if (flights.get(key) === flight) {\n flights.delete(key);\n }\n });\n\n flights.set(key, flight);\n\n return structuredClone(await flight);\n };\n}\n","import type { RemoteJWKSet } from 'jose';\nimport { createRemoteJWKSet, customFetch } from 'jose';\nimport type { JWKSOptions, KeySource } from './types';\n\nexport function jwks(url: string | URL, options: JWKSOptions = {}) : KeySource {\n const target = new URL(url);\n\n // One set (and so one jose key cache) per fetch implementation.\n const sets = new WeakMap<typeof fetch, RemoteJWKSet>();\n\n return async (context) => {\n let set = sets.get(context.fetch);\n if (!set) {\n set = createRemoteJWKSet(target, {\n cacheMaxAge: options.cacheMaxAge,\n cooldownDuration: options.cooldownDuration,\n timeoutDuration: options.timeoutDuration,\n [customFetch]: context.fetch,\n });\n sets.set(context.fetch, set);\n }\n\n return set(context.token.header);\n };\n}\n","import type { DiscoveryOptions } from '../discovery';\nimport { fetchProviderMetadata } from '../discovery';\nimport { VouchlyError, VouchlyErrorCode } from '../error';\nimport { jwks } from './jwks';\nimport type { KeySource } from './types';\n\n/**\n * Resolves keys through the configured issuer's OIDC discovery document.\n * A function issuer is refused: its only URL would be the token's own `iss`.\n */\nexport function discovery(options: DiscoveryOptions = {}) : KeySource {\n if (\n typeof options.cacheMaxAge !== 'undefined' &&\n (!Number.isFinite(options.cacheMaxAge) || options.cacheMaxAge < 0)\n ) {\n throw new TypeError('The discovery cacheMaxAge must be a finite, non-negative number of seconds.');\n }\n\n const sources = new Map<string, KeySource>();\n\n return async (context) => {\n const { issuer } = context.issuer;\n if (typeof issuer !== 'string') {\n throw new VouchlyError(\n VouchlyErrorCode.KEY_UNAVAILABLE,\n 'Discovery needs a configured issuer string, a function issuer cannot be discovered.',\n );\n }\n\n let metadata;\n try {\n metadata = await fetchProviderMetadata(issuer, context.fetch, options);\n } catch (e) {\n const message = e instanceof Error && e.message ? e.message : 'The provider metadata is unavailable.';\n throw new VouchlyError(VouchlyErrorCode.KEY_UNAVAILABLE, message, { cause: e });\n }\n\n const { jwks_uri: url } = metadata;\n if (!url) {\n throw new VouchlyError(VouchlyErrorCode.KEY_UNAVAILABLE, 'The provider metadata has no jwks_uri.');\n }\n\n let source = sources.get(url);\n if (!source) {\n source = jwks(url);\n sources.set(url, source);\n }\n\n return source(context);\n };\n}\n","import type { CryptoKey, JWK } from 'jose';\n\nconst RSA_MIN_MODULUS_LENGTH = 2048;\n\n/**\n * Throws an Error when a JWK must never be used to verify a signature.\n */\nexport function assertJWKPolicy(jwk: JWK) : void {\n if (jwk.kty === 'oct') {\n throw new Error('A symmetric key (kty \"oct\") is not accepted.');\n }\n\n if (typeof jwk.use !== 'undefined' && jwk.use !== 'sig') {\n throw new Error(`A key with use \"${jwk.use}\" is not a signature key.`);\n }\n}\n\n/**\n * Throws an Error when a CryptoKey must never be used to verify a signature.\n */\nexport function assertCryptoKeyPolicy(key: CryptoKey) : void {\n if (key.type === 'secret') {\n throw new Error('A symmetric key is not accepted.');\n }\n\n const { modulusLength } = key.algorithm as { modulusLength?: unknown };\n if (typeof modulusLength === 'number' && modulusLength < RSA_MIN_MODULUS_LENGTH) {\n throw new Error(`An RSA key of ${modulusLength} bits is too small, at least ${RSA_MIN_MODULUS_LENGTH} are required.`);\n }\n}\n","import type { CryptoKey, JWK } from 'jose';\nimport { importJWK } from 'jose';\nimport { VouchlyError, VouchlyErrorCode, isVouchlyError } from '../error';\nimport { assertCryptoKeyPolicy, assertJWKPolicy } from './policy';\nimport type { KeySource, KeySourceContext } from './types';\n\nfunction isJWK(input: CryptoKey | JWK) : input is JWK {\n return typeof (input as JWK).kty === 'string';\n}\n\nasync function resolve(source: KeySource, context: KeySourceContext) : Promise<CryptoKey> {\n const output = await source(context);\n\n let key : CryptoKey | Uint8Array;\n if (isJWK(output)) {\n assertJWKPolicy(output);\n key = await importJWK(output, output.alg ?? context.token.header.alg);\n } else {\n key = output;\n }\n\n if (key instanceof Uint8Array) {\n throw new Error('A symmetric key is not accepted.');\n }\n\n assertCryptoKeyPolicy(key);\n\n return key;\n}\n\n/**\n * Resolves the key a token is verified with. Every failure, including a key\n * the policy refuses, is a KEY_UNAVAILABLE VouchlyError.\n */\nexport async function resolveVerificationKey(source: KeySource, context: KeySourceContext) : Promise<CryptoKey> {\n try {\n return await resolve(source, context);\n } catch (e) {\n if (isVouchlyError(e) && e.code === VouchlyErrorCode.KEY_UNAVAILABLE) {\n throw e;\n }\n\n const message = e instanceof Error && e.message ?\n `The verification key is unavailable: ${e.message}` :\n 'The verification key is unavailable.';\n\n throw new VouchlyError(VouchlyErrorCode.KEY_UNAVAILABLE, message, { cause: e });\n }\n}\n","import type { JWK } from 'jose';\nimport { createLocalJWKSet } from 'jose';\nimport type { KeySource } from './types';\n\nexport function staticKeys(keys: JWK[]) : KeySource {\n const set = createLocalJWKSet({ keys: structuredClone(keys) });\n\n return async (context) => set(context.token.header);\n}\n","import { decodeJwt, decodeProtectedHeader } from 'jose';\nimport { VouchlyError, VouchlyErrorCode } from '../error';\nimport type { ParsedToken } from './types';\n\nconst COMPACT_TOKEN_REGEX = /^[\\w-]+\\.[\\w-]+\\.[\\w-]+$/;\n\nexport function isCompactToken(token: string): boolean {\n return COMPACT_TOKEN_REGEX.test(token);\n}\n\nfunction isPlainObject(input: unknown): input is Record<string, unknown> {\n return typeof input === 'object' && input !== null && !Array.isArray(input);\n}\n\nexport function parseToken(token: string): ParsedToken {\n if (typeof token !== 'string' || !isCompactToken(token)) {\n throw new VouchlyError(VouchlyErrorCode.TOKEN_MALFORMED, 'The token is not a compact JWS.');\n }\n\n let header: ParsedToken['header'];\n let claims: ParsedToken['claims'];\n try {\n header = decodeProtectedHeader(token);\n claims = decodeJwt(token);\n } catch (e) {\n throw new VouchlyError(VouchlyErrorCode.TOKEN_MALFORMED, 'The token could not be decoded.', { cause: e });\n }\n\n if (!isPlainObject(header) || !isPlainObject(claims)) {\n throw new VouchlyError(VouchlyErrorCode.TOKEN_MALFORMED, 'The token header or claims are not an object.');\n }\n\n return {\n raw: token,\n header,\n claims,\n };\n}\n","import type { JWTPayload } from 'jose';\nimport { VouchlyError, VouchlyErrorCode } from '../error';\nimport type { VerifyOptions } from './types';\n\n/**\n * RFC 8705: a token carrying `cnf` is certificate-bound and fails closed\n * unless the presented thumbprint equals `cnf.x5t#S256`. A `cnf` this check\n * cannot satisfy (no `x5t#S256`, e.g. a DPoP `jkt`) fails too.\n */\nexport function assertCertificateBinding(claims: JWTPayload, thumbprint: string | undefined) : void {\n if (typeof claims.cnf === 'undefined' || claims.cnf === null) {\n return;\n }\n\n const expected = typeof claims.cnf === 'object' ?\n (claims.cnf as Record<string, unknown>)['x5t#S256'] :\n undefined;\n\n if (\n typeof expected !== 'string' ||\n expected.length === 0 ||\n typeof thumbprint !== 'string' ||\n thumbprint !== expected\n ) {\n throw new VouchlyError(\n VouchlyErrorCode.BINDING_MISMATCH,\n 'The token is bound to a certificate that was not presented.',\n );\n }\n}\n\nfunction isBound(claims: JWTPayload) : boolean {\n return typeof claims.cnf !== 'undefined' && claims.cnf !== null;\n}\n\n/**\n * Checks the binding of every claim set given: a token verified by\n * introspection passes its own unverified claims next to the response, since\n * an unverified `cnf` may only add a requirement, never lift one.\n */\nexport async function resolveCertificateBinding(\n claims: JWTPayload | JWTPayload[],\n options: VerifyOptions,\n) : Promise<void> {\n const bound = (Array.isArray(claims) ? claims : [claims]).filter(isBound);\n if (bound.length === 0) {\n return;\n }\n\n let thumbprint : string | undefined;\n if (typeof options.certificateThumbprint === 'function') {\n try {\n thumbprint = await options.certificateThumbprint();\n } catch (e) {\n throw new VouchlyError(\n VouchlyErrorCode.BINDING_MISMATCH,\n 'The certificate thumbprint could not be resolved.',\n { cause: e },\n );\n }\n } else {\n thumbprint = options.certificateThumbprint;\n }\n\n for (const item of bound) {\n assertCertificateBinding(item, thumbprint);\n }\n}\n","import type { CryptoKey, JWTPayload } from 'jose';\nimport { errors, jwtVerify } from 'jose';\nimport type { ITokenCache, TokenCacheEntry } from '../cache';\nimport { MemoryTokenCache, hashToken } from '../cache';\nimport { VouchlyError, VouchlyErrorCode, isVouchlyError } from '../error';\nimport type { Issuer } from '../issuer';\nimport { matchIssuer, selectIssuer } from '../issuer';\nimport { introspect } from '../introspection';\nimport type { KeySource } from '../key';\nimport { discovery, resolveVerificationKey } from '../key';\nimport type { ParsedToken } from '../token';\nimport { isCompactToken, parseToken } from '../token';\nimport { resolveCertificateBinding } from './binding';\nimport type {\n IVerifier,\n VerifierOptions,\n VerifyOptions,\n VerifyResult,\n} from './types';\n\ntype IssuerRecord = {\n /**\n * Issuer.id, or the issuer's index when it has none; the cache entry's issuer.\n */\n name: string,\n issuer: Issuer,\n keys?: KeySource,\n};\n\n/**\n * One function for every verifier without a fetch of its own: discovery and\n * jwks() memoise per fetch, so their caches are shared between such\n * verifiers. It reads the global at call time, so a later stub applies.\n */\nconst defaultFetch : typeof fetch = (input, init) => fetch(input, init);\n\nconst EC_ALGORITHMS : Record<string, string> = {\n 'P-256': 'ES256',\n 'P-384': 'ES384',\n 'P-521': 'ES512',\n};\n\n/**\n * The JWS algorithms a resolved key verifies. A JWK without `alg` was\n * imported with the header's `alg`, so for it this is the header's choice\n * among the algorithms its key type supports; Issuer.algorithms pins it.\n */\nfunction deriveAlgorithms(key: CryptoKey) : string[] {\n const algorithm = key.algorithm as KeyAlgorithm & { hash?: { name: string }, namedCurve?: string };\n const bits = algorithm.hash?.name.replace('SHA-', '');\n\n switch (algorithm.name) {\n case 'RSASSA-PKCS1-v1_5':\n return bits ? [`RS${bits}`] : [];\n case 'RSA-PSS':\n return bits ? [`PS${bits}`] : [];\n case 'ECDSA': {\n const alg = algorithm.namedCurve ? EC_ALGORITHMS[algorithm.namedCurve] : undefined;\n return alg ? [alg] : [];\n }\n case 'Ed25519':\n return ['EdDSA', 'Ed25519'];\n default:\n return [];\n }\n}\n\nfunction mapJoseError(e: unknown) : VouchlyError {\n if (isVouchlyError(e)) {\n return e;\n }\n\n const message = e instanceof Error && e.message ? e.message : undefined;\n\n if (e instanceof errors.JWTExpired) {\n return new VouchlyError(VouchlyErrorCode.TOKEN_EXPIRED, message, { cause: e });\n }\n\n if (e instanceof errors.JWSSignatureVerificationFailed) {\n return new VouchlyError(VouchlyErrorCode.SIGNATURE_INVALID, message, { cause: e });\n }\n\n if (\n e instanceof errors.JWTClaimValidationFailed ||\n e instanceof errors.JOSEAlgNotAllowed ||\n e instanceof errors.JWTInvalid\n ) {\n return new VouchlyError(VouchlyErrorCode.CLAIM_INVALID, message, { cause: e });\n }\n\n return new VouchlyError(VouchlyErrorCode.SIGNATURE_INVALID, message, { cause: e });\n}\n\nfunction assertAudience(issuer: Issuer, claims: JWTPayload) : void {\n if (typeof issuer.audience === 'undefined') {\n return;\n }\n\n const expected = Array.isArray(issuer.audience) ? issuer.audience : [issuer.audience];\n const actual = Array.isArray(claims.aud) ? claims.aud : [claims.aud];\n if (actual.every((value) => typeof value !== 'string' || !expected.includes(value))) {\n throw new VouchlyError(VouchlyErrorCode.CLAIM_INVALID, 'The token audience is not accepted.');\n }\n}\n\nfunction normalizeTyp(value: string) : string {\n const normalized = value.toLowerCase();\n return value.includes('/') ? normalized : `application/${normalized}`;\n}\n\n/**\n * The rules jose applies to the header and claims of a local token that do\n * not need the signature, so a cache hit is held to them too.\n */\nfunction assertLocalClaims(issuer: Issuer, entry: TokenCacheEntry) : void {\n for (const claim of issuer.requiredClaims ?? ['exp']) {\n if (!(claim in entry.claims)) {\n throw new VouchlyError(VouchlyErrorCode.CLAIM_INVALID, `The token has no \"${claim}\" claim.`);\n }\n }\n\n if (\n typeof issuer.typ === 'string' &&\n (typeof entry.typ !== 'string' || normalizeTyp(entry.typ) !== normalizeTyp(issuer.typ))\n ) {\n throw new VouchlyError(VouchlyErrorCode.CLAIM_INVALID, 'The token typ is not accepted.');\n }\n\n if (\n issuer.algorithms &&\n (typeof entry.alg !== 'string' || !issuer.algorithms.includes(entry.alg))\n ) {\n throw new VouchlyError(VouchlyErrorCode.CLAIM_INVALID, 'The token algorithm is not accepted.');\n }\n\n const { nbf } = entry.claims;\n if (typeof nbf === 'number' && nbf > (Date.now() / 1000) + (issuer.clockTolerance ?? 0)) {\n throw new VouchlyError(VouchlyErrorCode.CLAIM_INVALID, 'The token is not yet valid.');\n }\n}\n\nfunction buildRecords(options: VerifierOptions) : IssuerRecord[] {\n if (!Array.isArray(options.issuers) || options.issuers.length === 0) {\n throw new TypeError('A verifier needs at least one issuer.');\n }\n\n const names = new Set<string>();\n\n return options.issuers.map((issuer, index) => {\n const name = issuer.id ?? String(index);\n if (names.has(name)) {\n throw new TypeError(`The issuer id \"${name}\" is used twice (an issuer without id is named by its index).`);\n }\n names.add(name);\n\n const verification = issuer.verification ?? 'local';\n if (verification !== 'local' && verification !== 'remote') {\n throw new TypeError(`The issuer \"${name}\" has an unknown verification \"${String(verification)}\".`);\n }\n\n let { keys } = issuer;\n if (!keys && verification === 'local') {\n if (typeof issuer.issuer !== 'string') {\n throw new TypeError(\n `The issuer \"${name}\" matches by function and needs a key source, since it cannot be discovered.`,\n );\n }\n\n keys = discovery();\n }\n\n return {\n name, \n issuer, \n keys, \n };\n });\n}\n\nexport class Verifier implements IVerifier {\n protected records: IssuerRecord[];\n\n protected cache: ITokenCache | undefined;\n\n protected fetch: typeof fetch;\n\n protected opaque: IssuerRecord | undefined;\n\n protected cacheNamespace: string;\n\n constructor(options: VerifierOptions) {\n this.records = buildRecords(options);\n\n if (typeof options.opaque !== 'undefined') {\n this.opaque = this.records.find((record) => record.issuer.id === options.opaque);\n if (!this.opaque) {\n throw new TypeError(`The opaque issuer \"${options.opaque}\" names no configured issuer.`);\n }\n }\n\n // A cache passed in may be shared with other verifiers, and a hit skips\n // the key lookup and signature check, so it is only safe between\n // verifiers whose issuer configuration is identical. The namespace\n // makes the caller name that group.\n if (options.cache && !options.cacheNamespace) {\n throw new TypeError(\n 'A cache passed in needs a cacheNamespace; verifiers sharing one namespace must have identical issuer configurations.',\n );\n }\n\n if (typeof options.cacheNamespace === 'string' && options.cacheNamespace.includes('\\u0000')) {\n throw new TypeError('The cacheNamespace must not contain a NUL character.');\n }\n\n this.cache = options.cache === false ? undefined : (options.cache ?? new MemoryTokenCache());\n this.cacheNamespace = options.cacheNamespace ?? '';\n\n this.fetch = options.fetch ?? defaultFetch;\n }\n\n async verify(token: string, options: VerifyOptions = {}) : Promise<VerifyResult> {\n const compact = typeof token === 'string' && isCompactToken(token);\n if (!compact && (!this.opaque || typeof token !== 'string' || token.length === 0)) {\n throw new VouchlyError(VouchlyErrorCode.TOKEN_MALFORMED, 'The token is not a compact JWS.');\n }\n\n const parsed = compact ? parseToken(token) : undefined;\n const key = await hashToken(`${this.cacheNamespace}\\u0000${token}`);\n\n const cached = await this.readCache(key, parsed);\n if (cached) {\n await resolveCertificateBinding(this.bindingClaims(cached.entry.claims, cached.entry.source, parsed), options);\n\n return {\n claims: structuredClone(cached.entry.claims),\n issuer: cached.record.issuer,\n source: cached.entry.source,\n };\n }\n\n if (!compact) {\n return this.introspect(token, key, this.opaque!, options, parsed);\n }\n\n const record = this.selectRecord(parsed!);\n if (record.issuer.verification === 'remote') {\n return this.introspect(token, key, record, options, parsed);\n }\n\n const claims = await this.verifyLocal(parsed!, record);\n\n const entry : TokenCacheEntry = {\n claims,\n issuer: record.name,\n source: 'local',\n };\n if (typeof parsed!.header.typ === 'string') {\n entry.typ = parsed!.header.typ;\n }\n\n if (typeof parsed!.header.alg === 'string') {\n entry.alg = parsed!.header.alg;\n }\n\n await this.writeCache(key, entry, claims.exp);\n\n await resolveCertificateBinding(claims, options);\n\n return {\n claims: structuredClone(claims),\n issuer: record.issuer,\n source: 'local',\n };\n }\n\n /**\n * The claim sets whose `cnf` a result must satisfy: an introspected\n * compact token is held to its own `cnf` as well as the response's.\n */\n protected bindingClaims(\n claims: JWTPayload,\n source: VerifyResult['source'],\n token: ParsedToken | undefined,\n ) : JWTPayload[] {\n return source === 'remote' && token ? [claims, token.claims] : [claims];\n }\n\n protected selectRecord(token: ParsedToken) : IssuerRecord {\n const index = selectIssuer(this.records.map((record) => record.issuer), token.claims);\n if (index === -1) {\n throw new VouchlyError(VouchlyErrorCode.ISSUER_UNTRUSTED, 'The token issuer is not trusted.');\n }\n\n return this.records[index]!;\n }\n\n protected async verifyLocal(token: ParsedToken, record: IssuerRecord) : Promise<JWTPayload> {\n const { issuer } = record;\n\n const key = await resolveVerificationKey(record.keys!, {\n token,\n issuer,\n fetch: this.fetch,\n });\n\n const algorithms = issuer.algorithms ?? deriveAlgorithms(key);\n if (algorithms.length === 0) {\n throw new VouchlyError(VouchlyErrorCode.KEY_UNAVAILABLE, 'The verification key has no supported algorithm.');\n }\n\n let payload : JWTPayload;\n try {\n const output = await jwtVerify(token.raw, key, {\n algorithms,\n audience: issuer.audience,\n typ: issuer.typ,\n clockTolerance: issuer.clockTolerance ?? 0,\n requiredClaims: issuer.requiredClaims ?? ['exp'],\n issuer: typeof issuer.issuer === 'string' ? issuer.issuer : undefined,\n });\n payload = output.payload;\n } catch (e) {\n throw mapJoseError(e);\n }\n\n await this.assertClaimsPredicate(issuer, payload);\n\n return payload;\n }\n\n protected async assertClaimsPredicate(issuer: Issuer, claims: JWTPayload) : Promise<void> {\n if (!issuer.claims) {\n return;\n }\n\n let passed : boolean;\n try {\n passed = await issuer.claims(structuredClone(claims)) === true;\n } catch (e) {\n throw new VouchlyError(VouchlyErrorCode.CLAIM_INVALID, 'The claims predicate failed.', { cause: e });\n }\n\n if (!passed) {\n throw new VouchlyError(VouchlyErrorCode.CLAIM_INVALID, 'The claims predicate refused the token.');\n }\n }\n\n /**\n * Verifies a token by RFC 7662 introspection and applies the issuer's\n * audience and claims predicate to the response.\n */\n protected async verifyIntrospection(\n token: string,\n record: IssuerRecord,\n ) : Promise<JWTPayload> {\n const claims = await introspect(token, record.issuer, this.fetch);\n\n assertAudience(record.issuer, claims);\n await this.assertClaimsPredicate(record.issuer, claims);\n\n return claims;\n }\n\n protected async introspect(\n token: string,\n key: string,\n record: IssuerRecord,\n options: VerifyOptions,\n parsed?: ParsedToken,\n ) : Promise<VerifyResult> {\n const claims = await this.verifyIntrospection(token, record);\n\n await this.writeCache(\n key,\n {\n claims, \n issuer: record.name, \n source: 'remote', \n },\n claims.exp,\n record.issuer.introspection?.maxCacheTTL,\n );\n\n await resolveCertificateBinding(this.bindingClaims(claims, 'remote', parsed), options);\n\n return {\n claims: structuredClone(claims),\n issuer: record.issuer,\n source: 'remote',\n };\n }\n\n /**\n * A cache failure is a miss: the token is verified again instead. An entry\n * is only served under the record an uncached verify would pick, and only\n * after this verifier's own rules that need no signature passed on it:\n * a verifier sharing the cache may have applied other ones.\n */\n protected async readCache(\n key: string,\n token: ParsedToken | undefined,\n ) : Promise<{ entry: TokenCacheEntry, record: IssuerRecord } | undefined> {\n if (!this.cache) {\n return undefined;\n }\n\n let entry : TokenCacheEntry | undefined;\n try {\n entry = await this.cache.get(key);\n } catch {\n return undefined;\n }\n\n if (!entry) {\n return undefined;\n }\n\n const record = token ? this.selectRecord(token) : this.opaque!;\n const source = record.issuer.verification ?? 'local';\n if (entry.issuer !== record.name || entry.source !== source) {\n return undefined;\n }\n\n if (source === 'local') {\n if (!matchIssuer(record.issuer, entry.claims)) {\n throw new VouchlyError(VouchlyErrorCode.ISSUER_UNTRUSTED, 'The token issuer is not trusted.');\n }\n\n assertLocalClaims(record.issuer, entry);\n }\n\n // A cache may keep an entry longer than asked (a TTL rounded up).\n const { exp } = entry.claims;\n if (\n typeof exp === 'number' &&\n exp <= (Date.now() / 1000) - (record.issuer.clockTolerance ?? 0)\n ) {\n throw new VouchlyError(VouchlyErrorCode.TOKEN_EXPIRED, 'The token has expired.');\n }\n\n assertAudience(record.issuer, entry.claims);\n await this.assertClaimsPredicate(record.issuer, entry.claims);\n\n return { entry, record };\n }\n\n /**\n * Caches until `exp`, measured to the millisecond, or for at most `maxTTL` seconds when given. A token\n * without `exp` is cached only under a `maxTTL`. A cache failure is ignored.\n */\n protected async writeCache(key: string, entry: TokenCacheEntry, exp: unknown, maxTTL?: number) : Promise<void> {\n if (!this.cache) {\n return;\n }\n\n let ttl : number | undefined;\n if (typeof exp === 'number' && Number.isFinite(exp)) {\n ttl = exp - (Date.now() / 1000);\n }\n\n if (typeof maxTTL === 'number') {\n ttl = typeof ttl === 'number' ? Math.min(ttl, maxTTL) : maxTTL;\n }\n\n if (typeof ttl !== 'number' || !(ttl > 0)) {\n return;\n }\n\n try {\n await this.cache.set(key, structuredClone(entry), ttl);\n } catch {\n // the result stays valid without a cache entry\n }\n }\n}\n\nexport function createVerifier(options: VerifierOptions) : Verifier {\n return new Verifier(options);\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vouchly",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"type": "module",
|
|
4
5
|
"description": "Verify OAuth2 and OIDC tokens against trusted issuers: JWT, introspection and certificate-bound tokens, on any Web runtime.",
|
|
5
|
-
"license": "Apache-2.0",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Peter Placzek",
|
|
8
8
|
"email": "contact@tada5hi.net",
|
|
@@ -10,7 +10,57 @@
|
|
|
10
10
|
},
|
|
11
11
|
"repository": {
|
|
12
12
|
"type": "git",
|
|
13
|
-
"url": "https://github.com/tada5hi/
|
|
13
|
+
"url": "https://github.com/tada5hi/vouchly.git"
|
|
14
|
+
},
|
|
15
|
+
"main": "dist/index.mjs",
|
|
16
|
+
"types": "dist/index.d.mts",
|
|
17
|
+
"exports": {
|
|
18
|
+
"./package.json": "./package.json",
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./dist/index.d.mts",
|
|
21
|
+
"import": "./dist/index.mjs"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist"
|
|
26
|
+
],
|
|
27
|
+
"engines": {
|
|
28
|
+
"node": ">=22.0.0"
|
|
29
|
+
},
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "tsdown",
|
|
32
|
+
"test": "vitest --config test/vitest.config.ts --run",
|
|
33
|
+
"test:coverage": "vitest --config test/vitest.config.ts --run --coverage",
|
|
34
|
+
"lint": "eslint",
|
|
35
|
+
"lint:fix": "npm run lint -- --fix",
|
|
36
|
+
"prepare": "husky"
|
|
37
|
+
},
|
|
38
|
+
"keywords": [
|
|
39
|
+
"oauth2",
|
|
40
|
+
"oidc",
|
|
41
|
+
"jwt",
|
|
42
|
+
"jwks",
|
|
43
|
+
"introspection",
|
|
44
|
+
"token-verification",
|
|
45
|
+
"mtls"
|
|
46
|
+
],
|
|
47
|
+
"publishConfig": {
|
|
48
|
+
"access": "public"
|
|
49
|
+
},
|
|
50
|
+
"license": "Apache-2.0",
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@tada5hi/commitlint-config": "^1.3.2",
|
|
53
|
+
"@tada5hi/eslint-config": "^2.4.0",
|
|
54
|
+
"@tada5hi/tsconfig": "^0.7.2",
|
|
55
|
+
"@vitest/coverage-v8": "^5.0.5",
|
|
56
|
+
"eslint": "^10.12.0",
|
|
57
|
+
"husky": "^9.1.7",
|
|
58
|
+
"tsdown": "^0.23.1",
|
|
59
|
+
"typescript": "^6.0.3",
|
|
60
|
+
"typescript-eslint": "^8.71.2",
|
|
61
|
+
"vitest": "^5.0.5"
|
|
14
62
|
},
|
|
15
|
-
"
|
|
63
|
+
"dependencies": {
|
|
64
|
+
"jose": "^6.2.12"
|
|
65
|
+
}
|
|
16
66
|
}
|