vouchly 0.0.0-stage → 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.
@@ -0,0 +1,349 @@
1
+ import { CryptoKey, JWK, JWTPayload, ProtectedHeaderParameters } from "jose";
2
+ //#region src/cache/hash.d.ts
3
+ export declare function hashToken(token: string): Promise<string>;
4
+ //#endregion
5
+ //#region src/cache/types.d.ts
6
+ type TokenCacheEntry = {
7
+ claims: JWTPayload;
8
+ /**
9
+ * Issuer.id, or the issuer's index in the verifier's list when it has no id.
10
+ */
11
+ issuer: string;
12
+ source: 'local' | 'remote';
13
+ /**
14
+ * The token header's `typ`, for a locally verified token that carried one.
15
+ */
16
+ typ?: string;
17
+ /**
18
+ * The token header's `alg`, for a locally verified token.
19
+ */
20
+ alg?: string;
21
+ };
22
+ interface ITokenCache {
23
+ get(key: string): Promise<TokenCacheEntry | undefined>;
24
+ /**
25
+ * @param ttl seconds; a value <= 0 stores nothing.
26
+ */
27
+ set(key: string, entry: TokenCacheEntry, ttl: number): Promise<void>;
28
+ }
29
+ type MemoryTokenCacheOptions = {
30
+ /**
31
+ * Maximum number of entries, default 10000.
32
+ */
33
+ max?: number;
34
+ };
35
+ //#endregion
36
+ //#region src/cache/memory.d.ts
37
+ type MemoryTokenCacheItem = {
38
+ entry: TokenCacheEntry;
39
+ expiresAt: number;
40
+ };
41
+ export declare class MemoryTokenCache implements ITokenCache {
42
+ protected max: number;
43
+ protected items: Map<string, MemoryTokenCacheItem>;
44
+ constructor(options?: MemoryTokenCacheOptions);
45
+ get(key: string): Promise<TokenCacheEntry | undefined>;
46
+ set(key: string, entry: TokenCacheEntry, ttl: number): Promise<void>;
47
+ }
48
+ //#endregion
49
+ //#region src/discovery/types.d.ts
50
+ type ProviderMetadata = {
51
+ issuer: string;
52
+ /**
53
+ * Required by the discovery key source, not by introspection.
54
+ */
55
+ jwks_uri?: string;
56
+ introspection_endpoint?: string;
57
+ };
58
+ type DiscoveryOptions = {
59
+ /**
60
+ * Seconds the provider metadata of an issuer is reused, default 600.
61
+ */
62
+ cacheMaxAge?: number;
63
+ };
64
+ //#endregion
65
+ //#region src/discovery/module.d.ts
66
+ /**
67
+ * Reads `<issuer>/.well-known/openid-configuration`. The issuer must come
68
+ * from configuration, never from a token. Answers are reused for
69
+ * cacheMaxAge seconds; after a failure, the issuer is not asked again for
70
+ * 30 seconds and calls fail fast instead.
71
+ */
72
+ export declare function fetchProviderMetadata(issuer: string, fetchFn: typeof globalThis.fetch, options?: DiscoveryOptions): Promise<ProviderMetadata>;
73
+ //#endregion
74
+ //#region src/error/constants.d.ts
75
+ export declare enum VouchlyErrorCode {
76
+ TOKEN_MALFORMED = "token_malformed",
77
+ TOKEN_EXPIRED = "token_expired",
78
+ TOKEN_INACTIVE = "token_inactive",
79
+ ISSUER_UNTRUSTED = "issuer_untrusted",
80
+ KEY_UNAVAILABLE = "key_unavailable",
81
+ SIGNATURE_INVALID = "signature_invalid",
82
+ CLAIM_INVALID = "claim_invalid",
83
+ INTROSPECTION_FAILED = "introspection_failed",
84
+ BINDING_MISMATCH = "binding_mismatch"
85
+ }
86
+ export declare const VOUCHLY_ERROR_MARKER: unique symbol;
87
+ //#endregion
88
+ //#region src/error/types.d.ts
89
+ type VouchlyErrorOptions = {
90
+ cause?: unknown;
91
+ };
92
+ //#endregion
93
+ //#region src/error/module.d.ts
94
+ export declare class VouchlyError extends Error {
95
+ readonly code: VouchlyErrorCode;
96
+ readonly [VOUCHLY_ERROR_MARKER] = true;
97
+ constructor(code: VouchlyErrorCode, message?: string, options?: VouchlyErrorOptions);
98
+ }
99
+ export declare function isVouchlyError(input: unknown): input is VouchlyError;
100
+ //#endregion
101
+ //#region src/token/types.d.ts
102
+ type ParsedToken = {
103
+ raw: string;
104
+ header: ProtectedHeaderParameters;
105
+ claims: JWTPayload;
106
+ };
107
+ //#endregion
108
+ //#region src/token/module.d.ts
109
+ export declare function isCompactToken(token: string): boolean;
110
+ export declare function parseToken(token: string): ParsedToken;
111
+ //#endregion
112
+ //#region src/key/types.d.ts
113
+ type KeySourceContext = {
114
+ token: ParsedToken;
115
+ issuer: Issuer;
116
+ fetch: typeof fetch;
117
+ };
118
+ type KeySource = (context: KeySourceContext) => Promise<CryptoKey | JWK>;
119
+ type JWKSOptions = {
120
+ /**
121
+ * Milliseconds, see jose createRemoteJWKSet.
122
+ */
123
+ cacheMaxAge?: number;
124
+ /**
125
+ * Milliseconds, see jose createRemoteJWKSet.
126
+ */
127
+ cooldownDuration?: number;
128
+ /**
129
+ * Milliseconds, see jose createRemoteJWKSet.
130
+ */
131
+ timeoutDuration?: number;
132
+ };
133
+ type CachedKeysOptions = {
134
+ /**
135
+ * The cache key of the context; one load is shared per key.
136
+ */
137
+ key: (context: KeySourceContext) => string;
138
+ /**
139
+ * Seconds, default 300; 0 caches nothing.
140
+ */
141
+ ttl?: number;
142
+ /**
143
+ * Seconds, default 10, at most 2147483.
144
+ */
145
+ timeout?: number;
146
+ /**
147
+ * Maximum number of entries, default 100.
148
+ */
149
+ max?: number;
150
+ };
151
+ //#endregion
152
+ //#region src/key/cached.d.ts
153
+ export declare function cachedKeys(load: (context: KeySourceContext) => Promise<JWK>, options: CachedKeysOptions): KeySource;
154
+ //#endregion
155
+ //#region src/key/discovery.d.ts
156
+ /**
157
+ * Resolves keys through the configured issuer's OIDC discovery document.
158
+ * A function issuer is refused: its only URL would be the token's own `iss`.
159
+ */
160
+ export declare function discovery(options?: DiscoveryOptions): KeySource;
161
+ //#endregion
162
+ //#region src/key/jwks.d.ts
163
+ export declare function jwks(url: string | URL, options?: JWKSOptions): KeySource;
164
+ //#endregion
165
+ //#region src/key/module.d.ts
166
+ /**
167
+ * Resolves the key a token is verified with. Every failure, including a key
168
+ * the policy refuses, is a KEY_UNAVAILABLE VouchlyError.
169
+ */
170
+ export declare function resolveVerificationKey(source: KeySource, context: KeySourceContext): Promise<CryptoKey>;
171
+ //#endregion
172
+ //#region src/key/static.d.ts
173
+ export declare function staticKeys(keys: JWK[]): KeySource;
174
+ //#endregion
175
+ //#region src/issuer/types.d.ts
176
+ type IntrospectionOptions = {
177
+ /**
178
+ * Default: the issuer's discovered introspection_endpoint.
179
+ */
180
+ endpoint?: string;
181
+ authorization?: {
182
+ clientId: string;
183
+ clientSecret: string;
184
+ } | (() => string | Promise<string>);
185
+ /**
186
+ * Upper bound, in seconds, for caching an introspection result.
187
+ */
188
+ maxCacheTTL?: number;
189
+ };
190
+ type Issuer = {
191
+ id?: string;
192
+ /**
193
+ * A string matches `iss` exactly. A function sees UNVERIFIED claims:
194
+ * it only selects this config and never replaces verification.
195
+ */
196
+ issuer: string | ((claims: JWTPayload) => boolean);
197
+ /**
198
+ * Default: discovery() when issuer is a string.
199
+ */
200
+ keys?: KeySource;
201
+ /**
202
+ * Default: 'local'.
203
+ */
204
+ verification?: 'local' | 'remote';
205
+ introspection?: IntrospectionOptions;
206
+ audience?: string | string[];
207
+ /**
208
+ * Default: the resolved key's algorithm only. A JWK without `alg` is
209
+ * imported with the token header's `alg`, restricted to what its key
210
+ * type supports; set this to pin the algorithm.
211
+ */
212
+ algorithms?: string[];
213
+ typ?: string;
214
+ /**
215
+ * Seconds, default 0.
216
+ */
217
+ clockTolerance?: number;
218
+ /**
219
+ * Default: ['exp'].
220
+ */
221
+ requiredClaims?: string[];
222
+ claims?: (claims: JWTPayload) => boolean | Promise<boolean>;
223
+ };
224
+ //#endregion
225
+ //#region src/issuer/match.d.ts
226
+ /**
227
+ * Whether an issuer config trusts a token by its UNVERIFIED claims. This only
228
+ * selects a config: verification still runs against it afterwards. A
229
+ * function matcher counts only when it returns exactly `true`; one that
230
+ * throws, or returns anything else (a Promise included), does not match.
231
+ */
232
+ export declare function matchIssuer(issuer: Issuer, claims: JWTPayload): boolean;
233
+ /**
234
+ * The index of the first issuer that trusts the claims, or -1.
235
+ */
236
+ export declare function selectIssuer(issuers: Issuer[], claims: JWTPayload): number;
237
+ //#endregion
238
+ //#region src/introspection/module.d.ts
239
+ /**
240
+ * RFC 7662: asks the issuer's introspection endpoint about a token and
241
+ * answers the response as its claims. Claim rules are the caller's.
242
+ */
243
+ export declare function introspect(token: string, issuer: Issuer, fetchFn: typeof globalThis.fetch): Promise<JWTPayload>;
244
+ //#endregion
245
+ //#region src/introspection/types.d.ts
246
+ type IntrospectionResponse = {
247
+ active: boolean;
248
+ [key: string]: unknown;
249
+ };
250
+ //#endregion
251
+ //#region src/verifier/types.d.ts
252
+ type VerifierOptions = {
253
+ issuers: Issuer[];
254
+ /**
255
+ * Default: a MemoryTokenCache; false disables caching.
256
+ */
257
+ cache?: ITokenCache | false;
258
+ /**
259
+ * Names the group of verifiers sharing a cache passed in; required then.
260
+ * Every verifier using one namespace must have the same issuer
261
+ * configuration, since a cache hit skips the key lookup and the
262
+ * signature check. Must not contain NUL. The cache key is the SHA-256 of
263
+ * the namespace, a NUL character and the token.
264
+ */
265
+ cacheNamespace?: string;
266
+ /**
267
+ * Default: the global fetch.
268
+ */
269
+ fetch?: typeof fetch;
270
+ /**
271
+ * The Issuer.id that introspects tokens which are not compact JWTs.
272
+ */
273
+ opaque?: string;
274
+ };
275
+ type VerifyOptions = {
276
+ /**
277
+ * The presented client certificate's SHA-256 thumbprint (base64url), for
278
+ * RFC 8705 bound tokens. A provider is only invoked for a bound token.
279
+ */
280
+ certificateThumbprint?: string | (() => string | undefined | Promise<string | undefined>);
281
+ };
282
+ type VerifyResult = {
283
+ claims: JWTPayload;
284
+ issuer: Issuer;
285
+ source: 'local' | 'remote';
286
+ };
287
+ interface IVerifier {
288
+ verify(token: string, options?: VerifyOptions): Promise<VerifyResult>;
289
+ }
290
+ //#endregion
291
+ //#region src/verifier/binding.d.ts
292
+ /**
293
+ * RFC 8705: a token carrying `cnf` is certificate-bound and fails closed
294
+ * unless the presented thumbprint equals `cnf.x5t#S256`. A `cnf` this check
295
+ * cannot satisfy (no `x5t#S256`, e.g. a DPoP `jkt`) fails too.
296
+ */
297
+ export declare function assertCertificateBinding(claims: JWTPayload, thumbprint: string | undefined): void;
298
+ //#endregion
299
+ //#region src/verifier/module.d.ts
300
+ type IssuerRecord = {
301
+ /**
302
+ * Issuer.id, or the issuer's index when it has none; the cache entry's issuer.
303
+ */
304
+ name: string;
305
+ issuer: Issuer;
306
+ keys?: KeySource;
307
+ };
308
+ export declare class Verifier implements IVerifier {
309
+ protected records: IssuerRecord[];
310
+ protected cache: ITokenCache | undefined;
311
+ protected fetch: typeof fetch;
312
+ protected opaque: IssuerRecord | undefined;
313
+ protected cacheNamespace: string;
314
+ constructor(options: VerifierOptions);
315
+ verify(token: string, options?: VerifyOptions): Promise<VerifyResult>;
316
+ /**
317
+ * The claim sets whose `cnf` a result must satisfy: an introspected
318
+ * compact token is held to its own `cnf` as well as the response's.
319
+ */
320
+ protected bindingClaims(claims: JWTPayload, source: VerifyResult['source'], token: ParsedToken | undefined): JWTPayload[];
321
+ protected selectRecord(token: ParsedToken): IssuerRecord;
322
+ protected verifyLocal(token: ParsedToken, record: IssuerRecord): Promise<JWTPayload>;
323
+ protected assertClaimsPredicate(issuer: Issuer, claims: JWTPayload): Promise<void>;
324
+ /**
325
+ * Verifies a token by RFC 7662 introspection and applies the issuer's
326
+ * audience and claims predicate to the response.
327
+ */
328
+ protected verifyIntrospection(token: string, record: IssuerRecord): Promise<JWTPayload>;
329
+ protected introspect(token: string, key: string, record: IssuerRecord, options: VerifyOptions, parsed?: ParsedToken): Promise<VerifyResult>;
330
+ /**
331
+ * A cache failure is a miss: the token is verified again instead. An entry
332
+ * is only served under the record an uncached verify would pick, and only
333
+ * after this verifier's own rules that need no signature passed on it:
334
+ * a verifier sharing the cache may have applied other ones.
335
+ */
336
+ protected readCache(key: string, token: ParsedToken | undefined): Promise<{
337
+ entry: TokenCacheEntry;
338
+ record: IssuerRecord;
339
+ } | undefined>;
340
+ /**
341
+ * Caches until `exp`, measured to the millisecond, or for at most `maxTTL` seconds when given. A token
342
+ * without `exp` is cached only under a `maxTTL`. A cache failure is ignored.
343
+ */
344
+ protected writeCache(key: string, entry: TokenCacheEntry, exp: unknown, maxTTL?: number): Promise<void>;
345
+ }
346
+ export declare function createVerifier(options: VerifierOptions): Verifier;
347
+ //#endregion
348
+ export type { CachedKeysOptions, DiscoveryOptions, ITokenCache, IVerifier, IntrospectionOptions, IntrospectionResponse, Issuer, JWKSOptions, KeySource, KeySourceContext, MemoryTokenCacheOptions, ParsedToken, ProviderMetadata, TokenCacheEntry, VerifierOptions, VerifyOptions, VerifyResult, VouchlyErrorOptions };
349
+ //# sourceMappingURL=index.d.mts.map