@openid4vc/oauth2 0.3.1-alpha-20251127040522 → 0.4.0-alpha-20251127093634

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/dist/index.cjs DELETED
@@ -1,3093 +0,0 @@
1
- //#region rolldown:runtime
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __copyProps = (to, from, except, desc) => {
9
- if (from && typeof from === "object" || typeof from === "function") {
10
- for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
- key = keys[i];
12
- if (!__hasOwnProp.call(to, key) && key !== except) {
13
- __defProp(to, key, {
14
- get: ((k) => from[k]).bind(null, key),
15
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
16
- });
17
- }
18
- }
19
- }
20
- return to;
21
- };
22
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
23
- value: mod,
24
- enumerable: true
25
- }) : target, mod));
26
-
27
- //#endregion
28
- let __openid4vc_utils = require("@openid4vc/utils");
29
- let zod = require("zod");
30
- zod = __toESM(zod);
31
-
32
- //#region src/callbacks.ts
33
- /**
34
- * Supported hashing algorithms
35
- *
36
- * Based on https://www.iana.org/assignments/named-information/named-information.xhtml
37
- */
38
- let HashAlgorithm = /* @__PURE__ */ function(HashAlgorithm$1) {
39
- HashAlgorithm$1["Sha256"] = "sha-256";
40
- HashAlgorithm$1["Sha384"] = "sha-384";
41
- HashAlgorithm$1["Sha512"] = "sha-512";
42
- return HashAlgorithm$1;
43
- }({});
44
-
45
- //#endregion
46
- //#region src/error/Oauth2Error.ts
47
- var Oauth2Error = class extends Error {
48
- constructor(message, options) {
49
- const errorMessage = message ?? "Unknown error occurred.";
50
- const causeMessage = options?.cause instanceof Error ? ` ${options.cause.message}` : options?.cause ? ` ${options?.cause}` : "";
51
- super(`${errorMessage}${causeMessage}`);
52
- this.cause = options?.cause;
53
- }
54
- };
55
-
56
- //#endregion
57
- //#region src/common/jwk/jwk-thumbprint.ts
58
- const zJwkThumbprintComponents = zod.default.discriminatedUnion("kty", [
59
- zod.default.object({
60
- kty: zod.default.literal("EC"),
61
- crv: zod.default.string(),
62
- x: zod.default.string(),
63
- y: zod.default.string()
64
- }),
65
- zod.default.object({
66
- kty: zod.default.literal("OKP"),
67
- crv: zod.default.string(),
68
- x: zod.default.string()
69
- }),
70
- zod.default.object({
71
- kty: zod.default.literal("RSA"),
72
- e: zod.default.string(),
73
- n: zod.default.string()
74
- }),
75
- zod.default.object({
76
- kty: zod.default.literal("oct"),
77
- k: zod.default.string()
78
- })
79
- ]).transform((data) => {
80
- if (data.kty === "EC") return {
81
- crv: data.crv,
82
- kty: data.kty,
83
- x: data.x,
84
- y: data.y
85
- };
86
- if (data.kty === "OKP") return {
87
- crv: data.crv,
88
- kty: data.kty,
89
- x: data.x
90
- };
91
- if (data.kty === "RSA") return {
92
- e: data.e,
93
- kty: data.kty,
94
- n: data.n
95
- };
96
- if (data.kty === "oct") return {
97
- k: data.k,
98
- kty: data.kty
99
- };
100
- throw new Error("Unsupported kty");
101
- });
102
- async function calculateJwkThumbprint(options) {
103
- const jwkThumbprintComponents = (0, __openid4vc_utils.parseWithErrorHandling)(zJwkThumbprintComponents, options.jwk, `Provided jwk does not match a supported jwk structure. Either the 'kty' is not supported, or required values are missing.`);
104
- return (0, __openid4vc_utils.encodeToBase64Url)(await options.hashCallback((0, __openid4vc_utils.decodeUtf8String)(JSON.stringify(jwkThumbprintComponents)), options.hashAlgorithm));
105
- }
106
-
107
- //#endregion
108
- //#region src/common/jwk/jwks.ts
109
- /**
110
- *
111
- * @param header
112
- * @param jwks
113
- */
114
- function extractJwkFromJwksForJwt(options) {
115
- const jwksForUse = options.jwks.keys.filter(({ use }) => !use || use === options.use);
116
- const jwkForKid = options.kid ? jwksForUse.find(({ kid }) => kid === options.kid) : void 0;
117
- if (jwkForKid) return jwkForKid;
118
- if (jwksForUse.length === 1) return jwksForUse[0];
119
- throw new Oauth2Error(`Unable to extract jwk from jwks for use '${options.use}'${options.kid ? `with kid '${options.kid}'.` : ". No kid provided and more than jwk."}`);
120
- }
121
- async function isJwkInSet({ jwk, jwks, callbacks }) {
122
- const jwkThumbprint = await calculateJwkThumbprint({
123
- hashAlgorithm: HashAlgorithm.Sha256,
124
- hashCallback: callbacks.hash,
125
- jwk
126
- });
127
- for (const jwkFromSet of jwks) if (await calculateJwkThumbprint({
128
- hashAlgorithm: HashAlgorithm.Sha256,
129
- hashCallback: callbacks.hash,
130
- jwk: jwkFromSet
131
- }) === jwkThumbprint) return true;
132
- return false;
133
- }
134
-
135
- //#endregion
136
- //#region src/error/Oauth2JwtParseError.ts
137
- var Oauth2JwtParseError = class extends Oauth2Error {
138
- constructor(message) {
139
- super(message ?? "Error parsing jwt");
140
- }
141
- };
142
-
143
- //#endregion
144
- //#region src/common/jwk/z-jwk.ts
145
- const zJwk = zod.default.object({
146
- kty: zod.default.string(),
147
- crv: zod.default.optional(zod.default.string()),
148
- x: zod.default.optional(zod.default.string()),
149
- y: zod.default.optional(zod.default.string()),
150
- e: zod.default.optional(zod.default.string()),
151
- n: zod.default.optional(zod.default.string()),
152
- alg: zod.default.optional(zod.default.string()),
153
- d: zod.default.optional(zod.default.string()),
154
- dp: zod.default.optional(zod.default.string()),
155
- dq: zod.default.optional(zod.default.string()),
156
- ext: zod.default.optional(zod.default.boolean()),
157
- k: zod.default.optional(zod.default.string()),
158
- key_ops: zod.default.optional(zod.default.array(zod.default.string())),
159
- kid: zod.default.optional(zod.default.string()),
160
- oth: zod.default.optional(zod.default.array(zod.default.object({
161
- d: zod.default.optional(zod.default.string()),
162
- r: zod.default.optional(zod.default.string()),
163
- t: zod.default.optional(zod.default.string())
164
- }).loose())),
165
- p: zod.default.optional(zod.default.string()),
166
- q: zod.default.optional(zod.default.string()),
167
- qi: zod.default.optional(zod.default.string()),
168
- use: zod.default.optional(zod.default.string()),
169
- x5c: zod.default.optional(zod.default.array(zod.default.string())),
170
- x5t: zod.default.optional(zod.default.string()),
171
- "x5t#S256": zod.default.optional(zod.default.string()),
172
- x5u: zod.default.optional(zod.default.string())
173
- }).loose();
174
- const zJwkSet = zod.default.object({ keys: zod.default.array(zJwk) }).loose();
175
-
176
- //#endregion
177
- //#region src/common/z-common.ts
178
- const zAlgValueNotNone = zod.default.string().refine((alg) => alg !== "none", { message: `alg value may not be 'none'` });
179
-
180
- //#endregion
181
- //#region src/common/jwt/z-jwt.ts
182
- const zCompactJwt = zod.default.string().regex(/^([a-zA-Z0-9-_]+)\.([a-zA-Z0-9-_]+)\.([a-zA-Z0-9-_]+)$/, { message: "Not a valid compact jwt" });
183
- const zJwtConfirmationPayload = zod.default.object({
184
- jwk: zJwk.optional(),
185
- jkt: zod.default.string().optional()
186
- }).loose();
187
- const zJwtPayload = zod.default.object({
188
- iss: zod.default.string().optional(),
189
- aud: zod.default.union([zod.default.string(), zod.default.array(zod.default.string())]).optional(),
190
- iat: __openid4vc_utils.zInteger.optional(),
191
- exp: __openid4vc_utils.zInteger.optional(),
192
- nbf: __openid4vc_utils.zInteger.optional(),
193
- nonce: zod.default.string().optional(),
194
- jti: zod.default.string().optional(),
195
- sub: zod.default.string().optional(),
196
- cnf: zJwtConfirmationPayload.optional(),
197
- status: zod.default.record(zod.default.string(), zod.default.any()).optional(),
198
- trust_chain: zod.default.tuple([zod.default.string()], zod.default.string()).optional()
199
- }).loose();
200
- const zJwtHeader = zod.default.object({
201
- alg: zAlgValueNotNone,
202
- typ: zod.default.string().optional(),
203
- kid: zod.default.string().optional(),
204
- jwk: zJwk.optional(),
205
- x5c: zod.default.array(zod.default.string()).optional(),
206
- trust_chain: zod.default.tuple([zod.default.string()], zod.default.string()).optional()
207
- }).loose();
208
-
209
- //#endregion
210
- //#region src/common/jwt/decode-jwt-header.ts
211
- function decodeJwtHeader(options) {
212
- const jwtParts = options.jwt.split(".");
213
- if (jwtParts.length <= 2) throw new Oauth2JwtParseError("Jwt is not a valid jwt, unable to decode");
214
- let headerJson;
215
- try {
216
- headerJson = (0, __openid4vc_utils.stringToJsonWithErrorHandling)((0, __openid4vc_utils.encodeToUtf8String)((0, __openid4vc_utils.decodeBase64)(jwtParts[0])), "Unable to parse jwt header to JSON");
217
- } catch (error) {
218
- throw new Oauth2JwtParseError(`Error parsing JWT. ${error instanceof Error ? error.message : ""}`);
219
- }
220
- return { header: (0, __openid4vc_utils.parseWithErrorHandling)(options.headerSchema ?? zJwtHeader, headerJson) };
221
- }
222
-
223
- //#endregion
224
- //#region src/common/jwt/decode-jwt.ts
225
- function decodeJwt(options) {
226
- const jwtParts = options.jwt.split(".");
227
- if (jwtParts.length !== 3) throw new Oauth2JwtParseError("Jwt is not a valid jwt, unable to decode");
228
- let payloadJson;
229
- try {
230
- payloadJson = (0, __openid4vc_utils.stringToJsonWithErrorHandling)((0, __openid4vc_utils.encodeToUtf8String)((0, __openid4vc_utils.decodeBase64)(jwtParts[1])), "Unable to parse jwt payload to JSON");
231
- } catch (error) {
232
- throw new Oauth2JwtParseError(`Error parsing JWT. ${error instanceof Error ? error.message : ""}`);
233
- }
234
- const { header } = decodeJwtHeader({
235
- jwt: options.jwt,
236
- headerSchema: options.headerSchema
237
- });
238
- return {
239
- header,
240
- payload: (0, __openid4vc_utils.parseWithErrorHandling)(options.payloadSchema ?? zJwtPayload, payloadJson),
241
- signature: jwtParts[2],
242
- compact: options.jwt
243
- };
244
- }
245
- function jwtHeaderFromJwtSigner(signer) {
246
- if (signer.method === "did") return {
247
- alg: signer.alg,
248
- kid: signer.didUrl
249
- };
250
- if (signer.method === "federation") return {
251
- alg: signer.alg,
252
- kid: signer.kid,
253
- trust_chain: signer.trustChain
254
- };
255
- if (signer.method === "jwk") return {
256
- alg: signer.alg,
257
- jwk: signer.publicJwk
258
- };
259
- if (signer.method === "x5c") return {
260
- alg: signer.alg,
261
- x5c: signer.x5c
262
- };
263
- return { alg: signer.alg };
264
- }
265
- function jwtSignerFromJwt({ header, payload, allowedSignerMethods }) {
266
- const found = [];
267
- if (header.x5c) found.push({
268
- method: "x5c",
269
- valid: true,
270
- signer: {
271
- alg: header.alg,
272
- method: "x5c",
273
- x5c: header.x5c,
274
- kid: header.kid
275
- }
276
- });
277
- if (header.trust_chain) if (!header.kid) found.push({
278
- method: "federation",
279
- valid: false,
280
- error: `When 'trust_chain' is used in jwt header, the 'kid' parameter is required.`
281
- });
282
- else found.push({
283
- method: "federation",
284
- valid: true,
285
- signer: {
286
- alg: header.alg,
287
- trustChain: header.trust_chain,
288
- kid: header.kid,
289
- method: "federation"
290
- }
291
- });
292
- if (header.kid?.startsWith("did:") || payload.iss?.startsWith("did:")) if (payload.iss && header.kid?.startsWith("did:") && !header.kid.startsWith(payload.iss)) found.push({
293
- method: "did",
294
- valid: false,
295
- error: `kid in header starts with did that is different from did value in 'iss'`
296
- });
297
- else if (!header.kid?.startsWith("did:") && !header.kid?.startsWith("#")) found.push({
298
- method: "did",
299
- valid: false,
300
- error: `kid in header must start with either 'did:' or '#' when 'iss' value is a did`
301
- });
302
- else found.push({
303
- method: "did",
304
- valid: true,
305
- signer: {
306
- method: "did",
307
- alg: header.alg,
308
- didUrl: header.kid.startsWith("did:") ? header.kid : `${payload.iss}${header.kid}`
309
- }
310
- });
311
- if (header.jwk) found.push({
312
- method: "jwk",
313
- signer: {
314
- alg: header.alg,
315
- method: "jwk",
316
- publicJwk: header.jwk
317
- },
318
- valid: true
319
- });
320
- const allowedFoundMethods = found.filter((f) => !allowedSignerMethods || allowedSignerMethods?.includes(f.method));
321
- const allowedValidMethods = allowedFoundMethods.filter((f) => f.valid);
322
- if (allowedValidMethods.length > 0) return allowedValidMethods[0].signer;
323
- if (allowedFoundMethods.length > 0) throw new Oauth2Error(`Unable to extract signer method from jwt. Found ${allowedFoundMethods.length} allowed signer method(s) but contained invalid configuration:\n${allowedFoundMethods.map((m) => m.valid ? "" : `FAILED: method ${m.method} - ${m.error}`).join("\n")}`);
324
- if (found.length > 0) throw new Oauth2Error(`Unable to extract signer method from jwt. Found ${found.length} signer method(s) that are not allowed:\n${found.map((m) => m.valid ? `SUCCEEDED: method ${m.method}` : `FAILED: method ${m.method} - ${m.error}`).join("\n")}`);
325
- if (!allowedSignerMethods || allowedSignerMethods.includes("custom")) return {
326
- method: "custom",
327
- alg: header.alg,
328
- kid: header.kid
329
- };
330
- throw new Oauth2Error(`Unable to extract signer method from jwt. Found no signer methods and 'custom' signer method is not allowed.`);
331
- }
332
-
333
- //#endregion
334
- //#region src/error/Oauth2JwtVerificationError.ts
335
- var Oauth2JwtVerificationError = class extends Oauth2Error {
336
- constructor(message, options) {
337
- super(message ?? "Error verifiying jwt.", options);
338
- }
339
- };
340
-
341
- //#endregion
342
- //#region src/common/jwt/verify-jwt.ts
343
- async function verifyJwt(options) {
344
- const errorMessage = options.errorMessage ?? "Error during verification of jwt.";
345
- let signerJwk;
346
- try {
347
- const result = await options.verifyJwtCallback(options.signer, {
348
- header: options.header,
349
- payload: options.payload,
350
- compact: options.compact
351
- });
352
- if (!result.verified) throw new Oauth2JwtVerificationError(errorMessage);
353
- signerJwk = result.signerJwk;
354
- } catch (error) {
355
- if (error instanceof Oauth2JwtVerificationError) throw error;
356
- throw new Oauth2JwtVerificationError(errorMessage, { cause: error });
357
- }
358
- const nowInSeconds = (0, __openid4vc_utils.dateToSeconds)(options.now ?? /* @__PURE__ */ new Date());
359
- const skewInSeconds = options.allowedSkewInSeconds ?? 0;
360
- const timeBasedValidation = options.skipTimeBasedValidation !== void 0 ? !options.skipTimeBasedValidation : true;
361
- if (timeBasedValidation && options.payload.nbf && nowInSeconds < options.payload.nbf - skewInSeconds) throw new Oauth2JwtVerificationError(`${errorMessage} jwt 'nbf' is in the future`);
362
- if (timeBasedValidation && options.payload.exp && nowInSeconds > options.payload.exp + skewInSeconds) throw new Oauth2JwtVerificationError(`${errorMessage} jwt 'exp' is in the past`);
363
- if (options.expectedAudience) {
364
- if (Array.isArray(options.payload.aud) && !options.payload.aud.includes(options.expectedAudience) || typeof options.payload.aud === "string" && options.payload.aud !== options.expectedAudience) throw new Oauth2JwtVerificationError(`${errorMessage} jwt 'aud' does not match expected value.`);
365
- }
366
- if (options.expectedIssuer && options.expectedIssuer !== options.payload.iss) throw new Oauth2JwtVerificationError(`${errorMessage} jwt 'iss' does not match expected value.`);
367
- if (options.expectedNonce && options.expectedNonce !== options.payload.nonce) throw new Oauth2JwtVerificationError(`${errorMessage} jwt 'nonce' does not match expected value.`);
368
- if (options.expectedSubject && options.expectedSubject !== options.payload.sub) throw new Oauth2JwtVerificationError(`${errorMessage} jwt 'sub' does not match expected value.`);
369
- if (options.requiredClaims) {
370
- for (const claim of options.requiredClaims) if (!options.payload[claim]) throw new Oauth2JwtVerificationError(`${errorMessage} jwt '${claim}' is missing.`);
371
- }
372
- return { signer: {
373
- ...options.signer,
374
- publicJwk: signerJwk
375
- } };
376
- }
377
-
378
- //#endregion
379
- //#region ../utils/src/error/ValidationError.ts
380
- var ValidationError$1 = class extends Error {
381
- constructor(message, zodError) {
382
- super(message);
383
- this.message = `${message}\n${zodError ? zod.default.prettifyError(zodError) : ""}`;
384
- Object.defineProperty(this, "zodError", {
385
- value: zodError,
386
- writable: false,
387
- enumerable: false
388
- });
389
- }
390
- };
391
-
392
- //#endregion
393
- //#region src/metadata/fetch-jwks-uri.ts
394
- /**
395
- * Fetch JWKs from a provided JWKs URI.
396
- *
397
- * Returns validated metadata if successful response
398
- * Throws error otherwise
399
- *
400
- * @throws {ValidationError} if successful response but validation of response failed
401
- * @throws {InvalidFetchResponseError} if unsuccesful response
402
- */
403
- async function fetchJwks(jwksUrl, fetch) {
404
- const { result, response } = await (0, __openid4vc_utils.createZodFetcher)(fetch)(zJwkSet, [__openid4vc_utils.ContentType.JwkSet, __openid4vc_utils.ContentType.Json], jwksUrl);
405
- if (!response.ok) throw new __openid4vc_utils.InvalidFetchResponseError(`Fetching JWKs from jwks_uri '${jwksUrl}' resulted in an unsuccessful response with status code '${response.status}'.`, await response.clone().text(), response);
406
- if (!result?.success) throw new ValidationError$1(`Validation of JWKs from jwks_uri '${jwksUrl}' failed`, result?.error);
407
- return result.data;
408
- }
409
-
410
- //#endregion
411
- //#region src/access-token/z-access-token-jwt.ts
412
- const zAccessTokenProfileJwtHeader = zod.default.object({
413
- ...zJwtHeader.shape,
414
- typ: zod.default.enum(["application/at+jwt", "at+jwt"])
415
- }).loose();
416
- const zAccessTokenProfileJwtPayload = zod.default.object({
417
- ...zJwtPayload.shape,
418
- iss: zod.default.string(),
419
- exp: __openid4vc_utils.zInteger,
420
- iat: __openid4vc_utils.zInteger,
421
- aud: zod.default.union([zod.default.string(), zod.default.array(zod.default.string())]),
422
- sub: zod.default.string(),
423
- client_id: zod.default.optional(zod.default.string()),
424
- jti: zod.default.string(),
425
- scope: zod.default.optional(zod.default.string())
426
- }).loose();
427
-
428
- //#endregion
429
- //#region src/access-token/verify-access-token.ts
430
- let SupportedAuthenticationScheme = /* @__PURE__ */ function(SupportedAuthenticationScheme$1) {
431
- SupportedAuthenticationScheme$1["Bearer"] = "Bearer";
432
- SupportedAuthenticationScheme$1["DPoP"] = "DPoP";
433
- return SupportedAuthenticationScheme$1;
434
- }({});
435
- /**
436
- * Verify an access token as a JWT Profile access token.
437
- *
438
- * @throws {@link ValidationError} if the JWT header or payload does not align with JWT Profile rules
439
- * @throws {@link Oauth2JwtParseError} if the jwt is not a valid jwt format, or the jwt header/payload cannot be parsed as JSON
440
- * @throws {@link Oauth2JwtVerificationError} if the JWT verification fails (signature or nbf/exp)
441
- * @throws {@link Oauth2JwtVerificationError} if the JWT verification fails (signature or nbf/exp)
442
- */
443
- async function verifyJwtProfileAccessToken(options) {
444
- const decodedJwt = decodeJwt({
445
- jwt: options.accessToken,
446
- headerSchema: zAccessTokenProfileJwtHeader,
447
- payloadSchema: zAccessTokenProfileJwtPayload
448
- });
449
- const authorizationServer = options.authorizationServers.find(({ issuer }) => decodedJwt.payload.iss === issuer);
450
- if (!authorizationServer) throw new Oauth2Error(`Access token jwt contains unrecognized authorization server 'iss' value of '${decodedJwt.payload.iss}'`);
451
- const jwksUrl = authorizationServer.jwks_uri;
452
- if (!jwksUrl) throw new Oauth2Error(`Authorization server '${authorizationServer.issuer}' does not have a 'jwks_uri' parameter to fetch JWKs.`);
453
- const jwks = await fetchJwks(jwksUrl, options.callbacks.fetch);
454
- const publicJwk = extractJwkFromJwksForJwt({
455
- kid: decodedJwt.header.kid,
456
- jwks,
457
- use: "sig"
458
- });
459
- await verifyJwt({
460
- compact: options.accessToken,
461
- header: decodedJwt.header,
462
- payload: decodedJwt.payload,
463
- signer: {
464
- method: "jwk",
465
- publicJwk,
466
- alg: decodedJwt.header.alg
467
- },
468
- verifyJwtCallback: options.callbacks.verifyJwt,
469
- errorMessage: "Error during verification of access token jwt.",
470
- now: options.now,
471
- expectedAudience: options.resourceServer
472
- });
473
- return {
474
- header: decodedJwt.header,
475
- payload: decodedJwt.payload,
476
- authorizationServer
477
- };
478
- }
479
-
480
- //#endregion
481
- //#region src/common/z-oauth2-error.ts
482
- let Oauth2ErrorCodes = /* @__PURE__ */ function(Oauth2ErrorCodes$1) {
483
- Oauth2ErrorCodes$1["ServerError"] = "server_error";
484
- Oauth2ErrorCodes$1["InvalidTarget"] = "invalid_target";
485
- Oauth2ErrorCodes$1["InvalidRequest"] = "invalid_request";
486
- Oauth2ErrorCodes$1["InvalidToken"] = "invalid_token";
487
- Oauth2ErrorCodes$1["InsufficientScope"] = "insufficient_scope";
488
- Oauth2ErrorCodes$1["InvalidGrant"] = "invalid_grant";
489
- Oauth2ErrorCodes$1["InvalidClient"] = "invalid_client";
490
- Oauth2ErrorCodes$1["UnauthorizedClient"] = "unauthorized_client";
491
- Oauth2ErrorCodes$1["UnsupportedGrantType"] = "unsupported_grant_type";
492
- Oauth2ErrorCodes$1["InvalidScope"] = "invalid_scope";
493
- Oauth2ErrorCodes$1["InvalidDpopProof"] = "invalid_dpop_proof";
494
- Oauth2ErrorCodes$1["UseDpopNonce"] = "use_dpop_nonce";
495
- Oauth2ErrorCodes$1["RedirectToWeb"] = "redirect_to_web";
496
- Oauth2ErrorCodes$1["InvalidSession"] = "invalid_session";
497
- Oauth2ErrorCodes$1["InsufficientAuthorization"] = "insufficient_authorization";
498
- Oauth2ErrorCodes$1["InvalidCredentialRequest"] = "invalid_credential_request";
499
- Oauth2ErrorCodes$1["CredentialRequestDenied"] = "credential_request_denied";
500
- Oauth2ErrorCodes$1["InvalidProof"] = "invalid_proof";
501
- Oauth2ErrorCodes$1["InvalidNonce"] = "invalid_nonce";
502
- Oauth2ErrorCodes$1["InvalidEncryptionParameters"] = "invalid_encryption_parameters";
503
- Oauth2ErrorCodes$1["UnknownCredentialConfiguration"] = "unknown_credential_configuration";
504
- Oauth2ErrorCodes$1["UnknownCredentialIdentifier"] = "unknown_credential_identifier";
505
- Oauth2ErrorCodes$1["InvalidTransactionId"] = "invalid_transaction_id";
506
- Oauth2ErrorCodes$1["UnsupportedCredentialType"] = "unsupported_credential_type";
507
- Oauth2ErrorCodes$1["UnsupportedCredentialFormat"] = "unsupported_credential_format";
508
- Oauth2ErrorCodes$1["InvalidRequestUri"] = "invalid_request_uri";
509
- Oauth2ErrorCodes$1["InvalidRequestObject"] = "invalid_request_object";
510
- Oauth2ErrorCodes$1["RequestNotSupported"] = "request_not_supported";
511
- Oauth2ErrorCodes$1["RequestUriNotSupported"] = "request_uri_not_supported";
512
- Oauth2ErrorCodes$1["VpFormatsNotSupported"] = "vp_formats_not_supported";
513
- Oauth2ErrorCodes$1["AccessDenied"] = "access_denied";
514
- Oauth2ErrorCodes$1["InvalidPresentationDefinitionUri"] = "invalid_presentation_definition_uri";
515
- Oauth2ErrorCodes$1["InvalidPresentationDefinitionReference"] = "invalid_presentation_definition_reference";
516
- Oauth2ErrorCodes$1["InvalidRequestUriMethod"] = "invalid_request_uri_method";
517
- Oauth2ErrorCodes$1["InvalidTransactionData"] = "invalid_transaction_data";
518
- Oauth2ErrorCodes$1["WalletUnavailable"] = "wallet_unavailable";
519
- return Oauth2ErrorCodes$1;
520
- }({});
521
- const zOauth2ErrorResponse = zod.default.object({
522
- error: zod.default.union([zod.default.enum(Oauth2ErrorCodes), zod.default.string()]),
523
- error_description: zod.default.string().optional(),
524
- error_uri: zod.default.string().optional()
525
- }).loose();
526
-
527
- //#endregion
528
- //#region src/error/Oauth2ServerErrorResponseError.ts
529
- var Oauth2ServerErrorResponseError = class extends Oauth2Error {
530
- constructor(errorResponse, options) {
531
- super(`${options?.internalMessage ?? errorResponse.error_description}\n${JSON.stringify(errorResponse, null, 2)}`, options);
532
- this.errorResponse = errorResponse;
533
- this.status = options?.status ?? 400;
534
- }
535
- };
536
-
537
- //#endregion
538
- //#region src/common/jwt/z-jwe.ts
539
- const zCompactJwe = zod.z.string().regex(/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]*\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/, { message: "Not a valid compact jwe" });
540
-
541
- //#endregion
542
- //#region src/jar/z-jar-authorization-request.ts
543
- const zJarAuthorizationRequest = zod.z.object({
544
- request: zod.z.optional(zod.z.string()),
545
- request_uri: zod.z.optional(__openid4vc_utils.zHttpsUrl),
546
- client_id: zod.z.optional(zod.z.string())
547
- }).loose();
548
- function validateJarRequestParams(options) {
549
- const { jarRequestParams } = options;
550
- if (jarRequestParams.request && jarRequestParams.request_uri) throw new Oauth2ServerErrorResponseError({
551
- error: Oauth2ErrorCodes.InvalidRequestObject,
552
- error_description: "request and request_uri cannot both be present in a JAR request"
553
- });
554
- if (!jarRequestParams.request && !jarRequestParams.request_uri) throw new Oauth2ServerErrorResponseError({
555
- error: Oauth2ErrorCodes.InvalidRequestObject,
556
- error_description: "request or request_uri must be present"
557
- });
558
- return jarRequestParams;
559
- }
560
- function isJarAuthorizationRequest(request) {
561
- return "request" in request || "request_uri" in request;
562
- }
563
-
564
- //#endregion
565
- //#region src/jar/z-jar-request-object.ts
566
- const zJarRequestObjectPayload = zod.z.object({
567
- ...zJwtPayload.shape,
568
- client_id: zod.z.string()
569
- }).loose();
570
- const zSignedAuthorizationRequestJwtHeaderTyp = zod.z.literal("oauth-authz-req+jwt");
571
- const signedAuthorizationRequestJwtHeaderTyp = zSignedAuthorizationRequestJwtHeaderTyp.value;
572
- const zJwtAuthorizationRequestJwtHeaderTyp = zod.z.literal("jwt");
573
- const jwtAuthorizationRequestJwtHeaderTyp = zJwtAuthorizationRequestJwtHeaderTyp.value;
574
-
575
- //#endregion
576
- //#region src/jar/handle-jar-request/verify-jar-request.ts
577
- /**
578
- * Parse a JAR (JWT Secured Authorization Request) request by validating and optionally fetch from uri.
579
- *
580
- * @param options - The input parameters
581
- * @param options.jarRequestParams - The JAR authorization request parameters
582
- * @param options.callbacks - Context containing the relevant Jose crypto operations
583
- * @returns An object containing the transmission method ('value' or 'reference') and the JWT request object.
584
- */
585
- async function parseJarRequest(options) {
586
- const { callbacks } = options;
587
- const jarRequestParams = {
588
- ...validateJarRequestParams(options),
589
- ...options.jarRequestParams
590
- };
591
- return {
592
- sendBy: jarRequestParams.request ? "value" : "reference",
593
- authorizationRequestJwt: jarRequestParams.request ?? await fetchJarRequestObject({
594
- requestUri: jarRequestParams.request_uri,
595
- fetch: callbacks.fetch
596
- })
597
- };
598
- }
599
- /**
600
- * Verifies a JAR (JWT Secured Authorization Request) request by validating and verifying signatures.
601
- *
602
- * @param options - The input parameters
603
- * @param options.jarRequestParams - The JAR authorization request parameters
604
- * @param options.callbacks - Context containing the relevant Jose crypto operations
605
- * @returns The verified authorization request parameters and metadata
606
- */
607
- async function verifyJarRequest(options) {
608
- const { jarRequestParams, authorizationRequestJwt, callbacks, jwtSigner } = options;
609
- if (zCompactJwe.safeParse(authorizationRequestJwt).success) throw new Oauth2ServerErrorResponseError({
610
- error: Oauth2ErrorCodes.InvalidRequestObject,
611
- error_description: "Encrypted JWE request objects are not supported."
612
- });
613
- if (!zCompactJwt.safeParse(authorizationRequestJwt).success) throw new Oauth2ServerErrorResponseError({
614
- error: Oauth2ErrorCodes.InvalidRequestObject,
615
- error_description: "JAR request object is not a valid JWT."
616
- });
617
- const { authorizationRequestPayload, signer, jwt } = await verifyJarRequestObject({
618
- authorizationRequestJwt,
619
- callbacks,
620
- jwtSigner
621
- });
622
- if (!authorizationRequestPayload.client_id) throw new Oauth2ServerErrorResponseError({
623
- error: Oauth2ErrorCodes.InvalidRequestObject,
624
- error_description: "Jar Request Object is missing the required \"client_id\" field."
625
- });
626
- if (jarRequestParams.client_id !== authorizationRequestPayload.client_id) throw new Oauth2ServerErrorResponseError({
627
- error: Oauth2ErrorCodes.InvalidRequest,
628
- error_description: "client_id does not match the request object client_id."
629
- });
630
- return {
631
- jwt,
632
- authorizationRequestPayload,
633
- signer
634
- };
635
- }
636
- async function fetchJarRequestObject(options) {
637
- const { requestUri, fetch } = options;
638
- const response = await (0, __openid4vc_utils.createFetcher)(fetch)(requestUri, {
639
- method: "get",
640
- headers: {
641
- Accept: `${__openid4vc_utils.ContentType.OAuthAuthorizationRequestJwt}, ${__openid4vc_utils.ContentType.Jwt};q=0.9, text/plain`,
642
- "Content-Type": __openid4vc_utils.ContentType.XWwwFormUrlencoded
643
- }
644
- }).catch(() => {
645
- throw new Oauth2ServerErrorResponseError({
646
- error_description: `Fetching request_object from request_uri '${requestUri}' failed`,
647
- error: Oauth2ErrorCodes.InvalidRequestUri
648
- });
649
- });
650
- if (!response.ok) throw new Oauth2ServerErrorResponseError({
651
- error_description: `Fetching request_object from request_uri '${requestUri}' failed with status code '${response.status}'.`,
652
- error: Oauth2ErrorCodes.InvalidRequestUri
653
- });
654
- return await response.text();
655
- }
656
- async function verifyJarRequestObject(options) {
657
- const { authorizationRequestJwt, callbacks, jwtSigner } = options;
658
- const jwt = decodeJwt({
659
- jwt: authorizationRequestJwt,
660
- payloadSchema: zJarRequestObjectPayload
661
- });
662
- const { signer } = await verifyJwt({
663
- verifyJwtCallback: callbacks.verifyJwt,
664
- compact: authorizationRequestJwt,
665
- header: jwt.header,
666
- payload: jwt.payload,
667
- signer: jwtSigner
668
- });
669
- if (jwt.header.typ !== signedAuthorizationRequestJwtHeaderTyp && jwt.header.typ !== jwtAuthorizationRequestJwtHeaderTyp) throw new Oauth2ServerErrorResponseError({
670
- error: Oauth2ErrorCodes.InvalidRequestObject,
671
- error_description: `Invalid Jar Request Object typ header. Expected "oauth-authz-req+jwt" or "jwt", received "${jwt.header.typ}".`
672
- });
673
- return {
674
- signer,
675
- jwt,
676
- authorizationRequestPayload: jwt.payload
677
- };
678
- }
679
-
680
- //#endregion
681
- //#region src/client-attestation/z-client-attestation.ts
682
- const zOauthClientAttestationHeader = zod.default.literal("OAuth-Client-Attestation");
683
- const oauthClientAttestationHeader = zOauthClientAttestationHeader.value;
684
- const zClientAttestationJwtPayload = zod.default.object({
685
- ...zJwtPayload.shape,
686
- iss: zod.default.string(),
687
- sub: zod.default.string(),
688
- exp: __openid4vc_utils.zInteger,
689
- cnf: zod.default.object({ jwk: zJwk }).loose(),
690
- wallet_name: zod.default.string().optional(),
691
- wallet_link: zod.default.url().optional()
692
- }).loose();
693
- const zClientAttestationJwtHeader = zod.default.object({
694
- ...zJwtHeader.shape,
695
- typ: zod.default.literal("oauth-client-attestation+jwt")
696
- }).loose();
697
- const zOauthClientAttestationPopHeader = zod.default.literal("OAuth-Client-Attestation-PoP");
698
- const oauthClientAttestationPopHeader = zOauthClientAttestationPopHeader.value;
699
- const zClientAttestationPopJwtPayload = zod.default.object({
700
- ...zJwtPayload.shape,
701
- iss: zod.default.string(),
702
- exp: __openid4vc_utils.zInteger,
703
- aud: zod.default.union([__openid4vc_utils.zHttpsUrl, zod.default.array(__openid4vc_utils.zHttpsUrl)]),
704
- jti: zod.default.string(),
705
- nonce: zod.default.optional(zod.default.string())
706
- }).loose();
707
- const zClientAttestationPopJwtHeader = zod.default.object({
708
- ...zJwtHeader.shape,
709
- typ: zod.default.literal("oauth-client-attestation-pop+jwt")
710
- }).loose();
711
-
712
- //#endregion
713
- //#region src/client-attestation/client-attestation-pop.ts
714
- async function verifyClientAttestationPopJwt(options) {
715
- const { header, payload } = decodeJwt({
716
- jwt: options.clientAttestationPopJwt,
717
- headerSchema: zClientAttestationPopJwtHeader,
718
- payloadSchema: zClientAttestationPopJwtPayload
719
- });
720
- if (payload.iss !== options.clientAttestation.payload.sub) throw new Oauth2Error(`Client Attestation Pop jwt contains 'iss' (client_id) value '${payload.iss}', but expected 'sub' value from client attestation '${options.clientAttestation.payload.sub}'`);
721
- const { signer } = await verifyJwt({
722
- signer: {
723
- alg: header.alg,
724
- method: "jwk",
725
- publicJwk: options.clientAttestation.payload.cnf.jwk
726
- },
727
- now: options.now,
728
- header,
729
- expectedNonce: options.expectedNonce,
730
- payload,
731
- expectedAudience: options.authorizationServer,
732
- compact: options.clientAttestationPopJwt,
733
- verifyJwtCallback: options.callbacks.verifyJwt,
734
- errorMessage: "client attestation pop jwt verification failed"
735
- });
736
- return {
737
- header,
738
- payload,
739
- signer
740
- };
741
- }
742
- async function createClientAttestationPopJwt(options) {
743
- const clientAttestation = decodeJwt({
744
- jwt: options.clientAttestation,
745
- headerSchema: zClientAttestationJwtHeader,
746
- payloadSchema: zClientAttestationJwtPayload
747
- });
748
- const signer = options.signer ?? {
749
- method: "jwk",
750
- alg: clientAttestation.header.alg,
751
- publicJwk: clientAttestation.payload.cnf.jwk
752
- };
753
- const header = (0, __openid4vc_utils.parseWithErrorHandling)(zClientAttestationPopJwtHeader, {
754
- typ: "oauth-client-attestation-pop+jwt",
755
- alg: signer.alg
756
- });
757
- const expiresAt = options.expiresAt ?? (0, __openid4vc_utils.addSecondsToDate)(options.issuedAt ?? /* @__PURE__ */ new Date(), 60);
758
- const payload = (0, __openid4vc_utils.parseWithErrorHandling)(zClientAttestationPopJwtPayload, {
759
- aud: options.authorizationServer,
760
- iss: clientAttestation.payload.sub,
761
- iat: (0, __openid4vc_utils.dateToSeconds)(options.issuedAt),
762
- exp: (0, __openid4vc_utils.dateToSeconds)(expiresAt),
763
- jti: (0, __openid4vc_utils.encodeToBase64Url)(await options.callbacks.generateRandom(32)),
764
- nonce: options.nonce,
765
- ...options.additionalPayload
766
- });
767
- const { jwt } = await options.callbacks.signJwt(signer, {
768
- header,
769
- payload
770
- });
771
- return jwt;
772
- }
773
-
774
- //#endregion
775
- //#region src/client-attestation/client-attestation.ts
776
- async function verifyClientAttestationJwt(options) {
777
- const { header, payload } = decodeJwt({
778
- jwt: options.clientAttestationJwt,
779
- headerSchema: zClientAttestationJwtHeader,
780
- payloadSchema: zClientAttestationJwtPayload
781
- });
782
- const { signer } = await verifyJwt({
783
- signer: jwtSignerFromJwt({
784
- header,
785
- payload
786
- }),
787
- now: options.now,
788
- header,
789
- payload,
790
- compact: options.clientAttestationJwt,
791
- verifyJwtCallback: options.callbacks.verifyJwt,
792
- errorMessage: "client attestation jwt verification failed."
793
- });
794
- return {
795
- header,
796
- payload,
797
- signer
798
- };
799
- }
800
- async function createClientAttestationJwt(options) {
801
- const header = (0, __openid4vc_utils.parseWithErrorHandling)(zClientAttestationJwtHeader, {
802
- typ: "oauth-client-attestation+jwt",
803
- ...jwtHeaderFromJwtSigner(options.signer)
804
- });
805
- const payload = (0, __openid4vc_utils.parseWithErrorHandling)(zClientAttestationJwtPayload, {
806
- iss: options.issuer,
807
- iat: (0, __openid4vc_utils.dateToSeconds)(options.issuedAt),
808
- exp: (0, __openid4vc_utils.dateToSeconds)(options.expiresAt),
809
- sub: options.clientId,
810
- cnf: options.confirmation,
811
- ...options.additionalPayload
812
- });
813
- const { jwt } = await options.callbacks.signJwt(options.signer, {
814
- header,
815
- payload
816
- });
817
- return jwt;
818
- }
819
- function extractClientAttestationJwtsFromHeaders(headers) {
820
- const clientAttestationHeader = headers.get(oauthClientAttestationHeader);
821
- const clientAttestationPopHeader = headers.get(oauthClientAttestationPopHeader);
822
- if (!clientAttestationHeader && !clientAttestationPopHeader) return { valid: true };
823
- if (!clientAttestationHeader || !clientAttestationPopHeader) return { valid: false };
824
- if (!zCompactJwt.safeParse(clientAttestationHeader).success || !zCompactJwt.safeParse(clientAttestationPopHeader).success) return { valid: false };
825
- return {
826
- valid: true,
827
- clientAttestationPopHeader,
828
- clientAttestationHeader
829
- };
830
- }
831
- async function verifyClientAttestation({ authorizationServer, clientAttestationJwt, clientAttestationPopJwt, callbacks, now }) {
832
- try {
833
- const clientAttestation = await verifyClientAttestationJwt({
834
- callbacks,
835
- clientAttestationJwt,
836
- now
837
- });
838
- return {
839
- clientAttestation,
840
- clientAttestationPop: await verifyClientAttestationPopJwt({
841
- callbacks,
842
- authorizationServer,
843
- clientAttestation,
844
- clientAttestationPopJwt,
845
- now
846
- })
847
- };
848
- } catch (error) {
849
- if (error instanceof Oauth2Error) throw new Oauth2ServerErrorResponseError({
850
- error: Oauth2ErrorCodes.InvalidClient,
851
- error_description: `Error verifying client attestation. ${error.message}`
852
- }, {
853
- status: 401,
854
- cause: error
855
- });
856
- throw new Oauth2ServerErrorResponseError({
857
- error: Oauth2ErrorCodes.ServerError,
858
- error_description: "Error during verification of client attestation jwt"
859
- }, {
860
- status: 500,
861
- cause: error,
862
- internalMessage: "Unknown error thrown during verification of client attestation jwt"
863
- });
864
- }
865
- }
866
-
867
- //#endregion
868
- //#region src/dpop/z-dpop.ts
869
- const zDpopJwtPayload = zod.default.object({
870
- ...zJwtPayload.shape,
871
- iat: __openid4vc_utils.zInteger,
872
- htu: __openid4vc_utils.zHttpsUrl,
873
- htm: __openid4vc_utils.zHttpMethod,
874
- jti: zod.default.string(),
875
- ath: zod.default.optional(zod.default.string())
876
- }).loose();
877
- const zDpopJwtHeader = zod.default.object({
878
- ...zJwtHeader.shape,
879
- typ: zod.default.literal("dpop+jwt"),
880
- jwk: zJwk
881
- }).loose();
882
-
883
- //#endregion
884
- //#region src/dpop/dpop.ts
885
- async function createDpopHeadersForRequest(options) {
886
- return { DPoP: await createDpopJwt(options) };
887
- }
888
- async function createDpopJwt(options) {
889
- let ath;
890
- if (options.accessToken) ath = (0, __openid4vc_utils.encodeToBase64Url)(await options.callbacks.hash((0, __openid4vc_utils.decodeUtf8String)(options.accessToken), HashAlgorithm.Sha256));
891
- const header = (0, __openid4vc_utils.parseWithErrorHandling)(zDpopJwtHeader, {
892
- typ: "dpop+jwt",
893
- jwk: options.signer.publicJwk,
894
- alg: options.signer.alg
895
- });
896
- const payload = (0, __openid4vc_utils.parseWithErrorHandling)(zDpopJwtPayload, {
897
- htu: htuFromRequestUrl(options.request.url),
898
- iat: (0, __openid4vc_utils.dateToSeconds)(options.issuedAt),
899
- htm: options.request.method,
900
- jti: (0, __openid4vc_utils.encodeToBase64Url)(await options.callbacks.generateRandom(32)),
901
- ath,
902
- nonce: options.nonce,
903
- ...options.additionalPayload
904
- });
905
- const { jwt } = await options.callbacks.signJwt(options.signer, {
906
- header,
907
- payload
908
- });
909
- return jwt;
910
- }
911
- async function verifyDpopJwt(options) {
912
- try {
913
- const { header, payload } = decodeJwt({
914
- jwt: options.dpopJwt,
915
- headerSchema: zDpopJwtHeader,
916
- payloadSchema: zDpopJwtPayload
917
- });
918
- if (options.allowedSigningAlgs && !options.allowedSigningAlgs.includes(header.alg)) throw new Oauth2Error(`dpop jwt uses alg value '${header.alg}' but allowed dpop signging alg values are ${options.allowedSigningAlgs.join(", ")}.`);
919
- if (options.expectedNonce) {
920
- if (!payload.nonce) throw new Oauth2Error(`Dpop jwt does not have a nonce value, but expected nonce value '${options.expectedNonce}'`);
921
- if (payload.nonce !== options.expectedNonce) throw new Oauth2Error(`Dpop jwt contains nonce value '${payload.nonce}', but expected nonce value '${options.expectedNonce}'`);
922
- }
923
- if (options.request.method !== payload.htm) throw new Oauth2Error(`Dpop jwt contains htm value '${payload.htm}', but expected htm value '${options.request.method}'`);
924
- const expectedHtu = htuFromRequestUrl(options.request.url);
925
- if (expectedHtu !== payload.htu) throw new Oauth2Error(`Dpop jwt contains htu value '${payload.htu}', but expected htu value '${expectedHtu}'.`);
926
- if (options.accessToken) {
927
- const expectedAth = (0, __openid4vc_utils.encodeToBase64Url)(await options.callbacks.hash((0, __openid4vc_utils.decodeUtf8String)(options.accessToken), HashAlgorithm.Sha256));
928
- if (!payload.ath) throw new Oauth2Error(`Dpop jwt does not have a ath value, but expected ath value '${expectedAth}'.`);
929
- if (payload.ath !== expectedAth) throw new Oauth2Error(`Dpop jwt contains ath value '${payload.ath}', but expected ath value '${expectedAth}'.`);
930
- }
931
- const jwkThumbprint = await calculateJwkThumbprint({
932
- hashAlgorithm: HashAlgorithm.Sha256,
933
- hashCallback: options.callbacks.hash,
934
- jwk: header.jwk
935
- });
936
- if (options.expectedJwkThumbprint && options.expectedJwkThumbprint !== jwkThumbprint) throw new Oauth2Error(`Dpop is signed with jwk with thumbprint value '${jwkThumbprint}', but expect jwk thumbprint value '${options.expectedJwkThumbprint}'`);
937
- await verifyJwt({
938
- signer: {
939
- alg: header.alg,
940
- method: "jwk",
941
- publicJwk: header.jwk
942
- },
943
- now: options.now,
944
- header,
945
- payload,
946
- compact: options.dpopJwt,
947
- verifyJwtCallback: options.callbacks.verifyJwt,
948
- errorMessage: "dpop jwt verification failed"
949
- });
950
- return {
951
- header,
952
- payload,
953
- jwkThumbprint
954
- };
955
- } catch (error) {
956
- if (error instanceof Oauth2Error) throw new Oauth2ServerErrorResponseError({
957
- error: Oauth2ErrorCodes.InvalidDpopProof,
958
- error_description: error.message
959
- });
960
- throw error;
961
- }
962
- }
963
- function htuFromRequestUrl(requestUrl) {
964
- const htu = new __openid4vc_utils.URL(requestUrl);
965
- htu.search = "";
966
- htu.hash = "";
967
- return htu.toString();
968
- }
969
- function extractDpopNonceFromHeaders(headers) {
970
- return headers.get("DPoP-Nonce");
971
- }
972
- function extractDpopJwtFromHeaders(headers) {
973
- const dpopJwt = headers.get("DPoP");
974
- if (!dpopJwt) return { valid: true };
975
- if (!zCompactJwt.safeParse(dpopJwt).success) return { valid: false };
976
- return {
977
- valid: true,
978
- dpopJwt
979
- };
980
- }
981
-
982
- //#endregion
983
- //#region src/authorization-request/parse-authorization-request.ts
984
- /**
985
- * Parse an authorization request.
986
- *
987
- * @throws {Oauth2ServerErrorResponseError}
988
- */
989
- function parseAuthorizationRequest(options) {
990
- const extractedDpopJwt = extractDpopJwtFromHeaders(options.request.headers);
991
- if (!extractedDpopJwt.valid) throw new Oauth2ServerErrorResponseError({
992
- error: Oauth2ErrorCodes.InvalidDpopProof,
993
- error_description: `Request contains a 'DPoP' header, but the value is not a valid DPoP jwt`
994
- });
995
- const extractedClientAttestationJwts = extractClientAttestationJwtsFromHeaders(options.request.headers);
996
- if (!extractedClientAttestationJwts.valid) throw new Oauth2ServerErrorResponseError({
997
- error: Oauth2ErrorCodes.InvalidClient,
998
- error_description: "Request contains client attestation header, but the values are not valid client attestation and client attestation PoP header."
999
- });
1000
- return {
1001
- dpop: extractedDpopJwt.dpopJwt ? {
1002
- jwt: extractedDpopJwt.dpopJwt,
1003
- jwkThumbprint: options.authorizationRequest.dpop_jkt
1004
- } : options.authorizationRequest.dpop_jkt ? {
1005
- jwt: extractedDpopJwt.dpopJwt,
1006
- jwkThumbprint: options.authorizationRequest.dpop_jkt
1007
- } : void 0,
1008
- clientAttestation: extractedClientAttestationJwts.clientAttestationHeader ? {
1009
- clientAttestationJwt: extractedClientAttestationJwts.clientAttestationHeader,
1010
- clientAttestationPopJwt: extractedClientAttestationJwts.clientAttestationPopHeader
1011
- } : void 0
1012
- };
1013
- }
1014
-
1015
- //#endregion
1016
- //#region src/authorization-request/z-authorization-request.ts
1017
- const zPushedAuthorizationRequestUriPrefix = zod.default.literal("urn:ietf:params:oauth:request_uri:");
1018
- const pushedAuthorizationRequestUriPrefix = zPushedAuthorizationRequestUriPrefix.value;
1019
- const zAuthorizationRequest = zod.default.object({
1020
- response_type: zod.default.string(),
1021
- client_id: zod.default.string(),
1022
- issuer_state: zod.default.optional(zod.default.string()),
1023
- redirect_uri: zod.default.url().optional(),
1024
- resource: zod.default.optional(__openid4vc_utils.zHttpsUrl),
1025
- scope: zod.default.optional(zod.default.string()),
1026
- state: zod.default.optional(zod.default.string()),
1027
- dpop_jkt: zod.default.optional(zod.default.base64url()),
1028
- code_challenge: zod.default.optional(zod.default.string()),
1029
- code_challenge_method: zod.default.optional(zod.default.string())
1030
- }).loose();
1031
- const zPushedAuthorizationRequest = zod.default.object({
1032
- request_uri: zod.default.string(),
1033
- client_id: zod.default.string()
1034
- }).loose();
1035
- const zPushedAuthorizationResponse = zod.default.object({
1036
- request_uri: zod.default.string(),
1037
- expires_in: zod.default.number().int()
1038
- }).loose();
1039
-
1040
- //#endregion
1041
- //#region src/authorization-request/parse-pushed-authorization-request.ts
1042
- /**
1043
- * Parse an pushed authorization request.
1044
- *
1045
- * @throws {Oauth2ServerErrorResponseError}
1046
- */
1047
- async function parsePushedAuthorizationRequest(options) {
1048
- const parsed = (0, __openid4vc_utils.parseWithErrorHandling)(zod.default.union([zAuthorizationRequest, zJarAuthorizationRequest]), options.authorizationRequest, "Invalid authorization request. Could not parse authorization request or jar.");
1049
- let parsedAuthorizationRequest;
1050
- let authorizationRequestJwt;
1051
- if (isJarAuthorizationRequest(parsed)) {
1052
- const parsedJar = await parseJarRequest({
1053
- jarRequestParams: parsed,
1054
- callbacks: options.callbacks
1055
- });
1056
- const jwt = decodeJwt({ jwt: parsedJar.authorizationRequestJwt });
1057
- parsedAuthorizationRequest = zAuthorizationRequest.safeParse(jwt.payload);
1058
- if (!parsedAuthorizationRequest.success) throw new Oauth2ServerErrorResponseError({
1059
- error: Oauth2ErrorCodes.InvalidRequest,
1060
- error_description: `Invalid authorization request. Could not parse jar request payload.\n${(0, __openid4vc_utils.formatZodError)(parsedAuthorizationRequest.error)}`
1061
- });
1062
- authorizationRequestJwt = parsedJar.authorizationRequestJwt;
1063
- } else {
1064
- parsedAuthorizationRequest = zAuthorizationRequest.safeParse(options.authorizationRequest);
1065
- if (!parsedAuthorizationRequest.success) throw new Oauth2ServerErrorResponseError({
1066
- error: Oauth2ErrorCodes.InvalidRequest,
1067
- error_description: `Error occurred during validation of pushed authorization request.\n${(0, __openid4vc_utils.formatZodError)(parsedAuthorizationRequest.error)}`
1068
- });
1069
- }
1070
- const authorizationRequest = parsedAuthorizationRequest.data;
1071
- const { clientAttestation, dpop } = parseAuthorizationRequest({
1072
- authorizationRequest,
1073
- request: options.request
1074
- });
1075
- return {
1076
- authorizationRequest,
1077
- authorizationRequestJwt,
1078
- dpop,
1079
- clientAttestation
1080
- };
1081
- }
1082
- /**
1083
- * Parse a pushed authorization request URI prefixed with `urn:ietf:params:oauth:request_uri:`
1084
- * and returns the identifier, without the prefix.
1085
- *
1086
- * @throws {Oauth2ServerErrorResponseError}
1087
- */
1088
- function parsePushedAuthorizationRequestUriReferenceValue(options) {
1089
- if (!options.uri.startsWith(pushedAuthorizationRequestUriPrefix)) throw new Oauth2ServerErrorResponseError({
1090
- error: Oauth2ErrorCodes.InvalidRequest,
1091
- error_description: `The 'request_uri' must start with the prefix "${pushedAuthorizationRequestUriPrefix}".`
1092
- });
1093
- return options.uri.substring(pushedAuthorizationRequestUriPrefix.length);
1094
- }
1095
-
1096
- //#endregion
1097
- //#region src/authorization-response/z-authorization-response.ts
1098
- const zAuthorizationResponse = zod.default.object({
1099
- state: zod.default.string().optional(),
1100
- code: zod.default.string().nonempty(),
1101
- error: zod.default.optional(zod.default.never())
1102
- }).loose();
1103
- const zAuthorizationResponseFromUriParams = zod.default.url().transform((url) => Object.fromEntries(new __openid4vc_utils.URL(url).searchParams)).pipe(zAuthorizationResponse);
1104
- const zAuthorizationErrorResponse = zod.default.object({
1105
- ...zOauth2ErrorResponse.shape,
1106
- state: zod.default.string().optional(),
1107
- code: zod.default.optional(zod.default.never())
1108
- }).loose();
1109
-
1110
- //#endregion
1111
- //#region src/authorization-response/parse-authorization-response.ts
1112
- /**
1113
- * Parse an authorization response redirect URL.
1114
- *
1115
- * @throws {Oauth2ServerErrorResponseError}
1116
- */
1117
- function parseAuthorizationResponseRedirectUrl(options) {
1118
- const searchParams = Object.fromEntries(new __openid4vc_utils.URL(options.url).searchParams);
1119
- const parsedAuthorizationResponse = zod.default.union([zAuthorizationErrorResponse, zAuthorizationResponse]).safeParse(searchParams);
1120
- if (!parsedAuthorizationResponse.success) throw new Oauth2ServerErrorResponseError({
1121
- error: Oauth2ErrorCodes.InvalidRequest,
1122
- error_description: `Error occurred during validation of authorization response redirect URL.\n${(0, __openid4vc_utils.formatZodError)(parsedAuthorizationResponse.error)}`
1123
- });
1124
- return parsedAuthorizationResponse.data;
1125
- }
1126
-
1127
- //#endregion
1128
- //#region src/z-grant-type.ts
1129
- const zPreAuthorizedCodeGrantIdentifier = zod.default.literal("urn:ietf:params:oauth:grant-type:pre-authorized_code");
1130
- const preAuthorizedCodeGrantIdentifier = zPreAuthorizedCodeGrantIdentifier.value;
1131
- const zAuthorizationCodeGrantIdentifier = zod.default.literal("authorization_code");
1132
- const authorizationCodeGrantIdentifier = zAuthorizationCodeGrantIdentifier.value;
1133
- const zRefreshTokenGrantIdentifier = zod.default.literal("refresh_token");
1134
- const refreshTokenGrantIdentifier = zRefreshTokenGrantIdentifier.value;
1135
-
1136
- //#endregion
1137
- //#region src/client-authentication.ts
1138
- let SupportedClientAuthenticationMethod = /* @__PURE__ */ function(SupportedClientAuthenticationMethod$1) {
1139
- SupportedClientAuthenticationMethod$1["ClientSecretBasic"] = "client_secret_basic";
1140
- SupportedClientAuthenticationMethod$1["ClientSecretPost"] = "client_secret_post";
1141
- SupportedClientAuthenticationMethod$1["ClientAttestationJwt"] = "attest_jwt_client_auth";
1142
- SupportedClientAuthenticationMethod$1["None"] = "none";
1143
- return SupportedClientAuthenticationMethod$1;
1144
- }({});
1145
- /**
1146
- * Determine the supported client authentication method based on authorization
1147
- * server metadata
1148
- */
1149
- function getSupportedClientAuthenticationMethod(authorizationServer, endpointType) {
1150
- if (endpointType === "introspection" && authorizationServer.introspection_endpoint_auth_methods_supported) {
1151
- const supportedMethod = authorizationServer.introspection_endpoint_auth_methods_supported.find((m) => Object.values(SupportedClientAuthenticationMethod).includes(m));
1152
- if (!supportedMethod) throw new Oauth2Error(`Authorization server metadata for issuer '${authorizationServer.issuer}' has 'introspection_endpoint_auth_methods_supported' metadata, but does not contain a supported value. Supported values are '${Object.values(SupportedClientAuthenticationMethod).join(", ")}', found values are '${authorizationServer.introspection_endpoint_auth_methods_supported.join(", ")}'`);
1153
- return supportedMethod;
1154
- }
1155
- if (authorizationServer.token_endpoint_auth_methods_supported) {
1156
- const supportedMethod = authorizationServer.token_endpoint_auth_methods_supported.find((m) => Object.values(SupportedClientAuthenticationMethod).includes(m));
1157
- if (!supportedMethod) throw new Oauth2Error(`Authorization server metadata for issuer '${authorizationServer.issuer}' has 'token_endpoint_auth_methods_supported' metadata, but does not contain a supported value. Supported values are '${Object.values(SupportedClientAuthenticationMethod).join(", ")}', found values are '${authorizationServer.token_endpoint_auth_methods_supported.join(", ")}'`);
1158
- return supportedMethod;
1159
- }
1160
- return SupportedClientAuthenticationMethod.ClientSecretBasic;
1161
- }
1162
- /**
1163
- * Dynamicaly get the client authentication method based on endpoint type and authorization server.
1164
- * Only `client_secret_post`, `client_secret_basic`, and `none` supported.
1165
- *
1166
- * It also supports anonymous access to the token endpoint for pre-authorized code flow
1167
- * if the authorization server has enabled `pre-authorized_grant_anonymous_access_supported`
1168
- */
1169
- function clientAuthenticationDynamic(options) {
1170
- return (callbackOptions) => {
1171
- const { url, authorizationServerMetadata, body } = callbackOptions;
1172
- const endpointType = url === authorizationServerMetadata.introspection_endpoint ? "introspection" : url === authorizationServerMetadata.token_endpoint ? "token" : "endpoint";
1173
- const method = getSupportedClientAuthenticationMethod(authorizationServerMetadata, endpointType);
1174
- if (endpointType === "token" && body.grant_type === preAuthorizedCodeGrantIdentifier && authorizationServerMetadata["pre-authorized_grant_anonymous_access_supported"]) return clientAuthenticationAnonymous()(callbackOptions);
1175
- if (method === SupportedClientAuthenticationMethod.ClientSecretBasic) return clientAuthenticationClientSecretBasic(options)(callbackOptions);
1176
- if (method === SupportedClientAuthenticationMethod.ClientSecretPost) return clientAuthenticationClientSecretPost(options)(callbackOptions);
1177
- if (method === SupportedClientAuthenticationMethod.None) return clientAuthenticationNone(options)(callbackOptions);
1178
- throw new Oauth2Error(`Unsupported client auth method ${method}. Supported values are ${Object.values(SupportedClientAuthenticationMethod).join(", ")}`);
1179
- };
1180
- }
1181
- /**
1182
- * Client authentication using `client_secret_post` option
1183
- */
1184
- function clientAuthenticationClientSecretPost(options) {
1185
- return ({ body }) => {
1186
- body.client_id = options.clientId;
1187
- body.client_secret = options.clientSecret;
1188
- };
1189
- }
1190
- /**
1191
- * Client authentication using `client_secret_basic` option
1192
- */
1193
- function clientAuthenticationClientSecretBasic(options) {
1194
- return ({ headers }) => {
1195
- const authorization = (0, __openid4vc_utils.encodeToBase64Url)((0, __openid4vc_utils.decodeUtf8String)(`${options.clientId}:${options.clientSecret}`));
1196
- headers.set("Authorization", `Basic ${authorization}`);
1197
- };
1198
- }
1199
- /**
1200
- * Client authentication using `none` option
1201
- */
1202
- function clientAuthenticationNone(options) {
1203
- return ({ body }) => {
1204
- body.client_id = options.clientId;
1205
- };
1206
- }
1207
- /**
1208
- * Anonymous client authentication
1209
- */
1210
- function clientAuthenticationAnonymous() {
1211
- return () => {};
1212
- }
1213
- /**
1214
- * Client authentication using `attest_jwt_client_auth` option.
1215
- */
1216
- function clientAuthenticationClientAttestationJwt(options) {
1217
- return async ({ headers, authorizationServerMetadata }) => {
1218
- const clientAttestationPop = await createClientAttestationPopJwt({
1219
- authorizationServer: authorizationServerMetadata.issuer,
1220
- callbacks: options.callbacks,
1221
- clientAttestation: options.clientAttestationJwt
1222
- });
1223
- headers.set(oauthClientAttestationHeader, options.clientAttestationJwt);
1224
- headers.set(oauthClientAttestationPopHeader, clientAttestationPop);
1225
- };
1226
- }
1227
-
1228
- //#endregion
1229
- //#region src/common/algorithm/algorithm-transform.ts
1230
- /**
1231
- * Algorithm transformation utilities for JWA and COSE
1232
- *
1233
- * This module provides utilities to transform between JWA (JSON Web Algorithms)
1234
- * signature algorithm identifiers and fully-specified COSE (CBOR Object Signing and Encryption)
1235
- * algorithm identifiers.
1236
- *
1237
- * Based on RFC 9864: Fully-Specified Algorithms for JOSE and COSE
1238
- * https://www.rfc-editor.org/rfc/rfc9864.html
1239
- */
1240
- /**
1241
- * JWA (JSON Web Algorithms) signature algorithm identifiers
1242
- *
1243
- * From RFC 7518 (JWA) and RFC 9864 (Fully-Specified Algorithms)
1244
- */
1245
- var JwaSignatureAlgorithm = /* @__PURE__ */ function(JwaSignatureAlgorithm$1) {
1246
- JwaSignatureAlgorithm$1["Ed25519"] = "Ed25519";
1247
- JwaSignatureAlgorithm$1["Ed448"] = "Ed448";
1248
- JwaSignatureAlgorithm$1["EdDSA"] = "EdDSA";
1249
- JwaSignatureAlgorithm$1["ES256"] = "ES256";
1250
- JwaSignatureAlgorithm$1["ES384"] = "ES384";
1251
- JwaSignatureAlgorithm$1["ES512"] = "ES512";
1252
- JwaSignatureAlgorithm$1["ES256K"] = "ES256K";
1253
- JwaSignatureAlgorithm$1["RS256"] = "RS256";
1254
- JwaSignatureAlgorithm$1["RS384"] = "RS384";
1255
- JwaSignatureAlgorithm$1["RS512"] = "RS512";
1256
- JwaSignatureAlgorithm$1["PS256"] = "PS256";
1257
- JwaSignatureAlgorithm$1["PS384"] = "PS384";
1258
- JwaSignatureAlgorithm$1["PS512"] = "PS512";
1259
- return JwaSignatureAlgorithm$1;
1260
- }(JwaSignatureAlgorithm || {});
1261
- /**
1262
- * Mapping of JWA signature algorithm identifiers to fully-specified COSE algorithm identifiers
1263
- *
1264
- * From RFC 9864:
1265
- * - EdDSA algorithms (Section 2.2)
1266
- * - ECDSA algorithms (Section 2.1) - JWA ECDSA algorithms are already fully-specified
1267
- *
1268
- * Note: JWA ECDSA algorithms (ES256, ES384, ES512) are already fully-specified,
1269
- * while COSE ECDSA algorithms with the same names are polymorphic and deprecated.
1270
- * The fully-specified COSE equivalents use different names (ESP256, ESP384, ESP512).
1271
- */
1272
- const JWA_SIGNATURE_TO_COSE_ALGORITHM_MAP = {
1273
- [JwaSignatureAlgorithm.Ed25519]: -19,
1274
- [JwaSignatureAlgorithm.Ed448]: -53,
1275
- [JwaSignatureAlgorithm.EdDSA]: -19,
1276
- [JwaSignatureAlgorithm.ES256]: -9,
1277
- [JwaSignatureAlgorithm.ES384]: -51,
1278
- [JwaSignatureAlgorithm.ES512]: -52,
1279
- [JwaSignatureAlgorithm.ES256K]: -47,
1280
- [JwaSignatureAlgorithm.RS256]: -257,
1281
- [JwaSignatureAlgorithm.RS384]: -258,
1282
- [JwaSignatureAlgorithm.RS512]: -259,
1283
- [JwaSignatureAlgorithm.PS256]: -37,
1284
- [JwaSignatureAlgorithm.PS384]: -38,
1285
- [JwaSignatureAlgorithm.PS512]: -39
1286
- };
1287
- /**
1288
- * Mapping of COSE algorithm identifiers to JWA signature algorithm identifiers
1289
- *
1290
- * This is the inverse of JWA_SIGNATURE_TO_COSE_ALGORITHM_MAP, with additional entries
1291
- * for deprecated polymorphic COSE algorithms that should be avoided.
1292
- */
1293
- const COSE_TO_JWA_SIGNATURE_ALGORITHM_MAP = {
1294
- [-19]: JwaSignatureAlgorithm.Ed25519,
1295
- [-53]: JwaSignatureAlgorithm.Ed448,
1296
- [-8]: JwaSignatureAlgorithm.Ed25519,
1297
- [-9]: JwaSignatureAlgorithm.ES256,
1298
- [-51]: JwaSignatureAlgorithm.ES384,
1299
- [-52]: JwaSignatureAlgorithm.ES512,
1300
- [-47]: JwaSignatureAlgorithm.ES256K,
1301
- [-7]: JwaSignatureAlgorithm.ES256,
1302
- [-35]: JwaSignatureAlgorithm.ES384,
1303
- [-36]: JwaSignatureAlgorithm.ES512,
1304
- [-257]: JwaSignatureAlgorithm.RS256,
1305
- [-258]: JwaSignatureAlgorithm.RS384,
1306
- [-259]: JwaSignatureAlgorithm.RS512,
1307
- [-37]: JwaSignatureAlgorithm.PS256,
1308
- [-38]: JwaSignatureAlgorithm.PS384,
1309
- [-39]: JwaSignatureAlgorithm.PS512
1310
- };
1311
- /**
1312
- * Transform a JWA signature algorithm identifier to an RFC 9864 fully-specified COSE algorithm identifier
1313
- *
1314
- * @param jwaAlg - JWA signature algorithm identifier (e.g., 'Ed25519', 'ES256')
1315
- * @returns Fully-specified COSE algorithm identifier (e.g., -19, -9) or undefined if not mappable
1316
- *
1317
- * @example
1318
- * ```typescript
1319
- * const coseAlg = jwaSignatureAlgorithmToFullySpecifiedCoseAlgorithm('Ed25519') // Returns -19
1320
- * const coseAlg = jwaSignatureAlgorithmToFullySpecifiedCoseAlgorithm('ES256') // Returns -9 (ESP256)
1321
- * ```
1322
- */
1323
- function jwaSignatureAlgorithmToFullySpecifiedCoseAlgorithm(jwaAlg) {
1324
- return JWA_SIGNATURE_TO_COSE_ALGORITHM_MAP[jwaAlg];
1325
- }
1326
- /**
1327
- * Transform a COSE algorithm identifier (either RFC 9864 fully-specified, or polymorphic) to a JWA signature algorithm identifier
1328
- *
1329
- * @param coseAlg - COSE algorithm identifier (e.g., -19, -9)
1330
- * @returns JWA signature algorithm identifier (e.g., 'Ed25519', 'ES256') or undefined if not mappable
1331
- *
1332
- * @example
1333
- * ```typescript
1334
- * const jwaAlg = fullySpecifiedCoseAlgorithmToJwaSignatureAlgorithm(-19) // Returns 'Ed25519'
1335
- * const jwaAlg = fullySpecifiedCoseAlgorithmToJwaSignatureAlgorithm(-9) // Returns 'ES256'
1336
- * const jwaAlg = fullySpecifiedCoseAlgorithmToJwaSignatureAlgorithm(-7) // Returns 'ES256' (deprecated polymorphic COSE ES256)
1337
- * ```
1338
- */
1339
- function fullySpecifiedCoseAlgorithmToJwaSignatureAlgorithm(coseAlg) {
1340
- return COSE_TO_JWA_SIGNATURE_ALGORITHM_MAP[coseAlg];
1341
- }
1342
- /**
1343
- * Transform an array of JWA signature algorithm identifiers to RFC 9864 fully-specified COSE algorithm identifiers.
1344
- *
1345
- * By default it filters out unmappable algorithms. You can also choose to throw an error when an unknown
1346
- * algorithm is detected.
1347
- *
1348
- * @param jwaAlgs - Array of JWA signature algorithm identifiers
1349
- * @returns Array of fully-specified COSE algorithm identifiers
1350
- *
1351
- * @example
1352
- * ```typescript
1353
- * const coseAlgs = jwaSignatureAlgorithmArrayToFullySpecifiedCoseAlgorithmArray(['Ed25519', 'ES256', 'Unknown'])
1354
- * // Returns [-19, -9]
1355
- * ```
1356
- */
1357
- function jwaSignatureAlgorithmArrayToFullySpecifiedCoseAlgorithmArray(jwaAlgs, throwOnUnknownValue = false) {
1358
- return jwaAlgs.map((jwaAlg) => {
1359
- const coseAlg = jwaSignatureAlgorithmToFullySpecifiedCoseAlgorithm(jwaAlg);
1360
- if (coseAlg || !throwOnUnknownValue) return coseAlg;
1361
- throw new Oauth2Error(`Found unknown JWA signature algorithm '${jwaAlg}'. Unable to map to COSE algorithm.`);
1362
- }).filter((coseAlg) => coseAlg !== void 0);
1363
- }
1364
- /**
1365
- * Transform an array of COSE algorithm identifiers (either RFC 9864 fully-specified or polymorphic) to JWA signature algorithm identifiers
1366
- *
1367
- * By default it filters out unmappable algorithms. You can also choose to throw an error when an unknown
1368
- * algorithm is detected.
1369
- *
1370
- * @param coseAlgs - Array of COSE algorithm identifiers
1371
- * @returns Array of JWA signature algorithm identifiers
1372
- *
1373
- * @example
1374
- * ```typescript
1375
- * const jwaAlgs = fullySpecifiedCoseAlgorithmArrayToJwaSignatureAlgorithmArray([-19, -9, 999])
1376
- * // Returns ['Ed25519', 'ES256']
1377
- * ```
1378
- */
1379
- function fullySpecifiedCoseAlgorithmArrayToJwaSignatureAlgorithmArray(coseAlgs, throwOnUnknownValue = false) {
1380
- return coseAlgs.map((coseAlg) => {
1381
- const jwaAlg = fullySpecifiedCoseAlgorithmToJwaSignatureAlgorithm(coseAlg);
1382
- if (jwaAlg || !throwOnUnknownValue) return jwaAlg;
1383
- throw new Oauth2Error(`Found unknown COSE algorithm identifier '${coseAlg}'. Unable to map to JWA signature algorithm.`);
1384
- }).filter((alg) => alg !== void 0);
1385
- }
1386
-
1387
- //#endregion
1388
- //#region src/error/Oauth2ClientErrorResponseError.ts
1389
- var Oauth2ClientErrorResponseError = class extends Oauth2Error {
1390
- constructor(message, errorResponse, response) {
1391
- super(`${message}\n${JSON.stringify(errorResponse, null, 2)}`);
1392
- this.errorResponse = errorResponse;
1393
- this.response = response.clone();
1394
- }
1395
- };
1396
-
1397
- //#endregion
1398
- //#region src/error/Oauth2ClientAuthorizationChallengeError.ts
1399
- var Oauth2ClientAuthorizationChallengeError = class extends Oauth2ClientErrorResponseError {
1400
- constructor(message, errorResponse, response) {
1401
- super(message, errorResponse, response);
1402
- this.errorResponse = errorResponse;
1403
- }
1404
- };
1405
-
1406
- //#endregion
1407
- //#region src/error/Oauth2ResourceUnauthorizedError.ts
1408
- var Oauth2ResourceUnauthorizedError = class Oauth2ResourceUnauthorizedError extends Oauth2Error {
1409
- constructor(internalMessage, wwwAuthenticateHeaders) {
1410
- super(`${internalMessage}\n${JSON.stringify(wwwAuthenticateHeaders, null, 2)}`);
1411
- this.wwwAuthenticateHeaders = Array.isArray(wwwAuthenticateHeaders) ? wwwAuthenticateHeaders : [wwwAuthenticateHeaders];
1412
- }
1413
- static fromHeaderValue(value) {
1414
- return new Oauth2ResourceUnauthorizedError(void 0, (0, __openid4vc_utils.parseWwwAuthenticateHeader)(value).map(({ scheme, payload: { error, error_description, scope, ...additionalPayload } }) => ({
1415
- scheme,
1416
- error: Array.isArray(error) ? error.join(",") : error ?? void 0,
1417
- error_description: Array.isArray(error_description) ? error_description.join(",") : error_description ?? void 0,
1418
- scope: Array.isArray(scope) ? scope.join(",") : scope ?? void 0,
1419
- ...additionalPayload
1420
- })));
1421
- }
1422
- toHeaderValue() {
1423
- return (0, __openid4vc_utils.encodeWwwAuthenticateHeader)(this.wwwAuthenticateHeaders.map((header) => ({
1424
- scheme: header.scheme,
1425
- payload: {
1426
- error: header.error ?? null,
1427
- error_description: header.error_description ?? null,
1428
- scope: header.scope ?? null,
1429
- ...header.additionalPayload
1430
- }
1431
- })));
1432
- }
1433
- };
1434
-
1435
- //#endregion
1436
- //#region src/id-token/z-id-token-jwt.ts
1437
- const zIdTokenJwtHeader = zod.default.object({ ...zJwtHeader.shape }).loose();
1438
- const zIdTokenJwtPayload = zod.default.object({
1439
- ...zJwtPayload.shape,
1440
- iss: zod.default.string(),
1441
- sub: zod.default.string(),
1442
- aud: zod.default.union([zod.default.string(), zod.default.array(zod.default.string())]),
1443
- exp: __openid4vc_utils.zInteger,
1444
- iat: __openid4vc_utils.zInteger,
1445
- auth_time: __openid4vc_utils.zInteger.optional(),
1446
- acr: zod.default.string().optional(),
1447
- amr: zod.default.array(zod.default.string()).optional(),
1448
- azp: zod.default.string().optional(),
1449
- name: zod.default.string().optional(),
1450
- given_name: zod.default.string().optional(),
1451
- family_name: zod.default.string().optional(),
1452
- middle_name: zod.default.string().optional(),
1453
- nickname: zod.default.string().optional(),
1454
- preferred_username: zod.default.string().optional(),
1455
- profile: zod.default.url().optional(),
1456
- picture: zod.default.url().optional(),
1457
- website: zod.default.url().optional(),
1458
- email: zod.default.email().optional(),
1459
- email_verified: zod.default.boolean().optional(),
1460
- gender: zod.default.enum(["male", "female"]).or(zod.default.string()).optional(),
1461
- birthdate: zod.default.iso.date().optional(),
1462
- zoneinfo: zod.default.string().optional(),
1463
- locale: zod.default.string().optional(),
1464
- phone_number: zod.default.string().optional(),
1465
- phone_number_verified: zod.default.boolean().optional(),
1466
- address: zod.default.object({
1467
- formatted: zod.default.string().optional(),
1468
- street_address: zod.default.string().optional(),
1469
- locality: zod.default.string().optional(),
1470
- region: zod.default.string().optional(),
1471
- postal_code: zod.default.string().optional(),
1472
- country: zod.default.string().optional()
1473
- }).loose().optional(),
1474
- updated_at: __openid4vc_utils.zInteger.optional()
1475
- }).loose();
1476
-
1477
- //#endregion
1478
- //#region src/id-token/verify-id-token.ts
1479
- /**
1480
- * Verify an ID Token JWT.
1481
- */
1482
- async function verifyIdTokenJwt(options) {
1483
- const { header, payload } = decodeJwt({
1484
- jwt: options.idToken,
1485
- headerSchema: zIdTokenJwtHeader,
1486
- payloadSchema: zIdTokenJwtPayload
1487
- });
1488
- const jwksUrl = options.authorizationServer.jwks_uri;
1489
- if (!jwksUrl) throw new Oauth2Error(`Authorization server '${options.authorizationServer.issuer}' does not have a 'jwks_uri' parameter to fetch JWKs.`);
1490
- if (payload.iss !== options.authorizationServer.issuer) throw new Oauth2Error(`Invalid 'iss' claim in id token jwt. Expected '${options.authorizationServer.issuer}', got '${payload.iss}'.`);
1491
- if (payload.azp && payload.azp !== options.clientId) throw new Oauth2Error(`Invalid 'azp' claim in id token jwt. Expected '${options.clientId}', got '${payload.azp}'.`);
1492
- const jwks = await fetchJwks(jwksUrl, options.callbacks.fetch);
1493
- const publicJwk = extractJwkFromJwksForJwt({
1494
- kid: header.kid,
1495
- jwks,
1496
- use: "sig"
1497
- });
1498
- await verifyJwt({
1499
- compact: options.idToken,
1500
- header,
1501
- payload,
1502
- signer: {
1503
- method: "jwk",
1504
- publicJwk,
1505
- alg: header.alg
1506
- },
1507
- verifyJwtCallback: options.callbacks.verifyJwt,
1508
- errorMessage: "Error during verification of id token jwt.",
1509
- now: options.now,
1510
- expectedAudience: options.clientId,
1511
- expectedIssuer: options.authorizationServer.issuer,
1512
- expectedNonce: options.expectedNonce
1513
- });
1514
- return {
1515
- header,
1516
- payload
1517
- };
1518
- }
1519
-
1520
- //#endregion
1521
- //#region src/jar/create-jar-authorization-request.ts
1522
- /**
1523
- * Creates a JAR (JWT Authorization Request) request object.
1524
- *
1525
- * @param options - The input parameters
1526
- * @param options.authorizationRequestPayload - The authorization request parameters
1527
- * @param options.jwtSigner - The JWT signer
1528
- * @param options.jweEncryptor - The JWE encryptor (optional) if provided, the request object will be encrypted
1529
- * @param options.requestUri - The request URI (optional) if provided, the request object needs to be fetched from the URI
1530
- * @param options.callbacks - The callback context
1531
- * @returns the requestParams, signerJwk, encryptionJwk, and requestObjectJwt
1532
- */
1533
- async function createJarAuthorizationRequest(options) {
1534
- const { jwtSigner, jweEncryptor, authorizationRequestPayload, requestUri, callbacks } = options;
1535
- let authorizationRequestJwt;
1536
- let encryptionJwk;
1537
- const now = options.now ?? /* @__PURE__ */ new Date();
1538
- const { jwt, signerJwk } = await callbacks.signJwt(jwtSigner, {
1539
- header: {
1540
- ...jwtHeaderFromJwtSigner(jwtSigner),
1541
- typ: "oauth-authz-req+jwt"
1542
- },
1543
- payload: {
1544
- iat: (0, __openid4vc_utils.dateToSeconds)(now),
1545
- exp: (0, __openid4vc_utils.dateToSeconds)((0, __openid4vc_utils.addSecondsToDate)(now, options.expiresInSeconds)),
1546
- ...options.additionalJwtPayload,
1547
- ...authorizationRequestPayload
1548
- }
1549
- });
1550
- authorizationRequestJwt = jwt;
1551
- if (jweEncryptor) {
1552
- const encryptionResult = await callbacks.encryptJwe(jweEncryptor, authorizationRequestJwt);
1553
- authorizationRequestJwt = encryptionResult.jwe;
1554
- encryptionJwk = encryptionResult.encryptionJwk;
1555
- }
1556
- const client_id = authorizationRequestPayload.client_id;
1557
- return {
1558
- jarAuthorizationRequest: requestUri ? {
1559
- client_id,
1560
- request_uri: requestUri
1561
- } : {
1562
- client_id,
1563
- request: authorizationRequestJwt
1564
- },
1565
- signerJwk,
1566
- encryptionJwk,
1567
- authorizationRequestJwt
1568
- };
1569
- }
1570
-
1571
- //#endregion
1572
- //#region src/metadata/fetch-well-known-metadata.ts
1573
- /**
1574
- * Fetch well known metadata and validate the response.
1575
- *
1576
- * Returns null if 404 is returned
1577
- * Returns validated metadata if successful response
1578
- * Throws error otherwise
1579
- *
1580
- * @throws {ValidationError} if successful response but validation of response failed
1581
- * @throws {InvalidFetchResponseError} if no successful or 404 response
1582
- * @throws {Error} if parsing json from response fails
1583
- */
1584
- async function fetchWellKnownMetadata(wellKnownMetadataUrl, schema, options) {
1585
- const { result, response } = await (0, __openid4vc_utils.createZodFetcher)(options?.fetch)(schema, options?.acceptedContentType ?? [__openid4vc_utils.ContentType.Json], wellKnownMetadataUrl);
1586
- if (response.status === 404) return null;
1587
- if (!response.ok) throw new __openid4vc_utils.InvalidFetchResponseError(`Fetching well known metadata from '${wellKnownMetadataUrl}' resulted in an unsuccessful response with status '${response.status}'.`, await response.clone().text(), response);
1588
- if (!result?.success) throw new ValidationError$1(`Validation of metadata from '${wellKnownMetadataUrl}' failed`, result?.error);
1589
- return result.data;
1590
- }
1591
-
1592
- //#endregion
1593
- //#region src/metadata/authorization-server/z-authorization-server-metadata.ts
1594
- const knownClientAuthenticationMethod = zod.default.enum([
1595
- "client_secret_basic",
1596
- "client_secret_post",
1597
- "attest_jwt_client_auth",
1598
- "client_secret_jwt",
1599
- "private_key_jwt"
1600
- ]);
1601
- const zAuthorizationServerMetadata = zod.default.object({
1602
- issuer: __openid4vc_utils.zHttpsUrl,
1603
- token_endpoint: __openid4vc_utils.zHttpsUrl,
1604
- token_endpoint_auth_methods_supported: zod.default.optional(zod.default.array(zod.default.union([knownClientAuthenticationMethod, zod.default.string()]))),
1605
- authorization_endpoint: zod.default.optional(__openid4vc_utils.zHttpsUrl),
1606
- jwks_uri: zod.default.optional(__openid4vc_utils.zHttpsUrl),
1607
- grant_types_supported: zod.default.optional(zod.default.array(zod.default.string())),
1608
- code_challenge_methods_supported: zod.default.optional(zod.default.array(zod.default.string())),
1609
- dpop_signing_alg_values_supported: zod.default.optional(zod.default.array(zod.default.string())),
1610
- require_pushed_authorization_requests: zod.default.optional(zod.default.boolean()),
1611
- pushed_authorization_request_endpoint: zod.default.optional(__openid4vc_utils.zHttpsUrl),
1612
- introspection_endpoint: zod.default.optional(__openid4vc_utils.zHttpsUrl),
1613
- introspection_endpoint_auth_methods_supported: zod.default.optional(zod.default.array(zod.default.union([knownClientAuthenticationMethod, zod.default.string()]))),
1614
- introspection_endpoint_auth_signing_alg_values_supported: zod.default.optional(zod.default.array(zAlgValueNotNone)),
1615
- authorization_challenge_endpoint: zod.default.optional(__openid4vc_utils.zHttpsUrl),
1616
- "pre-authorized_grant_anonymous_access_supported": zod.default.optional(zod.default.boolean()),
1617
- client_attestation_pop_nonce_required: zod.default.boolean().optional()
1618
- }).loose().refine(({ introspection_endpoint_auth_methods_supported: methodsSupported, introspection_endpoint_auth_signing_alg_values_supported: algValuesSupported }) => {
1619
- if (!methodsSupported) return true;
1620
- if (!methodsSupported.includes("private_key_jwt") && !methodsSupported.includes("client_secret_jwt")) return true;
1621
- return algValuesSupported !== void 0 && algValuesSupported.length > 0;
1622
- }, `Metadata value 'introspection_endpoint_auth_signing_alg_values_supported' must be defined if metadata 'introspection_endpoint_auth_methods_supported' value contains values 'private_key_jwt' or 'client_secret_jwt'`);
1623
-
1624
- //#endregion
1625
- //#region src/metadata/authorization-server/authorization-server-metadata.ts
1626
- const wellKnownAuthorizationServerSuffix = ".well-known/oauth-authorization-server";
1627
- const wellKnownOpenIdConfigurationServerSuffix = ".well-known/openid-configuration";
1628
- /**
1629
- * fetch authorization server metadata. It first tries to fetch the oauth-authorization-server metadata. If that returns
1630
- * a 404, the openid-configuration metadata will be fetched.
1631
- */
1632
- async function fetchAuthorizationServerMetadata(issuer, fetch) {
1633
- const parsedIssuerUrl = new __openid4vc_utils.URL(issuer);
1634
- const openIdConfigurationWellKnownMetadataUrl = (0, __openid4vc_utils.joinUriParts)(issuer, [wellKnownOpenIdConfigurationServerSuffix]);
1635
- const authorizationServerWellKnownMetadataUrl = (0, __openid4vc_utils.joinUriParts)(parsedIssuerUrl.origin, [wellKnownAuthorizationServerSuffix, parsedIssuerUrl.pathname]);
1636
- const nonCompliantAuthorizationServerWellKnownMetadataUrl = (0, __openid4vc_utils.joinUriParts)(issuer, [wellKnownAuthorizationServerSuffix]);
1637
- let authorizationServerResult = await fetchWellKnownMetadata(authorizationServerWellKnownMetadataUrl, zAuthorizationServerMetadata, { fetch });
1638
- if (!authorizationServerResult && nonCompliantAuthorizationServerWellKnownMetadataUrl !== authorizationServerWellKnownMetadataUrl) authorizationServerResult = await fetchWellKnownMetadata(nonCompliantAuthorizationServerWellKnownMetadataUrl, zAuthorizationServerMetadata, { fetch });
1639
- if (!authorizationServerResult) authorizationServerResult = await fetchWellKnownMetadata(openIdConfigurationWellKnownMetadataUrl, zAuthorizationServerMetadata, { fetch });
1640
- if (authorizationServerResult && authorizationServerResult.issuer !== issuer) throw new Oauth2Error(`The 'issuer' parameter '${authorizationServerResult.issuer}' in the well known authorization server metadata at '${authorizationServerWellKnownMetadataUrl}' does not match the provided issuer '${issuer}'.`);
1641
- return authorizationServerResult;
1642
- }
1643
- function getAuthorizationServerMetadataFromList(authorizationServersMetadata, issuer) {
1644
- const authorizationServerMetadata = authorizationServersMetadata.find((authorizationServerMetadata$1) => authorizationServerMetadata$1.issuer === issuer);
1645
- if (!authorizationServerMetadata) throw new Oauth2Error(`Authorization server '${issuer}' not found in list of authorization servers. Available authorization servers are ${authorizationServersMetadata.map((as) => `'${as.issuer}'`).join(", ")}`);
1646
- return authorizationServerMetadata;
1647
- }
1648
-
1649
- //#endregion
1650
- //#region src/access-token/create-access-token.ts
1651
- /**
1652
- * Create an oauth2 access token conformant with "JSON Web Token (JWT) Profile for OAuth 2.0 Access Tokens"
1653
- * @see https://datatracker.ietf.org/doc/html/rfc9068
1654
- */
1655
- async function createAccessTokenJwt(options) {
1656
- const header = (0, __openid4vc_utils.parseWithErrorHandling)(zAccessTokenProfileJwtHeader, {
1657
- ...jwtHeaderFromJwtSigner(options.signer),
1658
- typ: "at+jwt"
1659
- });
1660
- const now = options.now ?? /* @__PURE__ */ new Date();
1661
- const payload = (0, __openid4vc_utils.parseWithErrorHandling)(zAccessTokenProfileJwtPayload, {
1662
- iat: (0, __openid4vc_utils.dateToSeconds)(now),
1663
- exp: (0, __openid4vc_utils.dateToSeconds)((0, __openid4vc_utils.addSecondsToDate)(now, options.expiresInSeconds)),
1664
- aud: options.audience,
1665
- iss: options.authorizationServer,
1666
- jti: (0, __openid4vc_utils.encodeToBase64Url)(await options.callbacks.generateRandom(32)),
1667
- client_id: options.clientId,
1668
- sub: options.subject,
1669
- scope: options.scope,
1670
- cnf: options.dpop ? { jkt: await calculateJwkThumbprint({
1671
- hashAlgorithm: HashAlgorithm.Sha256,
1672
- hashCallback: options.callbacks.hash,
1673
- jwk: options.dpop.jwk
1674
- }) } : void 0,
1675
- ...options.additionalPayload
1676
- });
1677
- const { jwt } = await options.callbacks.signJwt(options.signer, {
1678
- header,
1679
- payload
1680
- });
1681
- return { jwt };
1682
- }
1683
-
1684
- //#endregion
1685
- //#region src/access-token/z-access-token.ts
1686
- const zAccessTokenRequest = zod.default.intersection(zod.default.object({
1687
- "pre-authorized_code": zod.default.optional(zod.default.string()),
1688
- code: zod.default.optional(zod.default.string()),
1689
- redirect_uri: zod.default.url().optional(),
1690
- refresh_token: zod.default.optional(zod.default.string()),
1691
- resource: zod.default.optional(__openid4vc_utils.zHttpsUrl),
1692
- code_verifier: zod.default.optional(zod.default.string()),
1693
- grant_type: zod.default.union([
1694
- zPreAuthorizedCodeGrantIdentifier,
1695
- zAuthorizationCodeGrantIdentifier,
1696
- zRefreshTokenGrantIdentifier,
1697
- zod.default.string()
1698
- ])
1699
- }).loose(), zod.default.object({
1700
- tx_code: zod.default.optional(zod.default.string()),
1701
- user_pin: zod.default.optional(zod.default.string())
1702
- }).loose().refine(({ tx_code, user_pin }) => !tx_code || !user_pin || user_pin === tx_code, { message: `If both 'tx_code' and 'user_pin' are present they must match` }).transform(({ tx_code, user_pin, ...rest }) => {
1703
- return {
1704
- ...rest,
1705
- ...tx_code ?? user_pin ? { tx_code: tx_code ?? user_pin } : {}
1706
- };
1707
- }));
1708
- const zAccessTokenResponse = zod.default.object({
1709
- access_token: zod.default.string(),
1710
- token_type: zod.default.string(),
1711
- expires_in: zod.default.optional(zod.default.number().int()),
1712
- scope: zod.default.optional(zod.default.string()),
1713
- state: zod.default.optional(zod.default.string()),
1714
- refresh_token: zod.default.optional(zod.default.string()),
1715
- c_nonce: zod.default.optional(zod.default.string()),
1716
- c_nonce_expires_in: zod.default.optional(zod.default.number().int()),
1717
- authorization_details: zod.default.array(zod.default.object({}).loose()).optional()
1718
- }).loose();
1719
- const zAccessTokenErrorResponse = zOauth2ErrorResponse;
1720
-
1721
- //#endregion
1722
- //#region src/access-token/create-access-token-response.ts
1723
- async function createAccessTokenResponse(options) {
1724
- return (0, __openid4vc_utils.parseWithErrorHandling)(zAccessTokenResponse, {
1725
- access_token: options.accessToken,
1726
- refresh_token: options.refreshToken,
1727
- token_type: options.tokenType,
1728
- expires_in: options.expiresInSeconds,
1729
- c_nonce: options.cNonce,
1730
- c_nonce_expires_in: options.cNonceExpiresIn,
1731
- ...options.additionalPayload
1732
- });
1733
- }
1734
-
1735
- //#endregion
1736
- //#region src/access-token/parse-access-token-request.ts
1737
- /**
1738
- * Parse access token request and extract the grant specific properties.
1739
- *
1740
- * If something goes wrong, such as the grant is not supported, missing parameters, etc,
1741
- * it will throw `Oauth2ServerErrorResponseError` containing an error response object
1742
- * that can be returned to the client.
1743
- */
1744
- function parseAccessTokenRequest(options) {
1745
- const parsedAccessTokenRequest = zAccessTokenRequest.safeParse(options.accessTokenRequest);
1746
- if (!parsedAccessTokenRequest.success) throw new Oauth2ServerErrorResponseError({
1747
- error: Oauth2ErrorCodes.InvalidRequest,
1748
- error_description: `Error occurred during validation of authorization request.\n${(0, __openid4vc_utils.formatZodError)(parsedAccessTokenRequest.error)}`
1749
- });
1750
- const accessTokenRequest = parsedAccessTokenRequest.data;
1751
- let grant;
1752
- if (accessTokenRequest.grant_type === preAuthorizedCodeGrantIdentifier) {
1753
- if (!accessTokenRequest["pre-authorized_code"]) throw new Oauth2ServerErrorResponseError({
1754
- error: Oauth2ErrorCodes.InvalidRequest,
1755
- error_description: `Missing required 'pre-authorized_code' for grant type '${preAuthorizedCodeGrantIdentifier}'`
1756
- });
1757
- grant = {
1758
- grantType: preAuthorizedCodeGrantIdentifier,
1759
- preAuthorizedCode: accessTokenRequest["pre-authorized_code"],
1760
- txCode: accessTokenRequest.tx_code
1761
- };
1762
- } else if (accessTokenRequest.grant_type === authorizationCodeGrantIdentifier) {
1763
- if (!accessTokenRequest.code) throw new Oauth2ServerErrorResponseError({
1764
- error: Oauth2ErrorCodes.InvalidRequest,
1765
- error_description: `Missing required 'code' for grant type '${authorizationCodeGrantIdentifier}'`
1766
- });
1767
- grant = {
1768
- grantType: authorizationCodeGrantIdentifier,
1769
- code: accessTokenRequest.code
1770
- };
1771
- } else if (accessTokenRequest.grant_type === refreshTokenGrantIdentifier) {
1772
- if (!accessTokenRequest.refresh_token) throw new Oauth2ServerErrorResponseError({
1773
- error: Oauth2ErrorCodes.InvalidRequest,
1774
- error_description: `Missing required 'refresh_token' for grant type '${refreshTokenGrantIdentifier}'`
1775
- });
1776
- grant = {
1777
- grantType: refreshTokenGrantIdentifier,
1778
- refreshToken: accessTokenRequest.refresh_token
1779
- };
1780
- } else throw new Oauth2ServerErrorResponseError({
1781
- error: Oauth2ErrorCodes.UnsupportedGrantType,
1782
- error_description: `The grant type '${accessTokenRequest.grant_type}' is not supported`
1783
- });
1784
- const extractedDpopJwt = extractDpopJwtFromHeaders(options.request.headers);
1785
- if (!extractedDpopJwt.valid) throw new Oauth2ServerErrorResponseError({
1786
- error: Oauth2ErrorCodes.InvalidDpopProof,
1787
- error_description: `Request contains a 'DPoP' header, but the value is not a valid DPoP jwt`
1788
- });
1789
- const extractedClientAttestationJwts = extractClientAttestationJwtsFromHeaders(options.request.headers);
1790
- if (!extractedClientAttestationJwts.valid) throw new Oauth2ServerErrorResponseError({
1791
- error: Oauth2ErrorCodes.InvalidClient,
1792
- error_description: "Request contains client attestation header, but the values are not valid client attestation and client attestation PoP header."
1793
- });
1794
- const pkceCodeVerifier = accessTokenRequest.code_verifier;
1795
- return {
1796
- accessTokenRequest,
1797
- grant,
1798
- dpop: extractedDpopJwt.dpopJwt ? { jwt: extractedDpopJwt.dpopJwt } : void 0,
1799
- clientAttestation: extractedClientAttestationJwts.clientAttestationHeader ? {
1800
- clientAttestationJwt: extractedClientAttestationJwts.clientAttestationHeader,
1801
- clientAttestationPopJwt: extractedClientAttestationJwts.clientAttestationPopHeader
1802
- } : void 0,
1803
- pkceCodeVerifier
1804
- };
1805
- }
1806
-
1807
- //#endregion
1808
- //#region src/pkce.ts
1809
- let PkceCodeChallengeMethod = /* @__PURE__ */ function(PkceCodeChallengeMethod$1) {
1810
- PkceCodeChallengeMethod$1["Plain"] = "plain";
1811
- PkceCodeChallengeMethod$1["S256"] = "S256";
1812
- return PkceCodeChallengeMethod$1;
1813
- }({});
1814
- async function createPkce(options) {
1815
- const allowedCodeChallengeMethods = options.allowedCodeChallengeMethods ?? [PkceCodeChallengeMethod.S256, PkceCodeChallengeMethod.Plain];
1816
- if (allowedCodeChallengeMethods.length === 0) throw new Oauth2Error(`Unable to create PKCE code verifier. 'allowedCodeChallengeMethods' is an empty array.`);
1817
- const codeChallengeMethod = allowedCodeChallengeMethods.includes(PkceCodeChallengeMethod.S256) ? PkceCodeChallengeMethod.S256 : PkceCodeChallengeMethod.Plain;
1818
- const codeVerifier = options.codeVerifier ?? (0, __openid4vc_utils.encodeToBase64Url)(await options.callbacks.generateRandom(64));
1819
- return {
1820
- codeVerifier,
1821
- codeChallenge: await calculateCodeChallenge({
1822
- codeChallengeMethod,
1823
- codeVerifier,
1824
- hashCallback: options.callbacks.hash
1825
- }),
1826
- codeChallengeMethod
1827
- };
1828
- }
1829
- async function verifyPkce(options) {
1830
- const calculatedCodeChallenge = await calculateCodeChallenge({
1831
- codeChallengeMethod: options.codeChallengeMethod,
1832
- codeVerifier: options.codeVerifier,
1833
- hashCallback: options.callbacks.hash
1834
- });
1835
- if (options.codeChallenge !== calculatedCodeChallenge) throw new Oauth2Error(`Derived code challenge '${calculatedCodeChallenge}' from code_verifier '${options.codeVerifier}' using code challenge method '${options.codeChallengeMethod}' does not match the expected code challenge.`);
1836
- }
1837
- async function calculateCodeChallenge(options) {
1838
- if (options.codeChallengeMethod === PkceCodeChallengeMethod.Plain) return options.codeVerifier;
1839
- if (options.codeChallengeMethod === PkceCodeChallengeMethod.S256) return (0, __openid4vc_utils.encodeToBase64Url)(await options.hashCallback((0, __openid4vc_utils.decodeUtf8String)(options.codeVerifier), HashAlgorithm.Sha256));
1840
- throw new Oauth2Error(`Unsupported code challenge method ${options.codeChallengeMethod}`);
1841
- }
1842
-
1843
- //#endregion
1844
- //#region src/access-token/verify-access-token-request.ts
1845
- async function verifyPreAuthorizedCodeAccessTokenRequest(options) {
1846
- if (options.pkce) await verifyAccessTokenRequestPkce(options.pkce, options.callbacks);
1847
- const dpopResult = options.dpop ? await verifyAccessTokenRequestDpop(options.dpop, options.request, options.callbacks) : void 0;
1848
- const clientAttestationResult = options.clientAttestation ? await verifyAccessTokenRequestClientAttestation(options.clientAttestation, options.authorizationServerMetadata, options.callbacks, dpopResult?.jwkThumbprint, options.now) : void 0;
1849
- if (options.grant.preAuthorizedCode !== options.expectedPreAuthorizedCode) throw new Oauth2ServerErrorResponseError({
1850
- error: Oauth2ErrorCodes.InvalidGrant,
1851
- error_description: `Invalid 'pre-authorized_code' provided`
1852
- });
1853
- if (options.grant.txCode !== options.expectedTxCode) {
1854
- if (!options.expectedTxCode) throw new Oauth2ServerErrorResponseError({
1855
- error: Oauth2ErrorCodes.InvalidRequest,
1856
- error_description: `Request contains 'tx_code' that was not expected`
1857
- });
1858
- if (!options.grant.txCode) throw new Oauth2ServerErrorResponseError({
1859
- error: Oauth2ErrorCodes.InvalidRequest,
1860
- error_description: `Missing required 'tx_code' in request`
1861
- });
1862
- throw new Oauth2ServerErrorResponseError({
1863
- error: Oauth2ErrorCodes.InvalidGrant,
1864
- error_description: `Invalid 'tx_code' provided`
1865
- });
1866
- }
1867
- if (options.preAuthorizedCodeExpiresAt) {
1868
- const now = options.now ?? /* @__PURE__ */ new Date();
1869
- if (now.getTime() > options.preAuthorizedCodeExpiresAt.getTime()) throw new Oauth2ServerErrorResponseError({
1870
- error: Oauth2ErrorCodes.InvalidGrant,
1871
- error_description: `Expired 'pre-authorized_code' provided`
1872
- }, { internalMessage: `The provided 'pre-authorized_code' in the request expired at '${options.preAuthorizedCodeExpiresAt.getTime()}', now is '${now.getTime()}'` });
1873
- }
1874
- return {
1875
- dpop: dpopResult,
1876
- clientAttestation: clientAttestationResult
1877
- };
1878
- }
1879
- async function verifyAuthorizationCodeAccessTokenRequest(options) {
1880
- if (options.pkce) await verifyAccessTokenRequestPkce(options.pkce, options.callbacks);
1881
- const dpopResult = options.dpop ? await verifyAccessTokenRequestDpop(options.dpop, options.request, options.callbacks) : void 0;
1882
- const clientAttestationResult = options.clientAttestation ? await verifyAccessTokenRequestClientAttestation(options.clientAttestation, options.authorizationServerMetadata, options.callbacks, dpopResult?.jwkThumbprint, options.now) : void 0;
1883
- if (options.grant.code !== options.expectedCode) throw new Oauth2ServerErrorResponseError({
1884
- error: Oauth2ErrorCodes.InvalidGrant,
1885
- error_description: `Invalid 'code' provided`
1886
- });
1887
- if (options.codeExpiresAt) {
1888
- const now = options.now ?? /* @__PURE__ */ new Date();
1889
- if (now.getTime() > options.codeExpiresAt.getTime()) throw new Oauth2ServerErrorResponseError({
1890
- error: Oauth2ErrorCodes.InvalidGrant,
1891
- error_description: `Expired 'code' provided`
1892
- }, { internalMessage: `The provided 'code' in the request expired at '${options.codeExpiresAt.getTime()}', now is '${now.getTime()}'` });
1893
- }
1894
- return {
1895
- dpop: dpopResult,
1896
- clientAttestation: clientAttestationResult
1897
- };
1898
- }
1899
- async function verifyRefreshTokenAccessTokenRequest(options) {
1900
- if (options.pkce) await verifyAccessTokenRequestPkce(options.pkce, options.callbacks);
1901
- const dpopResult = options.dpop ? await verifyAccessTokenRequestDpop(options.dpop, options.request, options.callbacks) : void 0;
1902
- const clientAttestationResult = options.clientAttestation ? await verifyAccessTokenRequestClientAttestation(options.clientAttestation, options.authorizationServerMetadata, options.callbacks, dpopResult?.jwkThumbprint, options.now) : void 0;
1903
- if (options.grant.refreshToken !== options.expectedRefreshToken) throw new Oauth2ServerErrorResponseError({
1904
- error: Oauth2ErrorCodes.InvalidGrant,
1905
- error_description: `Invalid 'refresh_token' provided`
1906
- });
1907
- if (options.refreshTokenExpiresAt) {
1908
- const now = options.now ?? /* @__PURE__ */ new Date();
1909
- if (now.getTime() > options.refreshTokenExpiresAt.getTime()) throw new Oauth2ServerErrorResponseError({
1910
- error: Oauth2ErrorCodes.InvalidGrant,
1911
- error_description: `Expired 'refresh_token' provided`
1912
- }, { internalMessage: `The provided 'refresh_token' in the request expired at '${options.refreshTokenExpiresAt.getTime()}', now is '${now.getTime()}'` });
1913
- }
1914
- return {
1915
- dpop: dpopResult,
1916
- clientAttestation: clientAttestationResult
1917
- };
1918
- }
1919
- async function verifyAccessTokenRequestClientAttestation(options, authorizationServerMetadata, callbacks, dpopJwkThumbprint, now) {
1920
- if (!options.clientAttestationJwt || !options.clientAttestationPopJwt) {
1921
- if (!options.required && !options.clientAttestationJwt && !options.clientAttestationPopJwt) return;
1922
- throw new Oauth2ServerErrorResponseError({
1923
- error: Oauth2ErrorCodes.InvalidClient,
1924
- error_description: `Missing required client attestation parameters in access token request. Make sure to provide the '${oauthClientAttestationHeader}' and '${oauthClientAttestationPopHeader}' header values.`
1925
- });
1926
- }
1927
- const verifiedClientAttestation = await verifyClientAttestation({
1928
- authorizationServer: authorizationServerMetadata.issuer,
1929
- callbacks,
1930
- clientAttestationJwt: options.clientAttestationJwt,
1931
- clientAttestationPopJwt: options.clientAttestationPopJwt,
1932
- now
1933
- });
1934
- if (options.expectedClientId && options.expectedClientId !== verifiedClientAttestation.clientAttestation.payload.sub) throw new Oauth2ServerErrorResponseError({
1935
- error: Oauth2ErrorCodes.InvalidClient,
1936
- error_description: `The client id '${verifiedClientAttestation.clientAttestation.payload.sub}' in the client attestation does not match the client id for the authorization.`
1937
- }, { status: 401 });
1938
- if (options.ensureConfirmationKeyMatchesDpopKey && dpopJwkThumbprint) {
1939
- if (await calculateJwkThumbprint({
1940
- hashAlgorithm: HashAlgorithm.Sha256,
1941
- hashCallback: callbacks.hash,
1942
- jwk: verifiedClientAttestation.clientAttestation.payload.cnf.jwk
1943
- }) !== dpopJwkThumbprint) throw new Oauth2ServerErrorResponseError({
1944
- error: Oauth2ErrorCodes.InvalidRequest,
1945
- error_description: "Expected the DPoP JWK thumbprint value to match the JWK thumbprint of the client attestation confirmation JWK. Ensure both DPoP and client attestation use the same key."
1946
- }, { status: 401 });
1947
- }
1948
- return verifiedClientAttestation;
1949
- }
1950
- async function verifyAccessTokenRequestDpop(options, request, callbacks) {
1951
- if (options.required && !options.jwt) throw new Oauth2ServerErrorResponseError({
1952
- error: Oauth2ErrorCodes.InvalidDpopProof,
1953
- error_description: "Missing required DPoP proof"
1954
- });
1955
- if (!options.jwt) return void 0;
1956
- const { header, jwkThumbprint } = await verifyDpopJwt({
1957
- callbacks,
1958
- dpopJwt: options.jwt,
1959
- request,
1960
- allowedSigningAlgs: options.allowedSigningAlgs,
1961
- expectedJwkThumbprint: options.expectedJwkThumbprint
1962
- });
1963
- return {
1964
- jwk: header.jwk,
1965
- jwkThumbprint
1966
- };
1967
- }
1968
- async function verifyAccessTokenRequestPkce(options, callbacks) {
1969
- if (options.codeChallenge && !options.codeVerifier) throw new Oauth2ServerErrorResponseError({
1970
- error: Oauth2ErrorCodes.InvalidRequest,
1971
- error_description: `Missing required 'code_verifier' in access token request`
1972
- });
1973
- if (!options.codeVerifier) return null;
1974
- try {
1975
- await verifyPkce({
1976
- callbacks,
1977
- codeChallenge: options.codeChallenge,
1978
- codeChallengeMethod: options.codeChallengeMethod,
1979
- codeVerifier: options.codeVerifier
1980
- });
1981
- } catch (error) {
1982
- if (error instanceof Oauth2Error) throw new Oauth2ServerErrorResponseError({
1983
- error: Oauth2ErrorCodes.InvalidGrant,
1984
- error_description: error.message
1985
- });
1986
- throw error;
1987
- }
1988
- }
1989
-
1990
- //#endregion
1991
- //#region src/authorization-challenge/z-authorization-challenge.ts
1992
- const zAuthorizationChallengeRequest = zod.default.object({
1993
- ...zAuthorizationRequest.omit({
1994
- response_type: true,
1995
- client_id: true
1996
- }).shape,
1997
- client_id: zod.default.optional(zAuthorizationRequest.shape.client_id),
1998
- auth_session: zod.default.optional(zod.default.string()),
1999
- presentation_during_issuance_session: zod.default.optional(zod.default.string())
2000
- }).loose();
2001
- const zAuthorizationChallengeResponse = zod.default.object({ authorization_code: zod.default.string() }).loose();
2002
- const zAuthorizationChallengeErrorResponse = zod.default.object({
2003
- ...zOauth2ErrorResponse.shape,
2004
- auth_session: zod.default.optional(zod.default.string()),
2005
- request_uri: zod.default.optional(zod.default.string()),
2006
- expires_in: zod.default.optional(__openid4vc_utils.zInteger),
2007
- presentation: zod.default.optional(zod.default.string())
2008
- }).loose();
2009
-
2010
- //#endregion
2011
- //#region src/authorization-challenge/create-authorization-challenge-response.ts
2012
- /**
2013
- * Create an authorization challenge response
2014
- *
2015
- * @throws {ValidationError} if an error occurred during verification of the {@link AuthorizationChallengeResponse}
2016
- */
2017
- function createAuthorizationChallengeResponse(options) {
2018
- return { authorizationChallengeResponse: (0, __openid4vc_utils.parseWithErrorHandling)(zAuthorizationChallengeResponse, {
2019
- ...options.additionalPayload,
2020
- authorization_code: options.authorizationCode
2021
- }) };
2022
- }
2023
- /**
2024
- * Create an authorization challenge error response
2025
- *
2026
- * @throws {ValidationError} if an error occurred during validation of the {@link AuthorizationChallengeErrorResponse}
2027
- */
2028
- function createAuthorizationChallengeErrorResponse(options) {
2029
- return (0, __openid4vc_utils.parseWithErrorHandling)(zAuthorizationChallengeErrorResponse, {
2030
- ...options.additionalPayload,
2031
- error: options.error,
2032
- error_description: options.errorDescription,
2033
- auth_session: options.authSession,
2034
- presentation: options.presentation,
2035
- request_uri: options.requestUri,
2036
- expires_in: options.expiresIn
2037
- });
2038
- }
2039
-
2040
- //#endregion
2041
- //#region src/authorization-challenge/parse-authorization-challenge-request.ts
2042
- /**
2043
- * Parse an authorization challenge request.
2044
- *
2045
- * @throws {Oauth2ServerErrorResponseError}
2046
- */
2047
- function parseAuthorizationChallengeRequest(options) {
2048
- const parsedAuthorizationChallengeRequest = zAuthorizationChallengeRequest.safeParse(options.authorizationChallengeRequest);
2049
- if (!parsedAuthorizationChallengeRequest.success) throw new Oauth2ServerErrorResponseError({
2050
- error: Oauth2ErrorCodes.InvalidRequest,
2051
- error_description: `Error occurred during validation of authorization challenge request.\n${(0, __openid4vc_utils.formatZodError)(parsedAuthorizationChallengeRequest.error)}`
2052
- });
2053
- const authorizationChallengeRequest = parsedAuthorizationChallengeRequest.data;
2054
- const { clientAttestation, dpop } = parseAuthorizationRequest({
2055
- authorizationRequest: authorizationChallengeRequest,
2056
- request: options.request
2057
- });
2058
- return {
2059
- authorizationChallengeRequest: parsedAuthorizationChallengeRequest.data,
2060
- dpop,
2061
- clientAttestation
2062
- };
2063
- }
2064
-
2065
- //#endregion
2066
- //#region src/authorization-request/verify-authorization-request.ts
2067
- async function verifyAuthorizationRequest(options) {
2068
- const dpopResult = options.dpop ? await verifyAuthorizationRequestDpop(options.dpop, options.request, options.callbacks, options.now) : void 0;
2069
- const clientAttestationResult = options.clientAttestation ? await verifyAuthorizationRequestClientAttestation(options.clientAttestation, options.authorizationServerMetadata, options.callbacks, dpopResult?.jwkThumbprint, options.now, options.authorizationRequest.client_id) : void 0;
2070
- return {
2071
- dpop: dpopResult?.jwkThumbprint ? {
2072
- jwkThumbprint: dpopResult.jwkThumbprint,
2073
- jwk: dpopResult.jwk
2074
- } : void 0,
2075
- clientAttestation: clientAttestationResult
2076
- };
2077
- }
2078
- async function verifyAuthorizationRequestClientAttestation(options, authorizationServerMetadata, callbacks, dpopJwkThumbprint, now, requestClientId) {
2079
- if (!options.clientAttestationJwt || !options.clientAttestationPopJwt) {
2080
- if (!options.required && !options.clientAttestationJwt && !options.clientAttestationPopJwt) return;
2081
- throw new Oauth2ServerErrorResponseError({
2082
- error: Oauth2ErrorCodes.InvalidClient,
2083
- error_description: `Missing required client attestation parameters in pushed authorization request. Make sure to provide the '${oauthClientAttestationHeader}' and '${oauthClientAttestationPopHeader}' header values.`
2084
- });
2085
- }
2086
- const verifiedClientAttestation = await verifyClientAttestation({
2087
- authorizationServer: authorizationServerMetadata.issuer,
2088
- callbacks,
2089
- clientAttestationJwt: options.clientAttestationJwt,
2090
- clientAttestationPopJwt: options.clientAttestationPopJwt,
2091
- now
2092
- });
2093
- if (requestClientId && requestClientId !== verifiedClientAttestation.clientAttestation.payload.sub) throw new Oauth2ServerErrorResponseError({
2094
- error: Oauth2ErrorCodes.InvalidClient,
2095
- error_description: `The client_id '${requestClientId}' in the request does not match the client id '${verifiedClientAttestation.clientAttestation.payload.sub}' in the client attestation`
2096
- }, { status: 401 });
2097
- if (options.ensureConfirmationKeyMatchesDpopKey && dpopJwkThumbprint) {
2098
- if (await calculateJwkThumbprint({
2099
- hashAlgorithm: HashAlgorithm.Sha256,
2100
- hashCallback: callbacks.hash,
2101
- jwk: verifiedClientAttestation.clientAttestation.payload.cnf.jwk
2102
- }) !== dpopJwkThumbprint) throw new Oauth2ServerErrorResponseError({
2103
- error: Oauth2ErrorCodes.InvalidRequest,
2104
- error_description: "Expected the DPoP JWK thumbprint value to match the JWK thumbprint of the client attestation confirmation JWK. Ensure both DPoP and client attestation use the same key."
2105
- }, { status: 401 });
2106
- }
2107
- return verifiedClientAttestation;
2108
- }
2109
- async function verifyAuthorizationRequestDpop(options, request, callbacks, now) {
2110
- if (options.required && !options.jwt && !options.jwkThumbprint) throw new Oauth2ServerErrorResponseError({
2111
- error: Oauth2ErrorCodes.InvalidDpopProof,
2112
- error_description: `Missing required DPoP parameters in authorization request. Either DPoP header or 'dpop_jkt' is required.`
2113
- });
2114
- const verifyDpopResult = options.jwt ? await verifyDpopJwt({
2115
- callbacks,
2116
- dpopJwt: options.jwt,
2117
- request,
2118
- allowedSigningAlgs: options.allowedSigningAlgs,
2119
- now
2120
- }) : void 0;
2121
- if (options.jwkThumbprint && verifyDpopResult && options.jwkThumbprint !== verifyDpopResult.jwkThumbprint) throw new Oauth2ServerErrorResponseError({
2122
- error: Oauth2ErrorCodes.InvalidDpopProof,
2123
- error_description: `DPoP jwk thumbprint does not match with 'dpop_jkt' provided in authorization request`
2124
- });
2125
- return {
2126
- jwk: verifyDpopResult?.header.jwk,
2127
- jwkThumbprint: verifyDpopResult?.jwkThumbprint ?? options.jwkThumbprint
2128
- };
2129
- }
2130
-
2131
- //#endregion
2132
- //#region src/authorization-challenge/verify-authorization-challenge-request.ts
2133
- async function verifyAuthorizationChallengeRequest(options) {
2134
- const { clientAttestation, dpop } = await verifyAuthorizationRequest({
2135
- ...options,
2136
- authorizationRequest: options.authorizationChallengeRequest
2137
- });
2138
- return {
2139
- dpop,
2140
- clientAttestation
2141
- };
2142
- }
2143
-
2144
- //#endregion
2145
- //#region src/authorization-request/create-pushed-authorization-response.ts
2146
- /**
2147
- * Create an pushed authorization response
2148
- *
2149
- * @throws {ValidationError} if an error occurred during verification of the {@link PushedAuthorizationResponse}
2150
- */
2151
- function createPushedAuthorizationResponse(options) {
2152
- return { pushedAuthorizationResponse: (0, __openid4vc_utils.parseWithErrorHandling)(zPushedAuthorizationResponse, {
2153
- ...options.additionalPayload,
2154
- expires_in: options.expiresInSeconds,
2155
- request_uri: options.requestUri
2156
- }) };
2157
- }
2158
- /**
2159
- * Create a pushed authorization error response
2160
- *
2161
- * @throws {ValidationError} if an error occurred during validation of the {@link PushedAuthorizationErrorResponse}
2162
- */
2163
- function createPushedAuthorizationErrorResponse(options) {
2164
- return (0, __openid4vc_utils.parseWithErrorHandling)(zAccessTokenErrorResponse, {
2165
- ...options.additionalPayload,
2166
- error: options.error,
2167
- error_description: options.errorDescription
2168
- });
2169
- }
2170
-
2171
- //#endregion
2172
- //#region src/authorization-request/verify-pushed-authorization-request.ts
2173
- async function verifyPushedAuthorizationRequest(options) {
2174
- let jar;
2175
- if (options.authorizationRequestJwt) jar = await verifyJarRequest({
2176
- authorizationRequestJwt: options.authorizationRequestJwt.jwt,
2177
- jarRequestParams: options.authorizationRequest,
2178
- callbacks: options.callbacks,
2179
- jwtSigner: options.authorizationRequestJwt.signer
2180
- });
2181
- const { clientAttestation, dpop } = await verifyAuthorizationRequest(options);
2182
- return {
2183
- dpop,
2184
- clientAttestation,
2185
- jar
2186
- };
2187
- }
2188
-
2189
- //#endregion
2190
- //#region src/Oauth2AuthorizationServer.ts
2191
- var Oauth2AuthorizationServer = class {
2192
- constructor(options) {
2193
- this.options = options;
2194
- }
2195
- createAuthorizationServerMetadata(authorizationServerMetadata) {
2196
- return (0, __openid4vc_utils.parseWithErrorHandling)(zAuthorizationServerMetadata, authorizationServerMetadata, "Error validating authorization server metadata");
2197
- }
2198
- /**
2199
- * Parse access token request and extract the grant specific properties.
2200
- *
2201
- * If something goes wrong, such as the grant is not supported, missing parameters, etc,
2202
- * it will throw `Oauth2ServerErrorResponseError` containing an error response object
2203
- * that can be returned to the client.
2204
- */
2205
- parseAccessTokenRequest(options) {
2206
- return parseAccessTokenRequest(options);
2207
- }
2208
- verifyPreAuthorizedCodeAccessTokenRequest(options) {
2209
- return verifyPreAuthorizedCodeAccessTokenRequest({
2210
- ...options,
2211
- callbacks: this.options.callbacks
2212
- });
2213
- }
2214
- verifyAuthorizationCodeAccessTokenRequest(options) {
2215
- return verifyAuthorizationCodeAccessTokenRequest({
2216
- ...options,
2217
- callbacks: this.options.callbacks
2218
- });
2219
- }
2220
- verifyRefreshTokenAccessTokenRequest(options) {
2221
- return verifyRefreshTokenAccessTokenRequest({
2222
- ...options,
2223
- callbacks: this.options.callbacks
2224
- });
2225
- }
2226
- /**
2227
- * Create an access token response.
2228
- *
2229
- * The `sub` claim can be used to identify the resource owner is subsequent requests.
2230
- * For pre-auth flow this can be the pre-authorized_code but there are no requirements
2231
- * on the value.
2232
- *
2233
- * To generate a refresh token, set the `refreshToken` option to `true`. You can
2234
- * also provide a custom refresh token string.
2235
- */
2236
- async createAccessTokenResponse(options) {
2237
- const { jwt: accessToken } = await createAccessTokenJwt({
2238
- audience: options.audience,
2239
- authorizationServer: options.authorizationServer,
2240
- callbacks: this.options.callbacks,
2241
- expiresInSeconds: options.expiresInSeconds,
2242
- subject: options.subject,
2243
- scope: options.scope,
2244
- clientId: options.clientId,
2245
- signer: options.signer,
2246
- dpop: options.dpop,
2247
- now: options.now,
2248
- additionalPayload: options.additionalAccessTokenPayload
2249
- });
2250
- return createAccessTokenResponse({
2251
- accessToken,
2252
- refreshToken: typeof options.refreshToken === "string" ? options.refreshToken : options.refreshToken ? (0, __openid4vc_utils.encodeToBase64Url)(await this.options.callbacks.generateRandom(32)) : void 0,
2253
- callbacks: this.options.callbacks,
2254
- expiresInSeconds: options.expiresInSeconds,
2255
- tokenType: options.dpop ? "DPoP" : "Bearer",
2256
- cNonce: options.cNonce,
2257
- cNonceExpiresIn: options.cNonceExpiresIn,
2258
- additionalPayload: options.additionalAccessTokenResponsePayload
2259
- });
2260
- }
2261
- /**
2262
- * Parse a pushed authorization request
2263
- */
2264
- async parsePushedAuthorizationRequest(options) {
2265
- return await parsePushedAuthorizationRequest({
2266
- ...options,
2267
- callbacks: this.options.callbacks
2268
- });
2269
- }
2270
- /**
2271
- * Verify pushed authorization request.
2272
- *
2273
- * Make sure to provide the `authorizationRequestJwt` if this was returned in the `parsePushedAuthorizationRequest`
2274
- */
2275
- verifyPushedAuthorizationRequest(options) {
2276
- return verifyPushedAuthorizationRequest({
2277
- ...options,
2278
- callbacks: this.options.callbacks
2279
- });
2280
- }
2281
- createPushedAuthorizationResponse(options) {
2282
- return createPushedAuthorizationResponse(options);
2283
- }
2284
- createPushedAuthorizationErrorResponse(options) {
2285
- return createPushedAuthorizationErrorResponse(options);
2286
- }
2287
- /**
2288
- * Parse an authorization challenge request
2289
- */
2290
- parseAuthorizationChallengeRequest(options) {
2291
- return parseAuthorizationChallengeRequest(options);
2292
- }
2293
- verifyAuthorizationChallengeRequest(options) {
2294
- return verifyAuthorizationChallengeRequest({
2295
- ...options,
2296
- callbacks: this.options.callbacks
2297
- });
2298
- }
2299
- createAuthorizationChallengeResponse(options) {
2300
- return createAuthorizationChallengeResponse(options);
2301
- }
2302
- /**
2303
- * Create an authorization challenge error response indicating presentation of credentials
2304
- * using OpenID4VP is required before authorization can be granted.
2305
- *
2306
- * The `presentation` parameter should be an OpenID4VP authorization request url.
2307
- * The `authSession` should be used to track the session
2308
- */
2309
- createAuthorizationChallengePresentationErrorResponse(options) {
2310
- return createAuthorizationChallengeErrorResponse({
2311
- error: Oauth2ErrorCodes.InsufficientAuthorization,
2312
- errorDescription: options.errorDescription,
2313
- additionalPayload: options.additionalPayload,
2314
- authSession: options.authSession,
2315
- presentation: options.presentation
2316
- });
2317
- }
2318
- createAuthorizationChallengeErrorResponse(options) {
2319
- return createAuthorizationChallengeErrorResponse(options);
2320
- }
2321
- async verifyDpopJwt(options) {
2322
- return verifyDpopJwt({
2323
- ...options,
2324
- callbacks: this.options.callbacks
2325
- });
2326
- }
2327
- async verifyClientAttestation(options) {
2328
- return verifyClientAttestation({
2329
- ...options,
2330
- callbacks: this.options.callbacks
2331
- });
2332
- }
2333
- };
2334
-
2335
- //#endregion
2336
- //#region src/dpop/dpop-retry.ts
2337
- async function authorizationServerRequestWithDpopRetry(options) {
2338
- try {
2339
- return await options.request(options.dpop);
2340
- } catch (error) {
2341
- if (options.dpop && error instanceof Oauth2ClientErrorResponseError) {
2342
- const dpopRetry = shouldRetryAuthorizationServerRequestWithDPoPNonce({
2343
- responseHeaders: error.response.headers,
2344
- errorResponse: error.errorResponse
2345
- });
2346
- if (dpopRetry.retry) return options.request({
2347
- ...options.dpop,
2348
- nonce: dpopRetry.dpopNonce
2349
- });
2350
- }
2351
- throw error;
2352
- }
2353
- }
2354
- function shouldRetryAuthorizationServerRequestWithDPoPNonce(options) {
2355
- if (options.errorResponse.error !== "use_dpop_nonce") return { retry: false };
2356
- const dpopNonce = extractDpopNonceFromHeaders(options.responseHeaders);
2357
- if (!dpopNonce) throw new Oauth2Error(`Error response error contains error 'use_dpop_nonce' but the response headers do not include a valid 'DPoP-Nonce' header value.`);
2358
- return {
2359
- retry: true,
2360
- dpopNonce
2361
- };
2362
- }
2363
- function shouldRetryResourceRequestWithDPoPNonce(options) {
2364
- if (!options.resourceUnauthorizedError.wwwAuthenticateHeaders.find((challenge) => challenge.scheme === SupportedAuthenticationScheme.DPoP && challenge.error === Oauth2ErrorCodes.UseDpopNonce)) return { retry: false };
2365
- const dpopNonce = extractDpopNonceFromHeaders(options.responseHeaders);
2366
- if (!dpopNonce || typeof dpopNonce !== "string") throw new Oauth2Error(`Resource request error in 'WWW-Authenticate' response header contains error 'use_dpop_nonce' but the response headers do not include a valid 'DPoP-Nonce' value.`);
2367
- return {
2368
- retry: true,
2369
- dpopNonce
2370
- };
2371
- }
2372
-
2373
- //#endregion
2374
- //#region src/access-token/retrieve-access-token.ts
2375
- async function retrievePreAuthorizedCodeAccessToken(options) {
2376
- const request = {
2377
- grant_type: preAuthorizedCodeGrantIdentifier,
2378
- "pre-authorized_code": options.preAuthorizedCode,
2379
- tx_code: options.txCode,
2380
- resource: options.resource,
2381
- ...options.additionalRequestPayload
2382
- };
2383
- return retrieveAccessToken({
2384
- authorizationServerMetadata: options.authorizationServerMetadata,
2385
- request,
2386
- dpop: options.dpop,
2387
- callbacks: options.callbacks,
2388
- resource: options.resource
2389
- });
2390
- }
2391
- async function retrieveAuthorizationCodeAccessToken(options) {
2392
- const request = {
2393
- grant_type: authorizationCodeGrantIdentifier,
2394
- code: options.authorizationCode,
2395
- code_verifier: options.pkceCodeVerifier,
2396
- redirect_uri: options.redirectUri,
2397
- resource: options.resource,
2398
- ...options.additionalRequestPayload
2399
- };
2400
- return retrieveAccessToken({
2401
- authorizationServerMetadata: options.authorizationServerMetadata,
2402
- request,
2403
- dpop: options.dpop,
2404
- resource: options.resource,
2405
- callbacks: options.callbacks
2406
- });
2407
- }
2408
- async function retrieveRefreshTokenAccessToken(options) {
2409
- const request = {
2410
- grant_type: refreshTokenGrantIdentifier,
2411
- refresh_token: options.refreshToken,
2412
- resource: options.resource,
2413
- ...options.additionalRequestPayload
2414
- };
2415
- return retrieveAccessToken({
2416
- authorizationServerMetadata: options.authorizationServerMetadata,
2417
- request,
2418
- dpop: options.dpop,
2419
- callbacks: options.callbacks,
2420
- resource: options.resource
2421
- });
2422
- }
2423
- /**
2424
- * Internal method
2425
- */
2426
- async function retrieveAccessToken(options) {
2427
- const fetchWithZod = (0, __openid4vc_utils.createZodFetcher)(options.callbacks.fetch);
2428
- const accessTokenRequest = (0, __openid4vc_utils.parseWithErrorHandling)(zAccessTokenRequest, options.request, "Error validating access token request");
2429
- if (accessTokenRequest.tx_code) accessTokenRequest.user_pin = accessTokenRequest.tx_code;
2430
- return await authorizationServerRequestWithDpopRetry({
2431
- dpop: options.dpop,
2432
- request: async (dpop) => {
2433
- const dpopHeaders = dpop ? await createDpopHeadersForRequest({
2434
- request: {
2435
- method: "POST",
2436
- url: options.authorizationServerMetadata.token_endpoint
2437
- },
2438
- signer: dpop.signer,
2439
- callbacks: options.callbacks,
2440
- nonce: dpop.nonce
2441
- }) : void 0;
2442
- const headers = new __openid4vc_utils.Headers({
2443
- "Content-Type": __openid4vc_utils.ContentType.XWwwFormUrlencoded,
2444
- ...dpopHeaders
2445
- });
2446
- await options.callbacks.clientAuthentication({
2447
- url: options.authorizationServerMetadata.token_endpoint,
2448
- method: "POST",
2449
- authorizationServerMetadata: options.authorizationServerMetadata,
2450
- body: accessTokenRequest,
2451
- contentType: __openid4vc_utils.ContentType.XWwwFormUrlencoded,
2452
- headers
2453
- });
2454
- const { response, result } = await fetchWithZod(zAccessTokenResponse, __openid4vc_utils.ContentType.Json, options.authorizationServerMetadata.token_endpoint, {
2455
- body: (0, __openid4vc_utils.objectToQueryParams)(accessTokenRequest).toString(),
2456
- method: "POST",
2457
- headers
2458
- });
2459
- if (!response.ok || !result) {
2460
- const tokenErrorResponse = zAccessTokenErrorResponse.safeParse(await response.clone().json().catch(() => null));
2461
- if (tokenErrorResponse.success) throw new Oauth2ClientErrorResponseError(`Unable to retrieve access token from '${options.authorizationServerMetadata.token_endpoint}'. Received token error response with status ${response.status}`, tokenErrorResponse.data, response);
2462
- throw new __openid4vc_utils.InvalidFetchResponseError(`Unable to retrieve access token from '${options.authorizationServerMetadata.token_endpoint}'. Received response with status ${response.status}`, await response.clone().text(), response);
2463
- }
2464
- if (!result.success) throw new ValidationError$1("Error validating access token response", result.error);
2465
- const dpopNonce = extractDpopNonceFromHeaders(response.headers) ?? void 0;
2466
- return {
2467
- dpop: dpop ? {
2468
- ...dpop,
2469
- nonce: dpopNonce
2470
- } : void 0,
2471
- accessTokenResponse: result.data
2472
- };
2473
- }
2474
- });
2475
- }
2476
-
2477
- //#endregion
2478
- //#region src/authorization-challenge/send-authorization-challenge.ts
2479
- /**
2480
- * Send an authorization challenge request.
2481
- *
2482
- * @throws {Oauth2ClientAuthorizationChallengeError} if the request failed and a {@link AuthorizationChallengeErrorResponse} is returned
2483
- * @throws {InvalidFetchResponseError} if the request failed but no error response could be parsed
2484
- * @throws {ValidationError} if a successful response was received but an error occurred during verification of the {@link AuthorizationChallengeResponse}
2485
- */
2486
- async function sendAuthorizationChallengeRequest(options) {
2487
- const fetchWithZod = (0, __openid4vc_utils.createZodFetcher)(options.callbacks.fetch);
2488
- const authorizationServerMetadata = options.authorizationServerMetadata;
2489
- const authorizationChallengeEndpoint = authorizationServerMetadata.authorization_challenge_endpoint;
2490
- if (!authorizationChallengeEndpoint) throw new Oauth2Error(`Unable to send authorization challenge. Authorization server '${authorizationServerMetadata.issuer}' has no 'authorization_challenge_endpoint'`);
2491
- const pkce = authorizationServerMetadata.code_challenge_methods_supported && !options.authSession ? await createPkce({
2492
- allowedCodeChallengeMethods: authorizationServerMetadata.code_challenge_methods_supported,
2493
- callbacks: options.callbacks,
2494
- codeVerifier: options.pkceCodeVerifier
2495
- }) : void 0;
2496
- const authorizationChallengeRequest = (0, __openid4vc_utils.parseWithErrorHandling)(zAuthorizationChallengeRequest, {
2497
- ...options.additionalRequestPayload,
2498
- auth_session: options.authSession,
2499
- scope: options.scope,
2500
- redirect_uri: options.redirectUri,
2501
- resource: options.resource,
2502
- state: options.state,
2503
- code_challenge: pkce?.codeChallenge,
2504
- code_challenge_method: pkce?.codeChallengeMethod,
2505
- presentation_during_issuance_session: options.presentationDuringIssuanceSession
2506
- });
2507
- return authorizationServerRequestWithDpopRetry({
2508
- dpop: options.dpop,
2509
- request: async (dpop) => {
2510
- const headers = new __openid4vc_utils.Headers({
2511
- ...dpop ? await createDpopHeadersForRequest({
2512
- request: {
2513
- method: "POST",
2514
- url: authorizationChallengeEndpoint
2515
- },
2516
- signer: dpop.signer,
2517
- callbacks: options.callbacks,
2518
- nonce: dpop.nonce
2519
- }) : void 0,
2520
- "Content-Type": __openid4vc_utils.ContentType.XWwwFormUrlencoded
2521
- });
2522
- await options.callbacks.clientAuthentication({
2523
- url: authorizationChallengeEndpoint,
2524
- method: "POST",
2525
- authorizationServerMetadata: options.authorizationServerMetadata,
2526
- body: authorizationChallengeRequest,
2527
- contentType: __openid4vc_utils.ContentType.XWwwFormUrlencoded,
2528
- headers
2529
- });
2530
- const { response, result } = await fetchWithZod(zAuthorizationChallengeResponse, __openid4vc_utils.ContentType.Json, authorizationChallengeEndpoint, {
2531
- method: "POST",
2532
- body: (0, __openid4vc_utils.objectToQueryParams)(authorizationChallengeRequest).toString(),
2533
- headers
2534
- });
2535
- if (!response.ok || !result) {
2536
- const authorizationChallengeErrorResponse = zAuthorizationChallengeErrorResponse.safeParse(await response.clone().json().catch(() => null));
2537
- if (authorizationChallengeErrorResponse.success) throw new Oauth2ClientAuthorizationChallengeError(`Error requesting authorization code from authorization challenge endpoint '${authorizationServerMetadata.authorization_challenge_endpoint}'. Received response with status ${response.status}`, authorizationChallengeErrorResponse.data, response);
2538
- throw new __openid4vc_utils.InvalidFetchResponseError(`Error requesting authorization code from authorization challenge endpoint '${authorizationServerMetadata.authorization_challenge_endpoint}'. Received response with status ${response.status}`, await response.clone().text(), response);
2539
- }
2540
- if (!result.success) throw new __openid4vc_utils.ValidationError("Error validating authorization challenge response", result.error);
2541
- const dpopNonce = extractDpopNonceFromHeaders(response.headers) ?? void 0;
2542
- return {
2543
- pkce,
2544
- dpop: dpop ? {
2545
- ...dpop,
2546
- nonce: dpopNonce
2547
- } : void 0,
2548
- authorizationChallengeResponse: result.data
2549
- };
2550
- }
2551
- });
2552
- }
2553
-
2554
- //#endregion
2555
- //#region src/authorization-request/create-authorization-request.ts
2556
- /**
2557
- * Create an authorization request url that can be used for authorization.
2558
- *
2559
- * If the authorization server supports Pushed Authorization Requests (PAR) the
2560
- * request will first be pushed to the authorization request, and a reference to
2561
- * the authorization request will be returned (using the 'request_uri' param).
2562
- */
2563
- async function createAuthorizationRequestUrl(options) {
2564
- const authorizationServerMetadata = options.authorizationServerMetadata;
2565
- const pushedAuthorizationRequestEndpoint = authorizationServerMetadata.pushed_authorization_request_endpoint;
2566
- if (!authorizationServerMetadata.authorization_endpoint) throw new Oauth2Error(`Unable to create authorization request url. Authorization server '${authorizationServerMetadata.issuer}' has no 'authorization_endpoint'`);
2567
- const pkce = authorizationServerMetadata.code_challenge_methods_supported ? await createPkce({
2568
- allowedCodeChallengeMethods: authorizationServerMetadata.code_challenge_methods_supported,
2569
- callbacks: options.callbacks,
2570
- codeVerifier: options.pkceCodeVerifier
2571
- }) : void 0;
2572
- const authorizationRequest = {
2573
- ...options.additionalRequestPayload,
2574
- response_type: "code",
2575
- client_id: options.clientId,
2576
- redirect_uri: options.redirectUri,
2577
- resource: options.resource,
2578
- scope: options.scope,
2579
- state: options.state,
2580
- code_challenge: pkce?.codeChallenge,
2581
- code_challenge_method: pkce?.codeChallengeMethod
2582
- };
2583
- let pushedAuthorizationRequest;
2584
- let dpop = options.dpop;
2585
- if (authorizationServerMetadata.require_pushed_authorization_requests || pushedAuthorizationRequestEndpoint) {
2586
- if (!pushedAuthorizationRequestEndpoint) throw new Oauth2Error(`Authorization server '${authorizationServerMetadata.issuer}' indicated that pushed authorization requests are required, but the 'pushed_authorization_request_endpoint' is missing in the authorization server metadata.`);
2587
- const { pushedAuthorizationResponse, dpopNonce } = await authorizationServerRequestWithDpopRetry({
2588
- dpop: options.dpop,
2589
- request: async (dpop$1) => {
2590
- const dpopHeaders = dpop$1 ? await createDpopHeadersForRequest({
2591
- request: {
2592
- method: "POST",
2593
- url: pushedAuthorizationRequestEndpoint
2594
- },
2595
- signer: dpop$1.signer,
2596
- callbacks: options.callbacks,
2597
- nonce: dpop$1.nonce
2598
- }) : void 0;
2599
- return await pushAuthorizationRequest({
2600
- authorizationServerMetadata,
2601
- authorizationRequest,
2602
- pushedAuthorizationRequestEndpoint,
2603
- callbacks: options.callbacks,
2604
- headers: dpopHeaders
2605
- });
2606
- }
2607
- });
2608
- pushedAuthorizationRequest = {
2609
- request_uri: pushedAuthorizationResponse.request_uri,
2610
- client_id: authorizationRequest.client_id
2611
- };
2612
- if (options.dpop && dpopNonce) dpop = {
2613
- ...options.dpop,
2614
- nonce: dpopNonce
2615
- };
2616
- } else if (options.dpop) authorizationRequest.dpop_jkt = await calculateJwkThumbprint({
2617
- hashAlgorithm: HashAlgorithm.Sha256,
2618
- hashCallback: options.callbacks.hash,
2619
- jwk: options.dpop.signer.publicJwk
2620
- });
2621
- return {
2622
- authorizationRequestUrl: `${authorizationServerMetadata.authorization_endpoint}?${(0, __openid4vc_utils.objectToQueryParams)(pushedAuthorizationRequest ?? authorizationRequest).toString()}`,
2623
- pkce,
2624
- dpop
2625
- };
2626
- }
2627
- async function pushAuthorizationRequest(options) {
2628
- const fetchWithZod = (0, __openid4vc_utils.createZodFetcher)(options.callbacks.fetch);
2629
- if (options.authorizationRequest.request_uri) throw new Oauth2Error(`Authorization request contains 'request_uri' parameter. This is not allowed for pushed authorization requests.`);
2630
- const headers = new __openid4vc_utils.Headers({
2631
- ...options.headers,
2632
- "Content-Type": __openid4vc_utils.ContentType.XWwwFormUrlencoded
2633
- });
2634
- await options.callbacks.clientAuthentication({
2635
- url: options.pushedAuthorizationRequestEndpoint,
2636
- method: "POST",
2637
- authorizationServerMetadata: options.authorizationServerMetadata,
2638
- body: options.authorizationRequest,
2639
- contentType: __openid4vc_utils.ContentType.XWwwFormUrlencoded,
2640
- headers
2641
- });
2642
- const { response, result } = await fetchWithZod(zPushedAuthorizationResponse, __openid4vc_utils.ContentType.Json, options.pushedAuthorizationRequestEndpoint, {
2643
- method: "POST",
2644
- body: (0, __openid4vc_utils.objectToQueryParams)(options.authorizationRequest).toString(),
2645
- headers
2646
- });
2647
- if (!response.ok || !result) {
2648
- const parErrorResponse = zOauth2ErrorResponse.safeParse(await response.clone().json().catch(() => null));
2649
- if (parErrorResponse.success) throw new Oauth2ClientErrorResponseError(`Unable to push authorization request to '${options.pushedAuthorizationRequestEndpoint}'. Received response with status ${response.status}`, parErrorResponse.data, response);
2650
- throw new __openid4vc_utils.InvalidFetchResponseError(`Unable to push authorization request to '${options.pushedAuthorizationRequestEndpoint}'. Received response with status ${response.status}`, await response.clone().text(), response);
2651
- }
2652
- if (!result.success) throw new ValidationError$1("Error validating pushed authorization response", result.error);
2653
- return {
2654
- dpopNonce: extractDpopNonceFromHeaders(response.headers),
2655
- pushedAuthorizationResponse: result.data
2656
- };
2657
- }
2658
-
2659
- //#endregion
2660
- //#region src/resource-request/make-resource-request.ts
2661
- async function resourceRequest(options) {
2662
- const dpopHeaders = options.dpop ? await createDpopHeadersForRequest({
2663
- request: {
2664
- url: options.url,
2665
- method: options.requestOptions.method ?? "GET"
2666
- },
2667
- signer: options.dpop.signer,
2668
- callbacks: options.callbacks,
2669
- nonce: options.dpop.nonce,
2670
- accessToken: options.accessToken
2671
- }) : void 0;
2672
- const response = await (0, __openid4vc_utils.createFetcher)(options.callbacks.fetch)(options.url, {
2673
- ...options.requestOptions,
2674
- headers: {
2675
- ...options.requestOptions.headers,
2676
- Authorization: `${dpopHeaders ? "DPoP" : "Bearer"} ${options.accessToken}`,
2677
- ...dpopHeaders
2678
- }
2679
- });
2680
- const dpopNonce = extractDpopNonceFromHeaders(response.headers);
2681
- if (response.ok) return {
2682
- ok: true,
2683
- response,
2684
- dpop: dpopNonce ? { nonce: dpopNonce } : void 0
2685
- };
2686
- const wwwAuthenticateHeader = response.headers.get("WWW-Authenticate");
2687
- const resourceUnauthorizedError = wwwAuthenticateHeader ? Oauth2ResourceUnauthorizedError.fromHeaderValue(wwwAuthenticateHeader) : void 0;
2688
- const shouldRetryWithNonce = options.dpop?.retryWithNonce ?? true;
2689
- const dpopRetry = resourceUnauthorizedError ? shouldRetryResourceRequestWithDPoPNonce({
2690
- responseHeaders: response.headers,
2691
- resourceUnauthorizedError
2692
- }) : void 0;
2693
- if (shouldRetryWithNonce && dpopRetry?.retry && options.dpop) return await resourceRequest({
2694
- ...options,
2695
- dpop: {
2696
- ...options.dpop,
2697
- nonce: dpopRetry.dpopNonce,
2698
- retryWithNonce: false
2699
- }
2700
- });
2701
- return {
2702
- ok: false,
2703
- response,
2704
- dpop: dpopNonce ? { nonce: dpopNonce } : void 0,
2705
- wwwAuthenticate: resourceUnauthorizedError?.wwwAuthenticateHeaders
2706
- };
2707
- }
2708
-
2709
- //#endregion
2710
- //#region src/Oauth2Client.ts
2711
- var Oauth2Client = class {
2712
- constructor(options) {
2713
- this.options = options;
2714
- }
2715
- isDpopSupported(options) {
2716
- if (!options.authorizationServerMetadata.dpop_signing_alg_values_supported || options.authorizationServerMetadata.dpop_signing_alg_values_supported.length === 0) return { supported: false };
2717
- return {
2718
- supported: true,
2719
- dpopSigningAlgValuesSupported: options.authorizationServerMetadata.dpop_signing_alg_values_supported
2720
- };
2721
- }
2722
- isClientAttestationSupported(options) {
2723
- if (!options.authorizationServerMetadata.token_endpoint_auth_methods_supported || !options.authorizationServerMetadata.token_endpoint_auth_methods_supported.includes(SupportedClientAuthenticationMethod.ClientAttestationJwt)) return { supported: false };
2724
- return { supported: true };
2725
- }
2726
- async fetchAuthorizationServerMetadata(issuer) {
2727
- return fetchAuthorizationServerMetadata(issuer, this.options.callbacks.fetch);
2728
- }
2729
- /**
2730
- * Initiate authorization.
2731
- *
2732
- * It will take the followings steps:
2733
- * - if `authorization_challenge_endpoint` is defined, send an authorization challenge request
2734
- * - if authorization challenge request returns a `redirect_to_web` error code with `request_uri`
2735
- * then construct the authorization request url based on the `request_uri`
2736
- * - if the `authorization_challenge_endpoint` is not defined, or authorization challenge request reuturns a `redirect_to_web` error code without `request_uri`
2737
- * then the authorization request url will be constructed as usual (optionally using PAR).
2738
- *
2739
- * @throws {Oauth2ClientAuthorizationChallengeError} in case of an error response. If `error` is
2740
- * `insufficient_authorization` possible extra steps can be taken.
2741
- */
2742
- async initiateAuthorization(options) {
2743
- const pkce = options.authorizationServerMetadata.code_challenge_methods_supported ? await createPkce({
2744
- allowedCodeChallengeMethods: options.authorizationServerMetadata.code_challenge_methods_supported,
2745
- callbacks: this.options.callbacks,
2746
- codeVerifier: options.pkceCodeVerifier
2747
- }) : void 0;
2748
- if (options.authorizationServerMetadata.authorization_challenge_endpoint) try {
2749
- await this.sendAuthorizationChallengeRequest({
2750
- authorizationServerMetadata: options.authorizationServerMetadata,
2751
- additionalRequestPayload: options.additionalRequestPayload,
2752
- pkceCodeVerifier: pkce?.codeVerifier,
2753
- redirectUri: options.redirectUri,
2754
- scope: options.scope,
2755
- resource: options.resource,
2756
- dpop: options.dpop,
2757
- state: options.state
2758
- });
2759
- } catch (error) {
2760
- if (!(error instanceof Oauth2ClientAuthorizationChallengeError && error.errorResponse.error === Oauth2ErrorCodes.RedirectToWeb)) throw error;
2761
- if (error.errorResponse.request_uri) {
2762
- const authorizationRequestUrl = `${options.authorizationServerMetadata.authorization_endpoint}?${(0, __openid4vc_utils.objectToQueryParams)({
2763
- request_uri: error.errorResponse.request_uri,
2764
- client_id: options.clientId
2765
- }).toString()}`;
2766
- const dpopNonce = extractDpopNonceFromHeaders(error.response.headers);
2767
- return {
2768
- dpop: options.dpop ? {
2769
- ...options.dpop,
2770
- nonce: dpopNonce
2771
- } : void 0,
2772
- authorizationRequestUrl,
2773
- pkce
2774
- };
2775
- }
2776
- }
2777
- return this.createAuthorizationRequestUrl({
2778
- authorizationServerMetadata: options.authorizationServerMetadata,
2779
- clientId: options.clientId,
2780
- additionalRequestPayload: options.additionalRequestPayload,
2781
- redirectUri: options.redirectUri,
2782
- scope: options.scope,
2783
- pkceCodeVerifier: pkce?.codeVerifier,
2784
- resource: options.resource,
2785
- dpop: options.dpop,
2786
- state: options.state
2787
- });
2788
- }
2789
- sendAuthorizationChallengeRequest(options) {
2790
- return sendAuthorizationChallengeRequest({
2791
- ...options,
2792
- callbacks: this.options.callbacks
2793
- });
2794
- }
2795
- async createAuthorizationRequestUrl(options) {
2796
- return createAuthorizationRequestUrl({
2797
- authorizationServerMetadata: options.authorizationServerMetadata,
2798
- clientId: options.clientId,
2799
- additionalRequestPayload: options.additionalRequestPayload,
2800
- redirectUri: options.redirectUri,
2801
- resource: options.resource,
2802
- scope: options.scope,
2803
- callbacks: this.options.callbacks,
2804
- pkceCodeVerifier: options.pkceCodeVerifier,
2805
- dpop: options.dpop,
2806
- state: options.state
2807
- });
2808
- }
2809
- async retrievePreAuthorizedCodeAccessToken({ authorizationServerMetadata, preAuthorizedCode, additionalRequestPayload, txCode, dpop, resource }) {
2810
- return await retrievePreAuthorizedCodeAccessToken({
2811
- authorizationServerMetadata,
2812
- preAuthorizedCode,
2813
- txCode,
2814
- resource,
2815
- additionalRequestPayload: {
2816
- ...additionalRequestPayload,
2817
- tx_code: txCode
2818
- },
2819
- callbacks: this.options.callbacks,
2820
- dpop
2821
- });
2822
- }
2823
- async retrieveAuthorizationCodeAccessToken({ authorizationServerMetadata, additionalRequestPayload, authorizationCode, pkceCodeVerifier, redirectUri, resource, dpop }) {
2824
- return await retrieveAuthorizationCodeAccessToken({
2825
- authorizationServerMetadata,
2826
- authorizationCode,
2827
- pkceCodeVerifier,
2828
- additionalRequestPayload,
2829
- resource,
2830
- callbacks: this.options.callbacks,
2831
- dpop,
2832
- redirectUri
2833
- });
2834
- }
2835
- async retrieveRefreshTokenAccessToken({ authorizationServerMetadata, additionalRequestPayload, refreshToken, resource, dpop }) {
2836
- return await retrieveRefreshTokenAccessToken({
2837
- authorizationServerMetadata,
2838
- refreshToken,
2839
- additionalRequestPayload,
2840
- resource,
2841
- callbacks: this.options.callbacks,
2842
- dpop
2843
- });
2844
- }
2845
- async resourceRequest(options) {
2846
- return resourceRequest(options);
2847
- }
2848
- };
2849
-
2850
- //#endregion
2851
- //#region src/Oauth2ResourceServer.ts
2852
- var Oauth2ResourceServer = class {
2853
- constructor(options) {
2854
- this.options = options;
2855
- }
2856
- async verifyResourceRequest(options) {
2857
- return verifyResourceRequest({
2858
- callbacks: this.options.callbacks,
2859
- ...options
2860
- });
2861
- }
2862
- };
2863
-
2864
- //#endregion
2865
- //#region src/access-token/z-token-introspection.ts
2866
- const zTokenIntrospectionRequest = zod.default.object({
2867
- token: zod.default.string(),
2868
- token_type_hint: zod.default.optional(zod.default.string())
2869
- }).loose();
2870
- const zTokenIntrospectionResponse = zod.default.object({
2871
- active: zod.default.boolean(),
2872
- scope: zod.default.optional(zod.default.string()),
2873
- client_id: zod.default.optional(zod.default.string()),
2874
- username: zod.default.optional(zod.default.string()),
2875
- token_type: zod.default.optional(zod.default.string()),
2876
- exp: zod.default.optional(__openid4vc_utils.zInteger),
2877
- iat: zod.default.optional(__openid4vc_utils.zInteger),
2878
- nbf: zod.default.optional(__openid4vc_utils.zInteger),
2879
- sub: zod.default.optional(zod.default.string()),
2880
- aud: zod.default.optional(zod.default.union([zod.default.string(), zod.default.array(zod.default.string())])),
2881
- iss: zod.default.optional(zod.default.string()),
2882
- jti: zod.default.optional(zod.default.string()),
2883
- cnf: zod.default.optional(zJwtConfirmationPayload)
2884
- }).loose();
2885
-
2886
- //#endregion
2887
- //#region src/access-token/introspect-token.ts
2888
- async function introspectToken(options) {
2889
- const fetchWithZod = (0, __openid4vc_utils.createZodFetcher)(options.callbacks.fetch);
2890
- const introspectionRequest = (0, __openid4vc_utils.parseWithErrorHandling)(zTokenIntrospectionRequest, {
2891
- token: options.token,
2892
- token_type_hint: options.tokenTypeHint,
2893
- ...options.additionalPayload
2894
- });
2895
- const introspectionEndpoint = options.authorizationServerMetadata.introspection_endpoint;
2896
- if (!introspectionEndpoint) throw new Oauth2Error(`Missing required 'introspection_endpoint' parameter in authorization server metadata`);
2897
- const headers = new __openid4vc_utils.Headers({ "Content-Type": __openid4vc_utils.ContentType.XWwwFormUrlencoded });
2898
- await options.callbacks.clientAuthentication({
2899
- url: introspectionEndpoint,
2900
- method: "POST",
2901
- authorizationServerMetadata: options.authorizationServerMetadata,
2902
- body: introspectionRequest,
2903
- contentType: __openid4vc_utils.ContentType.XWwwFormUrlencoded,
2904
- headers
2905
- });
2906
- const { result, response } = await fetchWithZod(zTokenIntrospectionResponse, __openid4vc_utils.ContentType.Json, introspectionEndpoint, {
2907
- body: (0, __openid4vc_utils.objectToQueryParams)(introspectionRequest).toString(),
2908
- method: "POST",
2909
- headers
2910
- });
2911
- if (!response.ok || !result?.success) throw new __openid4vc_utils.InvalidFetchResponseError(`Unable to introspect token from '${introspectionEndpoint}'. Received response with status ${response.status}`, await response.clone().text(), response);
2912
- return result.data;
2913
- }
2914
-
2915
- //#endregion
2916
- //#region src/resource-request/verify-resource-request.ts
2917
- async function verifyResourceRequest(options) {
2918
- const allowedAuthenticationSchemes = options.allowedAuthenticationSchemes ?? Object.values(SupportedAuthenticationScheme);
2919
- if (allowedAuthenticationSchemes.length === 0) throw new Oauth2Error(`Emtpy array provided for 'allowedAuthenticationSchemes', provide at least one allowed authentication scheme, or remove the value to allow all supported authentication schemes`);
2920
- const authorizationHeader = options.request.headers.get("Authorization");
2921
- if (!authorizationHeader) throw new Oauth2ResourceUnauthorizedError(`No 'Authorization' header provided in request.`, allowedAuthenticationSchemes.map((scheme$1) => ({ scheme: scheme$1 })));
2922
- const [scheme, accessToken] = authorizationHeader.split(" ", 2);
2923
- if (!scheme || !accessToken) throw new Oauth2ResourceUnauthorizedError(`Malformed 'Authorization' header provided in request.`, allowedAuthenticationSchemes.map((scheme$1) => ({ scheme: scheme$1 })));
2924
- if (!allowedAuthenticationSchemes.includes(scheme) || scheme !== SupportedAuthenticationScheme.Bearer && scheme !== SupportedAuthenticationScheme.DPoP) throw new Oauth2ResourceUnauthorizedError(`Provided authentication scheme '${scheme}' is not allowed. Allowed authentication schemes are ${allowedAuthenticationSchemes.map((s) => `'${s}'`).join(", ")}.`, allowedAuthenticationSchemes.map((scheme$1) => ({ scheme: scheme$1 })));
2925
- const verificationResult = await verifyJwtProfileAccessToken({
2926
- accessToken,
2927
- callbacks: options.callbacks,
2928
- authorizationServers: options.authorizationServers,
2929
- resourceServer: options.resourceServer,
2930
- now: options.now
2931
- }).catch((error) => {
2932
- if (error instanceof Oauth2JwtParseError || error instanceof __openid4vc_utils.ValidationError) return null;
2933
- const errorMessage = error instanceof Oauth2Error ? error.message : "Invalid access token";
2934
- throw new Oauth2ResourceUnauthorizedError(`Error occurred during verification of jwt profile access token: ${error.message}`, {
2935
- scheme,
2936
- error: Oauth2ErrorCodes.InvalidToken,
2937
- error_description: errorMessage
2938
- });
2939
- });
2940
- let tokenPayload = verificationResult?.payload;
2941
- let authorizationServer = verificationResult?.authorizationServer;
2942
- if (!tokenPayload) for (const authorizationServerMetadata of options.authorizationServers) try {
2943
- tokenPayload = await introspectToken({
2944
- authorizationServerMetadata,
2945
- callbacks: options.callbacks,
2946
- token: accessToken,
2947
- tokenTypeHint: scheme
2948
- });
2949
- authorizationServer = authorizationServerMetadata;
2950
- if (tokenPayload.active) break;
2951
- } catch (_error) {}
2952
- if (!tokenPayload || !authorizationServer) throw new Oauth2ResourceUnauthorizedError("Could not verify token as jwt or using token introspection.", {
2953
- scheme,
2954
- error: Oauth2ErrorCodes.InvalidToken,
2955
- error_description: "Token is not valid"
2956
- });
2957
- let dpopJwk;
2958
- if (scheme === SupportedAuthenticationScheme.DPoP || tokenPayload.token_type === SupportedAuthenticationScheme.DPoP || tokenPayload.cnf?.jkt) {
2959
- const dpopJwtResult = extractDpopJwtFromHeaders(options.request.headers);
2960
- if (!dpopJwtResult.valid) throw new Oauth2ResourceUnauthorizedError(`Request contains a 'DPoP' header, but the value is not a valid DPoP jwt.`, {
2961
- scheme,
2962
- error: Oauth2ErrorCodes.InvalidDpopProof,
2963
- error_description: `Request contains a 'DPoP' header, but the value is not a valid DPoP jwt.`
2964
- });
2965
- if (!dpopJwtResult.dpopJwt) throw new Oauth2ResourceUnauthorizedError(`Request is missing required 'DPoP' header.`, {
2966
- scheme,
2967
- error: Oauth2ErrorCodes.InvalidDpopProof,
2968
- error_description: `Request is missing required 'DPoP' header.`
2969
- });
2970
- if (!tokenPayload.cnf?.jkt) throw new Oauth2ResourceUnauthorizedError(`Token payload is missing required 'cnf.jkt' value for DPoP verification.`, {
2971
- scheme,
2972
- error: Oauth2ErrorCodes.InvalidToken,
2973
- error_description: `Token payload is missing required 'cnf.jkt' value for DPoP verification.`
2974
- });
2975
- try {
2976
- dpopJwk = (await verifyDpopJwt({
2977
- callbacks: options.callbacks,
2978
- dpopJwt: dpopJwtResult.dpopJwt,
2979
- request: options.request,
2980
- accessToken,
2981
- now: options.now,
2982
- expectedJwkThumbprint: tokenPayload.cnf?.jkt,
2983
- allowedSigningAlgs: authorizationServer.dpop_signing_alg_values_supported
2984
- })).header.jwk;
2985
- } catch (error) {
2986
- const errorMessage = error instanceof Oauth2Error ? error.message : "Error verifying DPoP jwt";
2987
- throw new Oauth2ResourceUnauthorizedError(`Error occurred during verification of jwt profile access token: ${error instanceof Error ? error.message : error}`, {
2988
- scheme,
2989
- error: Oauth2ErrorCodes.InvalidDpopProof,
2990
- error_description: errorMessage
2991
- });
2992
- }
2993
- }
2994
- return {
2995
- tokenPayload,
2996
- dpop: dpopJwk ? { jwk: dpopJwk } : void 0,
2997
- scheme,
2998
- accessToken,
2999
- authorizationServer: authorizationServer.issuer
3000
- };
3001
- }
3002
-
3003
- //#endregion
3004
- exports.HashAlgorithm = HashAlgorithm;
3005
- Object.defineProperty(exports, 'InvalidFetchResponseError', {
3006
- enumerable: true,
3007
- get: function () {
3008
- return __openid4vc_utils.InvalidFetchResponseError;
3009
- }
3010
- });
3011
- exports.Oauth2AuthorizationServer = Oauth2AuthorizationServer;
3012
- exports.Oauth2Client = Oauth2Client;
3013
- exports.Oauth2ClientAuthorizationChallengeError = Oauth2ClientAuthorizationChallengeError;
3014
- exports.Oauth2ClientErrorResponseError = Oauth2ClientErrorResponseError;
3015
- exports.Oauth2Error = Oauth2Error;
3016
- exports.Oauth2ErrorCodes = Oauth2ErrorCodes;
3017
- exports.Oauth2JwtParseError = Oauth2JwtParseError;
3018
- exports.Oauth2JwtVerificationError = Oauth2JwtVerificationError;
3019
- exports.Oauth2ResourceServer = Oauth2ResourceServer;
3020
- exports.Oauth2ResourceUnauthorizedError = Oauth2ResourceUnauthorizedError;
3021
- exports.Oauth2ServerErrorResponseError = Oauth2ServerErrorResponseError;
3022
- exports.PkceCodeChallengeMethod = PkceCodeChallengeMethod;
3023
- exports.SupportedAuthenticationScheme = SupportedAuthenticationScheme;
3024
- exports.SupportedClientAuthenticationMethod = SupportedClientAuthenticationMethod;
3025
- exports.authorizationCodeGrantIdentifier = authorizationCodeGrantIdentifier;
3026
- exports.calculateJwkThumbprint = calculateJwkThumbprint;
3027
- exports.clientAuthenticationAnonymous = clientAuthenticationAnonymous;
3028
- exports.clientAuthenticationClientAttestationJwt = clientAuthenticationClientAttestationJwt;
3029
- exports.clientAuthenticationClientSecretBasic = clientAuthenticationClientSecretBasic;
3030
- exports.clientAuthenticationClientSecretPost = clientAuthenticationClientSecretPost;
3031
- exports.clientAuthenticationDynamic = clientAuthenticationDynamic;
3032
- exports.clientAuthenticationNone = clientAuthenticationNone;
3033
- exports.createClientAttestationJwt = createClientAttestationJwt;
3034
- exports.createJarAuthorizationRequest = createJarAuthorizationRequest;
3035
- exports.decodeJwt = decodeJwt;
3036
- exports.decodeJwtHeader = decodeJwtHeader;
3037
- exports.fetchAuthorizationServerMetadata = fetchAuthorizationServerMetadata;
3038
- exports.fetchJwks = fetchJwks;
3039
- exports.fetchWellKnownMetadata = fetchWellKnownMetadata;
3040
- exports.fullySpecifiedCoseAlgorithmArrayToJwaSignatureAlgorithmArray = fullySpecifiedCoseAlgorithmArrayToJwaSignatureAlgorithmArray;
3041
- exports.fullySpecifiedCoseAlgorithmToJwaSignatureAlgorithm = fullySpecifiedCoseAlgorithmToJwaSignatureAlgorithm;
3042
- exports.getAuthorizationServerMetadataFromList = getAuthorizationServerMetadataFromList;
3043
- Object.defineProperty(exports, 'getGlobalConfig', {
3044
- enumerable: true,
3045
- get: function () {
3046
- return __openid4vc_utils.getGlobalConfig;
3047
- }
3048
- });
3049
- exports.isJwkInSet = isJwkInSet;
3050
- exports.jwaSignatureAlgorithmArrayToFullySpecifiedCoseAlgorithmArray = jwaSignatureAlgorithmArrayToFullySpecifiedCoseAlgorithmArray;
3051
- exports.jwaSignatureAlgorithmToFullySpecifiedCoseAlgorithm = jwaSignatureAlgorithmToFullySpecifiedCoseAlgorithm;
3052
- exports.jwtAuthorizationRequestJwtHeaderTyp = jwtAuthorizationRequestJwtHeaderTyp;
3053
- exports.jwtHeaderFromJwtSigner = jwtHeaderFromJwtSigner;
3054
- exports.jwtSignerFromJwt = jwtSignerFromJwt;
3055
- exports.parseAuthorizationResponseRedirectUrl = parseAuthorizationResponseRedirectUrl;
3056
- exports.parsePushedAuthorizationRequestUriReferenceValue = parsePushedAuthorizationRequestUriReferenceValue;
3057
- exports.preAuthorizedCodeGrantIdentifier = preAuthorizedCodeGrantIdentifier;
3058
- exports.pushedAuthorizationRequestUriPrefix = pushedAuthorizationRequestUriPrefix;
3059
- exports.refreshTokenGrantIdentifier = refreshTokenGrantIdentifier;
3060
- exports.resourceRequest = resourceRequest;
3061
- Object.defineProperty(exports, 'setGlobalConfig', {
3062
- enumerable: true,
3063
- get: function () {
3064
- return __openid4vc_utils.setGlobalConfig;
3065
- }
3066
- });
3067
- exports.signedAuthorizationRequestJwtHeaderTyp = signedAuthorizationRequestJwtHeaderTyp;
3068
- exports.validateJarRequestParams = validateJarRequestParams;
3069
- exports.verifyClientAttestationJwt = verifyClientAttestationJwt;
3070
- exports.verifyIdTokenJwt = verifyIdTokenJwt;
3071
- exports.verifyJwt = verifyJwt;
3072
- exports.verifyResourceRequest = verifyResourceRequest;
3073
- exports.zAlgValueNotNone = zAlgValueNotNone;
3074
- exports.zAuthorizationCodeGrantIdentifier = zAuthorizationCodeGrantIdentifier;
3075
- exports.zAuthorizationErrorResponse = zAuthorizationErrorResponse;
3076
- exports.zAuthorizationResponse = zAuthorizationResponse;
3077
- exports.zAuthorizationResponseFromUriParams = zAuthorizationResponseFromUriParams;
3078
- exports.zAuthorizationServerMetadata = zAuthorizationServerMetadata;
3079
- exports.zCompactJwe = zCompactJwe;
3080
- exports.zCompactJwt = zCompactJwt;
3081
- exports.zIdTokenJwtHeader = zIdTokenJwtHeader;
3082
- exports.zIdTokenJwtPayload = zIdTokenJwtPayload;
3083
- exports.zJarAuthorizationRequest = zJarAuthorizationRequest;
3084
- exports.zJarRequestObjectPayload = zJarRequestObjectPayload;
3085
- exports.zJwk = zJwk;
3086
- exports.zJwkSet = zJwkSet;
3087
- exports.zJwtHeader = zJwtHeader;
3088
- exports.zJwtPayload = zJwtPayload;
3089
- exports.zOauth2ErrorResponse = zOauth2ErrorResponse;
3090
- exports.zPreAuthorizedCodeGrantIdentifier = zPreAuthorizedCodeGrantIdentifier;
3091
- exports.zPushedAuthorizationRequestUriPrefix = zPushedAuthorizationRequestUriPrefix;
3092
- exports.zRefreshTokenGrantIdentifier = zRefreshTokenGrantIdentifier;
3093
- //# sourceMappingURL=index.cjs.map