@pagopa/io-wallet-oauth2 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +1058 -811
- package/dist/index.d.ts +1058 -811
- package/dist/index.js +981 -800
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +971 -805
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
package/dist/index.mjs
CHANGED
|
@@ -1,16 +1,10 @@
|
|
|
1
|
-
var __defProp = Object.defineProperty;
|
|
2
|
-
var __export = (target, all) => {
|
|
3
|
-
for (var name in all)
|
|
4
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
5
|
-
};
|
|
6
|
-
|
|
7
1
|
// src/access-token/create-token-request.ts
|
|
8
2
|
var createTokenRequest = async (options) => ({
|
|
3
|
+
...options.additionalRequestPayload,
|
|
9
4
|
code: options.authorizationCode,
|
|
10
5
|
code_verifier: options.pkceCodeVerifier,
|
|
11
6
|
grant_type: "authorization_code",
|
|
12
|
-
redirect_uri: options.redirectUri
|
|
13
|
-
...options.additionalRequestPayload
|
|
7
|
+
redirect_uri: options.redirectUri
|
|
14
8
|
});
|
|
15
9
|
|
|
16
10
|
// src/access-token/create-token-response.ts
|
|
@@ -30,6 +24,7 @@ import { Oauth2JwtParseError } from "@openid4vc/oauth2";
|
|
|
30
24
|
import {
|
|
31
25
|
decodeBase64,
|
|
32
26
|
encodeToUtf8String,
|
|
27
|
+
formatError,
|
|
33
28
|
parseWithErrorHandling,
|
|
34
29
|
stringToJsonWithErrorHandling
|
|
35
30
|
} from "@pagopa/io-wallet-utils";
|
|
@@ -83,6 +78,7 @@ var zJwk = z2.looseObject({
|
|
|
83
78
|
var zJwkSet = z2.looseObject({ keys: z2.array(zJwk) });
|
|
84
79
|
|
|
85
80
|
// src/common/jwt/z-jwt.ts
|
|
81
|
+
var MAX_JTI_LENGTH = 256;
|
|
86
82
|
var zCompactJwt = z3.string().regex(/^([a-zA-Z0-9-_]+)\.([a-zA-Z0-9-_]+)\.([a-zA-Z0-9-_]+)$/, {
|
|
87
83
|
message: "Not a valid compact jwt"
|
|
88
84
|
});
|
|
@@ -97,7 +93,7 @@ var zJwtPayload = z3.looseObject({
|
|
|
97
93
|
exp: z3.number().int().optional(),
|
|
98
94
|
iat: z3.number().int().optional(),
|
|
99
95
|
iss: z3.string().optional(),
|
|
100
|
-
jti: z3.string().optional(),
|
|
96
|
+
jti: z3.string().max(MAX_JTI_LENGTH).optional(),
|
|
101
97
|
nbf: z3.number().int().optional(),
|
|
102
98
|
nonce: z3.string().optional(),
|
|
103
99
|
// Reserved for status parameters
|
|
@@ -119,23 +115,35 @@ var zJwtHeader = z3.looseObject({
|
|
|
119
115
|
function decodeJwtHeader(options) {
|
|
120
116
|
const jwtParts = options.jwt.split(".");
|
|
121
117
|
if (jwtParts.length <= 2) {
|
|
122
|
-
throw new Oauth2JwtParseError(
|
|
118
|
+
throw new Oauth2JwtParseError(
|
|
119
|
+
formatError(
|
|
120
|
+
"Unable to decode because Jwt is not a valid!",
|
|
121
|
+
options.errorMessagePrefix
|
|
122
|
+
)
|
|
123
|
+
);
|
|
123
124
|
}
|
|
124
125
|
const [headerPart] = jwtParts;
|
|
125
126
|
let headerJson;
|
|
126
127
|
try {
|
|
127
128
|
headerJson = stringToJsonWithErrorHandling(
|
|
128
129
|
encodeToUtf8String(decodeBase64(headerPart)),
|
|
129
|
-
|
|
130
|
+
formatError(
|
|
131
|
+
"Unable to parse jwt header to JSON",
|
|
132
|
+
options.errorMessagePrefix
|
|
133
|
+
)
|
|
130
134
|
);
|
|
131
135
|
} catch (error) {
|
|
132
136
|
throw new Oauth2JwtParseError(
|
|
133
|
-
|
|
137
|
+
formatError(
|
|
138
|
+
`Error parsing JWT. ${error instanceof Error ? error.message : ""}`,
|
|
139
|
+
options.errorMessagePrefix
|
|
140
|
+
)
|
|
134
141
|
);
|
|
135
142
|
}
|
|
136
143
|
const header = parseWithErrorHandling(
|
|
137
144
|
options.headerSchema ?? zJwtHeader,
|
|
138
|
-
headerJson
|
|
145
|
+
headerJson,
|
|
146
|
+
formatError("Invalid JWT header", options.errorMessagePrefix)
|
|
139
147
|
);
|
|
140
148
|
return {
|
|
141
149
|
header
|
|
@@ -174,51 +182,55 @@ function jwtHeaderFromJwtSigner(signer) {
|
|
|
174
182
|
|
|
175
183
|
// src/errors.ts
|
|
176
184
|
var Oauth2Error = class extends Error {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
185
|
+
statusCode;
|
|
186
|
+
constructor(message, options) {
|
|
187
|
+
super(message, options);
|
|
180
188
|
this.name = "Oauth2Error";
|
|
189
|
+
this.statusCode = options?.statusCode;
|
|
181
190
|
}
|
|
182
191
|
};
|
|
183
192
|
var PushedAuthorizationRequestError = class extends Oauth2Error {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
193
|
+
statusCode;
|
|
194
|
+
constructor(message, options) {
|
|
195
|
+
super(message, options);
|
|
187
196
|
this.name = "PushedAuthorizationRequestError";
|
|
197
|
+
this.statusCode = options?.statusCode;
|
|
188
198
|
}
|
|
189
199
|
};
|
|
190
200
|
var CreateTokenDPoPError = class extends Oauth2Error {
|
|
191
|
-
constructor(message) {
|
|
192
|
-
super(message);
|
|
201
|
+
constructor(message, options) {
|
|
202
|
+
super(message, options);
|
|
193
203
|
this.name = "CreateTokenDPoPError";
|
|
194
204
|
}
|
|
195
205
|
};
|
|
196
206
|
var MrtdPopError = class extends Oauth2Error {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
207
|
+
statusCode;
|
|
208
|
+
constructor(message, options) {
|
|
209
|
+
super(message, options);
|
|
200
210
|
this.name = "MrtdPopError";
|
|
211
|
+
this.statusCode = options?.statusCode;
|
|
201
212
|
}
|
|
202
213
|
};
|
|
203
214
|
var FetchTokenResponseError = class extends Oauth2Error {
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
this.name = "
|
|
215
|
+
statusCode;
|
|
216
|
+
constructor(message, options) {
|
|
217
|
+
super(message, options);
|
|
218
|
+
this.name = "FetchTokenResponseError";
|
|
219
|
+
this.statusCode = options?.statusCode;
|
|
208
220
|
}
|
|
209
221
|
};
|
|
210
222
|
var CreateTokenResponseError = class extends Oauth2Error {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
223
|
+
statusCode;
|
|
224
|
+
constructor(message, options) {
|
|
225
|
+
super(message, options);
|
|
214
226
|
this.name = "CreateTokenResponseError";
|
|
227
|
+
this.statusCode = options?.statusCode;
|
|
215
228
|
}
|
|
216
229
|
};
|
|
217
230
|
var ClientAttestationError = class extends Oauth2Error {
|
|
218
|
-
constructor(message,
|
|
219
|
-
super(message);
|
|
231
|
+
constructor(message, options) {
|
|
232
|
+
super(message, options);
|
|
220
233
|
this.name = "ClientAttestationError";
|
|
221
|
-
this.cause = cause;
|
|
222
234
|
}
|
|
223
235
|
};
|
|
224
236
|
|
|
@@ -264,7 +276,7 @@ var zAccessTokenProfileJwtPayload = z4.looseObject({
|
|
|
264
276
|
exp: z4.number(),
|
|
265
277
|
iat: z4.number(),
|
|
266
278
|
iss: z4.string(),
|
|
267
|
-
jti: z4.string(),
|
|
279
|
+
jti: z4.string().max(MAX_JTI_LENGTH),
|
|
268
280
|
nbf: z4.number().optional(),
|
|
269
281
|
scope: z4.string().optional(),
|
|
270
282
|
sub: z4.string()
|
|
@@ -284,6 +296,7 @@ async function createAccessTokenResponse(options) {
|
|
|
284
296
|
typ: "at+jwt"
|
|
285
297
|
});
|
|
286
298
|
const payload = parseWithErrorHandling2(zAccessTokenProfileJwtPayload, {
|
|
299
|
+
...options.additionalPayload,
|
|
287
300
|
aud: options.audience,
|
|
288
301
|
client_id: options.clientId,
|
|
289
302
|
cnf: options.dpop ? {
|
|
@@ -299,19 +312,18 @@ async function createAccessTokenResponse(options) {
|
|
|
299
312
|
jti: encodeToBase64Url(await options.callbacks.generateRandom(32)),
|
|
300
313
|
nbf: options.nbf,
|
|
301
314
|
scope: options.scope,
|
|
302
|
-
sub: options.subject
|
|
303
|
-
...options.additionalPayload
|
|
315
|
+
sub: options.subject
|
|
304
316
|
});
|
|
305
317
|
const { jwt } = await options.callbacks.signJwt(options.signer, {
|
|
306
318
|
header,
|
|
307
319
|
payload
|
|
308
320
|
});
|
|
309
321
|
const accessTokenResponse = parseWithErrorHandling2(zAccessTokenResponse, {
|
|
322
|
+
...options.additionalPayload,
|
|
310
323
|
access_token: jwt,
|
|
311
324
|
expires_in: options.expiresInSeconds,
|
|
312
325
|
refresh_token: options.refreshToken,
|
|
313
|
-
token_type: options.tokenType
|
|
314
|
-
...options.additionalPayload
|
|
326
|
+
token_type: options.tokenType
|
|
315
327
|
});
|
|
316
328
|
return accessTokenResponse;
|
|
317
329
|
} catch (error) {
|
|
@@ -379,55 +391,90 @@ import {
|
|
|
379
391
|
formatZodError
|
|
380
392
|
} from "@pagopa/io-wallet-utils";
|
|
381
393
|
|
|
382
|
-
// src/client-attestation/
|
|
383
|
-
import {
|
|
384
|
-
verifyJwt
|
|
385
|
-
} from "@openid4vc/oauth2";
|
|
394
|
+
// src/client-attestation/wallet-attestation.ts
|
|
395
|
+
import { zCompactJwt as zCompactJwt2 } from "@openid4vc/oauth2";
|
|
386
396
|
import {
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
encodeToBase64Url as encodeToBase64Url2
|
|
397
|
+
ItWalletSpecsVersion,
|
|
398
|
+
ItWalletSpecsVersionError
|
|
390
399
|
} from "@pagopa/io-wallet-utils";
|
|
391
400
|
|
|
401
|
+
// src/client-attestation/types.ts
|
|
402
|
+
import z5 from "zod";
|
|
403
|
+
var zOauthClientAttestationHeader = z5.literal(
|
|
404
|
+
"OAuth-Client-Attestation"
|
|
405
|
+
);
|
|
406
|
+
var oauthClientAttestationHeader = zOauthClientAttestationHeader.value;
|
|
407
|
+
var zOauthClientAttestationPopHeader = z5.literal(
|
|
408
|
+
"OAuth-Client-Attestation-PoP"
|
|
409
|
+
);
|
|
410
|
+
var oauthClientAttestationPopHeader = zOauthClientAttestationPopHeader.value;
|
|
411
|
+
|
|
412
|
+
// src/client-attestation/verify-wallet-attestation-jwt-base.ts
|
|
413
|
+
import { jwtSignerFromJwt, verifyJwt } from "@openid4vc/oauth2";
|
|
414
|
+
|
|
392
415
|
// src/common/jwt/decode-jwt.ts
|
|
393
416
|
import { Oauth2JwtParseError as Oauth2JwtParseError2 } from "@openid4vc/oauth2";
|
|
394
417
|
import {
|
|
395
418
|
decodeBase64 as decodeBase642,
|
|
396
419
|
encodeToUtf8String as encodeToUtf8String2,
|
|
420
|
+
formatError as formatError2,
|
|
397
421
|
parseWithErrorHandling as parseWithErrorHandling4,
|
|
398
422
|
stringToJsonWithErrorHandling as stringToJsonWithErrorHandling2
|
|
399
423
|
} from "@pagopa/io-wallet-utils";
|
|
400
424
|
function decodeJwt(options) {
|
|
401
425
|
const jwtParts = options.jwt.split(".");
|
|
402
426
|
if (jwtParts.length !== 3) {
|
|
403
|
-
throw new Oauth2JwtParseError2(
|
|
427
|
+
throw new Oauth2JwtParseError2(
|
|
428
|
+
formatError2(
|
|
429
|
+
"Unable to decode because Jwt is not a valid!",
|
|
430
|
+
options.errorMessagePrefix
|
|
431
|
+
)
|
|
432
|
+
);
|
|
404
433
|
}
|
|
405
434
|
let payloadJson;
|
|
406
435
|
try {
|
|
407
436
|
const payloadPart = jwtParts[1];
|
|
408
437
|
if (payloadPart === void 0) {
|
|
409
|
-
throw new Oauth2JwtParseError2(
|
|
438
|
+
throw new Oauth2JwtParseError2(
|
|
439
|
+
formatError2(
|
|
440
|
+
"Unable to decode because Jwt is not a valid!",
|
|
441
|
+
options.errorMessagePrefix
|
|
442
|
+
)
|
|
443
|
+
);
|
|
410
444
|
}
|
|
411
445
|
payloadJson = stringToJsonWithErrorHandling2(
|
|
412
446
|
encodeToUtf8String2(decodeBase642(payloadPart)),
|
|
413
|
-
|
|
447
|
+
formatError2(
|
|
448
|
+
"Unable to parse jwt payload to JSON",
|
|
449
|
+
options.errorMessagePrefix
|
|
450
|
+
)
|
|
414
451
|
);
|
|
415
452
|
} catch (error) {
|
|
416
453
|
throw new Oauth2JwtParseError2(
|
|
417
|
-
|
|
454
|
+
formatError2(
|
|
455
|
+
`Error parsing JWT. ${error instanceof Error ? error.message : ""}`,
|
|
456
|
+
options.errorMessagePrefix
|
|
457
|
+
)
|
|
418
458
|
);
|
|
419
459
|
}
|
|
420
460
|
const signaturePart = jwtParts[2];
|
|
421
461
|
if (signaturePart === void 0) {
|
|
422
|
-
throw new Oauth2JwtParseError2(
|
|
462
|
+
throw new Oauth2JwtParseError2(
|
|
463
|
+
formatError2(
|
|
464
|
+
"Unable to decode because Jwt is not a valid!",
|
|
465
|
+
options.errorMessagePrefix
|
|
466
|
+
)
|
|
467
|
+
);
|
|
423
468
|
}
|
|
424
469
|
const { header } = decodeJwtHeader({
|
|
470
|
+
errorMessagePrefix: options.errorMessagePrefix,
|
|
425
471
|
headerSchema: options.headerSchema,
|
|
426
472
|
jwt: options.jwt
|
|
427
473
|
});
|
|
428
474
|
const payload = parseWithErrorHandling4(
|
|
429
475
|
options.payloadSchema ?? zJwtPayload,
|
|
430
|
-
payloadJson
|
|
476
|
+
payloadJson,
|
|
477
|
+
formatError2("Invalid JWT payload", options.errorMessagePrefix)
|
|
431
478
|
);
|
|
432
479
|
return {
|
|
433
480
|
header,
|
|
@@ -436,160 +483,26 @@ function decodeJwt(options) {
|
|
|
436
483
|
};
|
|
437
484
|
}
|
|
438
485
|
|
|
439
|
-
// src/client-attestation/
|
|
440
|
-
async function
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
signer: {
|
|
458
|
-
alg: header.alg,
|
|
459
|
-
method: "jwk",
|
|
460
|
-
publicJwk: options.clientAttestationPublicJwk
|
|
461
|
-
},
|
|
462
|
-
verifyJwtCallback: options.callbacks.verifyJwt
|
|
463
|
-
});
|
|
464
|
-
return {
|
|
465
|
-
header,
|
|
466
|
-
payload,
|
|
467
|
-
signer
|
|
468
|
-
};
|
|
469
|
-
} catch (error) {
|
|
470
|
-
if (error instanceof Oauth2Error) throw error;
|
|
471
|
-
throw new Oauth2Error(
|
|
472
|
-
`Error creating client attestation pop jwt : ${error instanceof Error ? error.message : String(error)}`
|
|
473
|
-
);
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
async function createClientAttestationPopJwt(options) {
|
|
477
|
-
try {
|
|
478
|
-
const clientAttestation = decodeJwt({
|
|
479
|
-
jwt: options.clientAttestation
|
|
480
|
-
});
|
|
481
|
-
const jwk = clientAttestation.payload.cnf?.jwk;
|
|
482
|
-
if (!jwk) {
|
|
483
|
-
throw new Oauth2Error(
|
|
484
|
-
"Client attestation does not contain 'cnf.jwk', cannot create client attestation pop jwt"
|
|
485
|
-
);
|
|
486
|
-
}
|
|
487
|
-
const sub = clientAttestation.payload.sub;
|
|
488
|
-
if (!sub || typeof sub !== "string") {
|
|
489
|
-
throw new Oauth2Error(
|
|
490
|
-
"Client attestation does not contain 'sub', cannot create client attestation pop jwt"
|
|
491
|
-
);
|
|
492
|
-
}
|
|
493
|
-
const signer = options.signer ?? {
|
|
494
|
-
alg: clientAttestation.header.alg,
|
|
495
|
-
method: "jwk",
|
|
496
|
-
publicJwk: jwk
|
|
497
|
-
};
|
|
498
|
-
const header = {
|
|
499
|
-
alg: signer.alg,
|
|
500
|
-
typ: "oauth-client-attestation-pop+jwt"
|
|
501
|
-
};
|
|
502
|
-
const issuedAt = options.issuedAt ?? /* @__PURE__ */ new Date();
|
|
503
|
-
const expiresAt = options.expiresAt ?? addSecondsToDate2(issuedAt, 1 * 60);
|
|
504
|
-
const jti = options.jti ?? (options.callbacks.generateRandom ? encodeToBase64Url2(await options.callbacks.generateRandom(32)) : void 0);
|
|
505
|
-
if (!jti) {
|
|
506
|
-
throw new Oauth2Error(
|
|
507
|
-
"Error: neither a default jti nor a generateRandom callback have been provided"
|
|
508
|
-
);
|
|
509
|
-
}
|
|
510
|
-
const payload = {
|
|
511
|
-
aud: options.authorizationServer,
|
|
512
|
-
exp: dateToSeconds2(expiresAt),
|
|
513
|
-
iat: dateToSeconds2(issuedAt),
|
|
514
|
-
iss: sub,
|
|
515
|
-
jti
|
|
516
|
-
};
|
|
517
|
-
const { jwt } = await options.callbacks.signJwt(signer, {
|
|
518
|
-
header,
|
|
519
|
-
payload
|
|
520
|
-
});
|
|
521
|
-
return jwt;
|
|
522
|
-
} catch (error) {
|
|
523
|
-
if (error instanceof Oauth2Error) throw error;
|
|
524
|
-
throw new Oauth2Error(
|
|
525
|
-
`Error creating client attestation pop jwt : ${error instanceof Error ? error.message : String(error)}`
|
|
526
|
-
);
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
// src/client-attestation/types.ts
|
|
531
|
-
import z5 from "zod";
|
|
532
|
-
var zOauthClientAttestationHeader = z5.literal(
|
|
533
|
-
"OAuth-Client-Attestation"
|
|
534
|
-
);
|
|
535
|
-
var oauthClientAttestationHeader = zOauthClientAttestationHeader.value;
|
|
536
|
-
var zOauthClientAttestationPopHeader = z5.literal(
|
|
537
|
-
"OAuth-Client-Attestation-PoP"
|
|
538
|
-
);
|
|
539
|
-
var oauthClientAttestationPopHeader = zOauthClientAttestationPopHeader.value;
|
|
540
|
-
|
|
541
|
-
// src/client-attestation/client-authentication.ts
|
|
542
|
-
var SupportedClientAuthenticationMethod = {
|
|
543
|
-
ClientSecretBasic: "client_secret_basic",
|
|
544
|
-
ClientSecretPost: "client_secret_post",
|
|
545
|
-
None: "none",
|
|
546
|
-
WalletAttestationJwt: "attest_jwt_client_auth"
|
|
547
|
-
};
|
|
548
|
-
function isClientAttestationSupported(options) {
|
|
549
|
-
if (!options.authorizationServerMetadata.token_endpoint_auth_methods_supported || !options.authorizationServerMetadata.token_endpoint_auth_methods_supported.includes(
|
|
550
|
-
SupportedClientAuthenticationMethod.WalletAttestationJwt
|
|
551
|
-
)) {
|
|
552
|
-
return {
|
|
553
|
-
supported: false
|
|
554
|
-
};
|
|
555
|
-
}
|
|
556
|
-
return {
|
|
557
|
-
supported: true
|
|
558
|
-
};
|
|
559
|
-
}
|
|
560
|
-
function clientAuthenticationAnonymous() {
|
|
561
|
-
return () => {
|
|
562
|
-
};
|
|
563
|
-
}
|
|
564
|
-
function clientAuthenticationWalletAttestationJwt(options) {
|
|
565
|
-
return async ({ authorizationServerMetadata, headers }) => {
|
|
566
|
-
const clientAttestationPop = await createClientAttestationPopJwt({
|
|
567
|
-
authorizationServer: authorizationServerMetadata.issuer,
|
|
568
|
-
callbacks: options.callbacks,
|
|
569
|
-
clientAttestation: options.walletAttestationJwt
|
|
570
|
-
});
|
|
571
|
-
headers.set(oauthClientAttestationHeader, options.walletAttestationJwt);
|
|
572
|
-
headers.set(oauthClientAttestationPopHeader, clientAttestationPop);
|
|
573
|
-
};
|
|
486
|
+
// src/client-attestation/verify-wallet-attestation-jwt-base.ts
|
|
487
|
+
async function verifyWalletAttestationBase(options, headerSchema, payloadSchema) {
|
|
488
|
+
const { header, payload } = decodeJwt({
|
|
489
|
+
errorMessagePrefix: "Error decoding wallet attestation JWT:",
|
|
490
|
+
headerSchema,
|
|
491
|
+
jwt: options.walletAttestationJwt,
|
|
492
|
+
payloadSchema
|
|
493
|
+
});
|
|
494
|
+
const { signer } = await verifyJwt({
|
|
495
|
+
compact: options.walletAttestationJwt,
|
|
496
|
+
errorMessage: "wallet attestation verification failed.",
|
|
497
|
+
header,
|
|
498
|
+
now: options.now,
|
|
499
|
+
payload,
|
|
500
|
+
signer: jwtSignerFromJwt({ header, payload }),
|
|
501
|
+
verifyJwtCallback: options.callbacks.verifyJwt
|
|
502
|
+
});
|
|
503
|
+
return { header, payload, signer };
|
|
574
504
|
}
|
|
575
505
|
|
|
576
|
-
// src/client-attestation/v1.0/index.ts
|
|
577
|
-
var v1_exports = {};
|
|
578
|
-
__export(v1_exports, {
|
|
579
|
-
createWalletAttestationJwt: () => createWalletAttestationJwt,
|
|
580
|
-
verifyWalletAttestationJwt: () => verifyWalletAttestationJwt,
|
|
581
|
-
zWalletAttestationJwtHeaderV1_0: () => zWalletAttestationJwtHeaderV1_0,
|
|
582
|
-
zWalletAttestationJwtPayloadV1_0: () => zWalletAttestationJwtPayloadV1_0,
|
|
583
|
-
zWalletAttestationJwtV1_0: () => zWalletAttestationJwtV1_0
|
|
584
|
-
});
|
|
585
|
-
|
|
586
|
-
// src/client-attestation/v1.0/create-wallet-attestation-jwt.ts
|
|
587
|
-
import {
|
|
588
|
-
ValidationError as ValidationError2,
|
|
589
|
-
addSecondsToDate as addSecondsToDate3,
|
|
590
|
-
dateToSeconds as dateToSeconds3
|
|
591
|
-
} from "@pagopa/io-wallet-utils";
|
|
592
|
-
|
|
593
506
|
// src/client-attestation/v1.0/z-wallet-attestation.ts
|
|
594
507
|
import { z as z6 } from "zod";
|
|
595
508
|
var zWalletAttestationJwtHeaderV1_0 = z6.looseObject({
|
|
@@ -613,67 +526,6 @@ var zWalletAttestationJwtPayloadV1_0 = z6.looseObject({
|
|
|
613
526
|
});
|
|
614
527
|
var zWalletAttestationJwtV1_0 = z6.string().min(1);
|
|
615
528
|
|
|
616
|
-
// src/client-attestation/v1.0/create-wallet-attestation-jwt.ts
|
|
617
|
-
var createWalletAttestationJwt = async (options) => {
|
|
618
|
-
try {
|
|
619
|
-
const { signJwt } = options.callbacks;
|
|
620
|
-
const exp = options.expiresAt ?? addSecondsToDate3(/* @__PURE__ */ new Date(), 3600 * 24 * 60);
|
|
621
|
-
const payload = {
|
|
622
|
-
cnf: { jwk: options.dpopJwkPublic },
|
|
623
|
-
exp: dateToSeconds3(exp),
|
|
624
|
-
iat: dateToSeconds3(/* @__PURE__ */ new Date()),
|
|
625
|
-
iss: options.issuer,
|
|
626
|
-
sub: options.dpopJwkPublic.kid,
|
|
627
|
-
...options.walletLink && { wallet_link: options.walletLink },
|
|
628
|
-
...options.walletName && { wallet_name: options.walletName },
|
|
629
|
-
aal: options.authenticatorAssuranceLevel
|
|
630
|
-
};
|
|
631
|
-
const header = {
|
|
632
|
-
alg: options.signer.alg,
|
|
633
|
-
kid: options.signer.kid,
|
|
634
|
-
trust_chain: options.signer.trustChain,
|
|
635
|
-
typ: "oauth-client-attestation+jwt"
|
|
636
|
-
};
|
|
637
|
-
const result = await signJwt(options.signer, {
|
|
638
|
-
header,
|
|
639
|
-
payload
|
|
640
|
-
});
|
|
641
|
-
decodeJwt({
|
|
642
|
-
headerSchema: zWalletAttestationJwtHeaderV1_0,
|
|
643
|
-
jwt: result.jwt,
|
|
644
|
-
payloadSchema: zWalletAttestationJwtPayloadV1_0
|
|
645
|
-
});
|
|
646
|
-
return result.jwt;
|
|
647
|
-
} catch (error) {
|
|
648
|
-
if (error instanceof ValidationError2) {
|
|
649
|
-
throw error;
|
|
650
|
-
}
|
|
651
|
-
throw new ClientAttestationError(
|
|
652
|
-
`Unexpected error during wallet attestation creation: ${error instanceof Error ? error.message : String(error)}`
|
|
653
|
-
);
|
|
654
|
-
}
|
|
655
|
-
};
|
|
656
|
-
|
|
657
|
-
// src/client-attestation/verify-wallet-attestation-jwt-base.ts
|
|
658
|
-
import { jwtSignerFromJwt, verifyJwt as verifyJwt2 } from "@openid4vc/oauth2";
|
|
659
|
-
async function verifyWalletAttestationBase(options, headerSchema, payloadSchema) {
|
|
660
|
-
const { header, payload } = decodeJwt({
|
|
661
|
-
headerSchema,
|
|
662
|
-
jwt: options.walletAttestationJwt,
|
|
663
|
-
payloadSchema
|
|
664
|
-
});
|
|
665
|
-
const { signer } = await verifyJwt2({
|
|
666
|
-
compact: options.walletAttestationJwt,
|
|
667
|
-
errorMessage: "wallet attestation verification failed.",
|
|
668
|
-
header,
|
|
669
|
-
now: options.now,
|
|
670
|
-
payload,
|
|
671
|
-
signer: jwtSignerFromJwt({ header, payload }),
|
|
672
|
-
verifyJwtCallback: options.callbacks.verifyJwt
|
|
673
|
-
});
|
|
674
|
-
return { header, payload, signer };
|
|
675
|
-
}
|
|
676
|
-
|
|
677
529
|
// src/client-attestation/v1.0/verify-wallet-attestation-jwt.ts
|
|
678
530
|
async function verifyWalletAttestationJwt(options) {
|
|
679
531
|
return verifyWalletAttestationBase(
|
|
@@ -683,23 +535,6 @@ async function verifyWalletAttestationJwt(options) {
|
|
|
683
535
|
);
|
|
684
536
|
}
|
|
685
537
|
|
|
686
|
-
// src/client-attestation/v1.3/index.ts
|
|
687
|
-
var v1_exports2 = {};
|
|
688
|
-
__export(v1_exports2, {
|
|
689
|
-
createWalletAttestationJwt: () => createWalletAttestationJwt2,
|
|
690
|
-
verifyWalletAttestationJwt: () => verifyWalletAttestationJwt2,
|
|
691
|
-
zWalletAttestationJwtHeaderV1_3: () => zWalletAttestationJwtHeaderV1_3,
|
|
692
|
-
zWalletAttestationJwtPayloadV1_3: () => zWalletAttestationJwtPayloadV1_3,
|
|
693
|
-
zWalletAttestationJwtV1_3: () => zWalletAttestationJwtV1_3
|
|
694
|
-
});
|
|
695
|
-
|
|
696
|
-
// src/client-attestation/v1.3/create-wallet-attestation-jwt.ts
|
|
697
|
-
import {
|
|
698
|
-
ValidationError as ValidationError3,
|
|
699
|
-
addSecondsToDate as addSecondsToDate4,
|
|
700
|
-
dateToSeconds as dateToSeconds4
|
|
701
|
-
} from "@pagopa/io-wallet-utils";
|
|
702
|
-
|
|
703
538
|
// src/client-attestation/v1.3/z-wallet-attestation.ts
|
|
704
539
|
import { z as z7 } from "zod";
|
|
705
540
|
var zWalletAttestationJwtHeaderV1_3 = z7.looseObject({
|
|
@@ -733,55 +568,6 @@ var zWalletAttestationJwtPayloadV1_3 = z7.looseObject({
|
|
|
733
568
|
});
|
|
734
569
|
var zWalletAttestationJwtV1_3 = z7.string().min(1);
|
|
735
570
|
|
|
736
|
-
// src/client-attestation/v1.3/create-wallet-attestation-jwt.ts
|
|
737
|
-
var createWalletAttestationJwt2 = async (options) => {
|
|
738
|
-
try {
|
|
739
|
-
const { signJwt } = options.callbacks;
|
|
740
|
-
const exp = options.expiresAt ?? addSecondsToDate4(/* @__PURE__ */ new Date(), 3600 * 24 * 60);
|
|
741
|
-
if (options.nbf && options.nbf >= exp) {
|
|
742
|
-
throw new ValidationError3("nbf must be before exp");
|
|
743
|
-
}
|
|
744
|
-
const payload = {
|
|
745
|
-
cnf: { jwk: options.dpopJwkPublic },
|
|
746
|
-
exp: dateToSeconds4(exp),
|
|
747
|
-
iat: dateToSeconds4(/* @__PURE__ */ new Date()),
|
|
748
|
-
iss: options.issuer,
|
|
749
|
-
sub: options.dpopJwkPublic.kid,
|
|
750
|
-
...options.nbf && { nbf: dateToSeconds4(options.nbf) },
|
|
751
|
-
...options.status && { status: options.status },
|
|
752
|
-
...options.walletLink && { wallet_link: options.walletLink },
|
|
753
|
-
...options.walletName && { wallet_name: options.walletName }
|
|
754
|
-
};
|
|
755
|
-
const header = {
|
|
756
|
-
alg: options.signer.alg,
|
|
757
|
-
kid: options.signer.kid,
|
|
758
|
-
typ: "oauth-client-attestation+jwt",
|
|
759
|
-
x5c: options.signer.x5c,
|
|
760
|
-
// REQUIRED
|
|
761
|
-
...options.signer.trustChain && {
|
|
762
|
-
trust_chain: options.signer.trustChain
|
|
763
|
-
}
|
|
764
|
-
};
|
|
765
|
-
const result = await signJwt(options.signer, {
|
|
766
|
-
header,
|
|
767
|
-
payload
|
|
768
|
-
});
|
|
769
|
-
decodeJwt({
|
|
770
|
-
headerSchema: zWalletAttestationJwtHeaderV1_3,
|
|
771
|
-
jwt: result.jwt,
|
|
772
|
-
payloadSchema: zWalletAttestationJwtPayloadV1_3
|
|
773
|
-
});
|
|
774
|
-
return result.jwt;
|
|
775
|
-
} catch (error) {
|
|
776
|
-
if (error instanceof ValidationError3) {
|
|
777
|
-
throw error;
|
|
778
|
-
}
|
|
779
|
-
throw new ClientAttestationError(
|
|
780
|
-
`Unexpected error during wallet attestation creation: ${error instanceof Error ? error.message : String(error)}`
|
|
781
|
-
);
|
|
782
|
-
}
|
|
783
|
-
};
|
|
784
|
-
|
|
785
571
|
// src/client-attestation/v1.3/verify-wallet-attestation-jwt.ts
|
|
786
572
|
async function verifyWalletAttestationJwt2(options) {
|
|
787
573
|
return verifyWalletAttestationBase(
|
|
@@ -791,25 +577,65 @@ async function verifyWalletAttestationJwt2(options) {
|
|
|
791
577
|
);
|
|
792
578
|
}
|
|
793
579
|
|
|
794
|
-
// src/client-attestation/
|
|
795
|
-
import {
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
580
|
+
// src/client-attestation/v1.4/z-wallet-attestation.ts
|
|
581
|
+
import { z as z8 } from "zod";
|
|
582
|
+
var zWalletAttestationStatusV1_4 = z8.object({
|
|
583
|
+
status_list: z8.object({
|
|
584
|
+
idx: z8.number().int(),
|
|
585
|
+
uri: z8.string()
|
|
586
|
+
})
|
|
587
|
+
});
|
|
588
|
+
var zEudiWalletInfoV1_4 = z8.object({
|
|
589
|
+
general_info: z8.object({
|
|
590
|
+
wallet_provider_name: z8.string(),
|
|
591
|
+
wallet_solution_certification_information: z8.url(),
|
|
592
|
+
wallet_solution_id: z8.string(),
|
|
593
|
+
wallet_solution_version: z8.string()
|
|
594
|
+
})
|
|
595
|
+
});
|
|
596
|
+
var zWalletAttestationJwtHeaderV1_4 = z8.looseObject({
|
|
597
|
+
...zJwtHeader.shape,
|
|
598
|
+
trust_chain: zTrustChain.optional(),
|
|
599
|
+
typ: z8.literal("oauth-client-attestation+jwt"),
|
|
600
|
+
x5c: zCertificateChain
|
|
601
|
+
});
|
|
602
|
+
var zWalletAttestationJwtPayloadV1_4 = z8.looseObject({
|
|
603
|
+
...zJwtPayload.shape,
|
|
604
|
+
cnf: z8.object({
|
|
605
|
+
jwk: zJwk
|
|
606
|
+
}),
|
|
607
|
+
eudi_wallet_info: zEudiWalletInfoV1_4.optional(),
|
|
608
|
+
exp: z8.number().int(),
|
|
609
|
+
iat: z8.number().int(),
|
|
610
|
+
iss: z8.string(),
|
|
611
|
+
nbf: z8.number().optional(),
|
|
612
|
+
status: zWalletAttestationStatusV1_4,
|
|
613
|
+
sub: z8.string(),
|
|
614
|
+
wallet_link: z8.url(),
|
|
615
|
+
wallet_name: z8.string()
|
|
616
|
+
});
|
|
617
|
+
var zWalletAttestationJwtV1_4 = z8.string().min(1);
|
|
618
|
+
|
|
619
|
+
// src/client-attestation/v1.4/verify-wallet-attestation-jwt.ts
|
|
620
|
+
async function verifyWalletAttestationJwt3(options) {
|
|
621
|
+
return verifyWalletAttestationBase(
|
|
622
|
+
options,
|
|
623
|
+
zWalletAttestationJwtHeaderV1_4,
|
|
624
|
+
zWalletAttestationJwtPayloadV1_4
|
|
625
|
+
);
|
|
626
|
+
}
|
|
799
627
|
|
|
800
628
|
// src/client-attestation/wallet-attestation.ts
|
|
801
|
-
import { zCompactJwt as zCompactJwt2 } from "@openid4vc/oauth2";
|
|
802
|
-
import {
|
|
803
|
-
ItWalletSpecsVersion,
|
|
804
|
-
ItWalletSpecsVersionError
|
|
805
|
-
} from "@pagopa/io-wallet-utils";
|
|
806
629
|
function isV1_0Options(options) {
|
|
807
630
|
return options.config.itWalletSpecsVersion === ItWalletSpecsVersion.V1_0;
|
|
808
631
|
}
|
|
809
632
|
function isV1_3Options(options) {
|
|
810
633
|
return options.config.itWalletSpecsVersion === ItWalletSpecsVersion.V1_3;
|
|
811
634
|
}
|
|
812
|
-
|
|
635
|
+
function isV1_4Options(options) {
|
|
636
|
+
return options.config.itWalletSpecsVersion === ItWalletSpecsVersion.V1_4;
|
|
637
|
+
}
|
|
638
|
+
async function verifyWalletAttestationJwt4(options) {
|
|
813
639
|
const version = options.config.itWalletSpecsVersion;
|
|
814
640
|
if (isV1_0Options(options)) {
|
|
815
641
|
return verifyWalletAttestationJwt(options);
|
|
@@ -817,10 +643,14 @@ async function verifyWalletAttestationJwt3(options) {
|
|
|
817
643
|
if (isV1_3Options(options)) {
|
|
818
644
|
return verifyWalletAttestationJwt2(options);
|
|
819
645
|
}
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
646
|
+
if (isV1_4Options(options)) {
|
|
647
|
+
return verifyWalletAttestationJwt3(options);
|
|
648
|
+
}
|
|
649
|
+
throw new ItWalletSpecsVersionError(
|
|
650
|
+
"verifyWalletAttestationJwt",
|
|
651
|
+
version,
|
|
652
|
+
Object.values(ItWalletSpecsVersion)
|
|
653
|
+
);
|
|
824
654
|
}
|
|
825
655
|
function extractClientAttestationJwtsFromHeaders(headers) {
|
|
826
656
|
const walletAttestationHeader = headers.get(oauthClientAttestationHeader);
|
|
@@ -843,60 +673,16 @@ function extractClientAttestationJwtsFromHeaders(headers) {
|
|
|
843
673
|
};
|
|
844
674
|
}
|
|
845
675
|
|
|
846
|
-
// src/client-attestation/verify-client-attestation.ts
|
|
847
|
-
async function verifyClientAttestation(options) {
|
|
848
|
-
if (!options.clientAttestation.walletAttestationJwt || !options.clientAttestation.clientAttestationPopJwt) {
|
|
849
|
-
throw new Oauth2Error(
|
|
850
|
-
`Missing required client attestation parameters in the request. Make sure to provide the '${oauthClientAttestationHeader}' and '${oauthClientAttestationPopHeader}' header values.`
|
|
851
|
-
);
|
|
852
|
-
}
|
|
853
|
-
const clientAttestation = await verifyWalletAttestationJwt3({
|
|
854
|
-
callbacks: options.callbacks,
|
|
855
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
856
|
-
config: options.config,
|
|
857
|
-
now: options.now,
|
|
858
|
-
walletAttestationJwt: options.clientAttestation.walletAttestationJwt
|
|
859
|
-
});
|
|
860
|
-
const clientAttestationPop = await verifyClientAttestationPopJwt({
|
|
861
|
-
authorizationServer: options.authorizationServerMetadata.issuer,
|
|
862
|
-
callbacks: options.callbacks,
|
|
863
|
-
clientAttestationPopJwt: options.clientAttestation.clientAttestationPopJwt,
|
|
864
|
-
clientAttestationPublicJwk: clientAttestation.payload.cnf.jwk,
|
|
865
|
-
now: options.now
|
|
866
|
-
});
|
|
867
|
-
if (options.requestClientId && options.requestClientId !== clientAttestation.payload.sub) {
|
|
868
|
-
throw new Oauth2Error(
|
|
869
|
-
`The client_id '${options.requestClientId}' in the request does not match the client id '${clientAttestation.payload.sub}' in the client attestation`
|
|
870
|
-
);
|
|
871
|
-
}
|
|
872
|
-
if (options.clientAttestation.ensureConfirmationKeyMatchesDpopKey && options.dpopJwkThumbprint) {
|
|
873
|
-
const clientAttestationJkt = await calculateJwkThumbprint2({
|
|
874
|
-
hashAlgorithm: HashAlgorithm2.Sha256,
|
|
875
|
-
hashCallback: options.callbacks.hash,
|
|
876
|
-
jwk: clientAttestation.payload.cnf.jwk
|
|
877
|
-
});
|
|
878
|
-
if (clientAttestationJkt !== options.dpopJwkThumbprint) {
|
|
879
|
-
throw new Oauth2Error(
|
|
880
|
-
"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."
|
|
881
|
-
);
|
|
882
|
-
}
|
|
883
|
-
}
|
|
884
|
-
return {
|
|
885
|
-
clientAttestation,
|
|
886
|
-
clientAttestationPop
|
|
887
|
-
};
|
|
888
|
-
}
|
|
889
|
-
|
|
890
676
|
// src/token-dpop/create-token-dpop.ts
|
|
891
677
|
import {
|
|
892
|
-
HashAlgorithm as
|
|
678
|
+
HashAlgorithm as HashAlgorithm2,
|
|
893
679
|
zCompactJwt as zCompactJwt3
|
|
894
680
|
} from "@openid4vc/oauth2";
|
|
895
681
|
import {
|
|
896
|
-
ValidationError as
|
|
897
|
-
dateToSeconds as
|
|
682
|
+
ValidationError as ValidationError2,
|
|
683
|
+
dateToSeconds as dateToSeconds2,
|
|
898
684
|
decodeUtf8String,
|
|
899
|
-
encodeToBase64Url as
|
|
685
|
+
encodeToBase64Url as encodeToBase64Url2,
|
|
900
686
|
parseWithErrorHandling as parseWithErrorHandling5
|
|
901
687
|
} from "@pagopa/io-wallet-utils";
|
|
902
688
|
import { Base64 } from "js-base64";
|
|
@@ -911,28 +697,28 @@ var htuFromRequestUrl = (requestUrl) => {
|
|
|
911
697
|
|
|
912
698
|
// src/token-dpop/z-dpop.ts
|
|
913
699
|
import { zHttpMethod } from "@pagopa/io-wallet-utils";
|
|
914
|
-
import
|
|
915
|
-
var zDpopJwtPayload =
|
|
700
|
+
import z9 from "zod";
|
|
701
|
+
var zDpopJwtPayload = z9.looseObject({
|
|
916
702
|
...zJwtPayload.shape,
|
|
917
|
-
ath:
|
|
703
|
+
ath: z9.optional(z9.string()),
|
|
918
704
|
htm: zHttpMethod,
|
|
919
|
-
htu:
|
|
920
|
-
iat:
|
|
921
|
-
jti:
|
|
705
|
+
htu: z9.url(),
|
|
706
|
+
iat: z9.number().int().nonnegative(),
|
|
707
|
+
jti: z9.string().max(MAX_JTI_LENGTH)
|
|
922
708
|
});
|
|
923
|
-
var zDpopJwtHeader =
|
|
709
|
+
var zDpopJwtHeader = z9.looseObject({
|
|
924
710
|
...zJwtHeader.shape,
|
|
925
711
|
jwk: zJwk,
|
|
926
|
-
typ:
|
|
712
|
+
typ: z9.literal("dpop+jwt")
|
|
927
713
|
});
|
|
928
714
|
|
|
929
715
|
// src/token-dpop/create-token-dpop.ts
|
|
930
716
|
async function createTokenDPoP(options) {
|
|
931
717
|
try {
|
|
932
|
-
const ath = options.accessToken ?
|
|
718
|
+
const ath = options.accessToken ? encodeToBase64Url2(
|
|
933
719
|
await options.callbacks.hash(
|
|
934
720
|
decodeUtf8String(options.accessToken),
|
|
935
|
-
|
|
721
|
+
HashAlgorithm2.Sha256
|
|
936
722
|
)
|
|
937
723
|
) : void 0;
|
|
938
724
|
const jti = options.jti ?? (options.callbacks.generateRandom ? Base64.fromUint8Array(
|
|
@@ -953,7 +739,7 @@ async function createTokenDPoP(options) {
|
|
|
953
739
|
ath,
|
|
954
740
|
htm: options.tokenRequest.method,
|
|
955
741
|
htu: htuFromRequestUrl(options.tokenRequest.url),
|
|
956
|
-
iat:
|
|
742
|
+
iat: dateToSeconds2(options.issuedAt),
|
|
957
743
|
jti
|
|
958
744
|
});
|
|
959
745
|
return options.callbacks.signJwt(options.signer, {
|
|
@@ -961,7 +747,7 @@ async function createTokenDPoP(options) {
|
|
|
961
747
|
payload
|
|
962
748
|
});
|
|
963
749
|
} catch (error) {
|
|
964
|
-
if (error instanceof CreateTokenDPoPError || error instanceof
|
|
750
|
+
if (error instanceof CreateTokenDPoPError || error instanceof ValidationError2) {
|
|
965
751
|
throw error;
|
|
966
752
|
}
|
|
967
753
|
throw new CreateTokenDPoPError(
|
|
@@ -980,114 +766,11 @@ function extractDpopJwtFromHeaders(headers) {
|
|
|
980
766
|
return { dpopJwt, valid: true };
|
|
981
767
|
}
|
|
982
768
|
|
|
983
|
-
// src/token-dpop/verify-token-dpop.ts
|
|
984
|
-
import {
|
|
985
|
-
HashAlgorithm as HashAlgorithm4,
|
|
986
|
-
calculateJwkThumbprint as calculateJwkThumbprint3,
|
|
987
|
-
verifyJwt as verifyJwt3
|
|
988
|
-
} from "@openid4vc/oauth2";
|
|
989
|
-
import {
|
|
990
|
-
decodeUtf8String as decodeUtf8String2,
|
|
991
|
-
encodeToBase64Url as encodeToBase64Url4,
|
|
992
|
-
verifyJwtIatOrThrow
|
|
993
|
-
} from "@pagopa/io-wallet-utils";
|
|
994
|
-
async function verifyTokenDPoP(options) {
|
|
995
|
-
const { header, payload } = decodeJwt({
|
|
996
|
-
headerSchema: zDpopJwtHeader,
|
|
997
|
-
jwt: options.dpopJwt,
|
|
998
|
-
payloadSchema: zDpopJwtPayload
|
|
999
|
-
});
|
|
1000
|
-
if (options.allowedSigningAlgs && !options.allowedSigningAlgs.includes(header.alg)) {
|
|
1001
|
-
throw new Oauth2Error(
|
|
1002
|
-
`dpop jwt uses alg value '${header.alg}' but allowed dpop signing alg values are ${options.allowedSigningAlgs.join(", ")}.`
|
|
1003
|
-
);
|
|
1004
|
-
}
|
|
1005
|
-
if (options.expectedNonce) {
|
|
1006
|
-
if (!payload.nonce) {
|
|
1007
|
-
throw new Oauth2Error(
|
|
1008
|
-
`Dpop jwt does not have a nonce value, but expected nonce value '${options.expectedNonce}'`
|
|
1009
|
-
);
|
|
1010
|
-
}
|
|
1011
|
-
if (payload.nonce !== options.expectedNonce) {
|
|
1012
|
-
throw new Oauth2Error(
|
|
1013
|
-
`Dpop jwt contains nonce value '${payload.nonce}', but expected nonce value '${options.expectedNonce}'`
|
|
1014
|
-
);
|
|
1015
|
-
}
|
|
1016
|
-
}
|
|
1017
|
-
if (options.request.method !== payload.htm) {
|
|
1018
|
-
throw new Oauth2Error(
|
|
1019
|
-
`Dpop jwt contains htm value '${payload.htm}', but expected htm value '${options.request.method}'`
|
|
1020
|
-
);
|
|
1021
|
-
}
|
|
1022
|
-
const expectedHtu = htuFromRequestUrl(options.request.url);
|
|
1023
|
-
if (expectedHtu !== payload.htu) {
|
|
1024
|
-
throw new Oauth2Error(
|
|
1025
|
-
`Dpop jwt contains htu value '${payload.htu}', but expected htu value '${expectedHtu}'.`
|
|
1026
|
-
);
|
|
1027
|
-
}
|
|
1028
|
-
if (options.accessToken) {
|
|
1029
|
-
const expectedAth = encodeToBase64Url4(
|
|
1030
|
-
await options.callbacks.hash(
|
|
1031
|
-
decodeUtf8String2(options.accessToken),
|
|
1032
|
-
HashAlgorithm4.Sha256
|
|
1033
|
-
)
|
|
1034
|
-
);
|
|
1035
|
-
if (!payload.ath) {
|
|
1036
|
-
throw new Oauth2Error(
|
|
1037
|
-
`Dpop jwt does not have a ath value, but expected ath value '${expectedAth}'.`
|
|
1038
|
-
);
|
|
1039
|
-
}
|
|
1040
|
-
if (payload.ath !== expectedAth) {
|
|
1041
|
-
throw new Oauth2Error(
|
|
1042
|
-
`Dpop jwt contains ath value '${payload.ath}', but expected ath value '${expectedAth}'.`
|
|
1043
|
-
);
|
|
1044
|
-
}
|
|
1045
|
-
}
|
|
1046
|
-
const jwkThumbprint = await calculateJwkThumbprint3({
|
|
1047
|
-
hashAlgorithm: HashAlgorithm4.Sha256,
|
|
1048
|
-
hashCallback: options.callbacks.hash,
|
|
1049
|
-
jwk: header.jwk
|
|
1050
|
-
});
|
|
1051
|
-
if (options.expectedJwkThumbprint && options.expectedJwkThumbprint !== jwkThumbprint) {
|
|
1052
|
-
throw new Oauth2Error(
|
|
1053
|
-
`Dpop is signed with jwk with thumbprint value '${jwkThumbprint}', but expect jwk thumbprint value '${options.expectedJwkThumbprint}'`
|
|
1054
|
-
);
|
|
1055
|
-
}
|
|
1056
|
-
try {
|
|
1057
|
-
verifyJwtIatOrThrow({
|
|
1058
|
-
iat: payload.iat,
|
|
1059
|
-
now: options.now
|
|
1060
|
-
});
|
|
1061
|
-
} catch (error) {
|
|
1062
|
-
if (error instanceof Error) {
|
|
1063
|
-
throw new Oauth2Error(`Invalid iat claim in dpop JWT: ${error.message}`);
|
|
1064
|
-
}
|
|
1065
|
-
}
|
|
1066
|
-
await verifyJwt3({
|
|
1067
|
-
compact: options.dpopJwt,
|
|
1068
|
-
errorMessage: "dpop jwt verification failed",
|
|
1069
|
-
header,
|
|
1070
|
-
now: options.now,
|
|
1071
|
-
payload,
|
|
1072
|
-
signer: {
|
|
1073
|
-
alg: header.alg,
|
|
1074
|
-
method: "jwk",
|
|
1075
|
-
publicJwk: header.jwk
|
|
1076
|
-
},
|
|
1077
|
-
verifyJwtCallback: options.callbacks.verifyJwt
|
|
1078
|
-
});
|
|
1079
|
-
return {
|
|
1080
|
-
header,
|
|
1081
|
-
jwkThumbprint,
|
|
1082
|
-
payload
|
|
1083
|
-
};
|
|
1084
|
-
}
|
|
1085
|
-
|
|
1086
769
|
// src/access-token/z-grant-type.ts
|
|
1087
|
-
import { z as
|
|
1088
|
-
var zAuthorizationCodeGrantIdentifier =
|
|
770
|
+
import { z as z10 } from "zod";
|
|
771
|
+
var zAuthorizationCodeGrantIdentifier = z10.literal("authorization_code");
|
|
1089
772
|
var authorizationCodeGrantIdentifier = zAuthorizationCodeGrantIdentifier.value;
|
|
1090
|
-
var zRefreshTokenGrantIdentifier =
|
|
773
|
+
var zRefreshTokenGrantIdentifier = z10.literal("refresh_token");
|
|
1091
774
|
var refreshTokenGrantIdentifier = zRefreshTokenGrantIdentifier.value;
|
|
1092
775
|
|
|
1093
776
|
// src/access-token/parse-token-request.ts
|
|
@@ -1164,11 +847,162 @@ function parseSecurityHeaders(headers) {
|
|
|
1164
847
|
};
|
|
1165
848
|
}
|
|
1166
849
|
|
|
850
|
+
// src/client-attestation/verify-client-attestation.ts
|
|
851
|
+
import {
|
|
852
|
+
HashAlgorithm as HashAlgorithm3,
|
|
853
|
+
calculateJwkThumbprint as calculateJwkThumbprint2
|
|
854
|
+
} from "@openid4vc/oauth2";
|
|
855
|
+
|
|
856
|
+
// src/client-attestation/client-attestation-pop.ts
|
|
857
|
+
import {
|
|
858
|
+
verifyJwt as verifyJwt2
|
|
859
|
+
} from "@openid4vc/oauth2";
|
|
860
|
+
import {
|
|
861
|
+
addSecondsToDate as addSecondsToDate2,
|
|
862
|
+
dateToSeconds as dateToSeconds3,
|
|
863
|
+
encodeToBase64Url as encodeToBase64Url3
|
|
864
|
+
} from "@pagopa/io-wallet-utils";
|
|
865
|
+
async function verifyClientAttestationPopJwt(options) {
|
|
866
|
+
try {
|
|
867
|
+
const { header, payload } = decodeJwt({
|
|
868
|
+
errorMessagePrefix: "Error decoding client attestation PoP JWT:",
|
|
869
|
+
jwt: options.clientAttestationPopJwt
|
|
870
|
+
});
|
|
871
|
+
if (payload.aud !== options.authorizationServer) {
|
|
872
|
+
throw new Oauth2Error(
|
|
873
|
+
`Client Attestation Pop jwt contains 'aud' value '${payload.aud}', but expected authorization server identifier '${options.authorizationServer}'`
|
|
874
|
+
);
|
|
875
|
+
}
|
|
876
|
+
const { signer } = await verifyJwt2({
|
|
877
|
+
compact: options.clientAttestationPopJwt,
|
|
878
|
+
errorMessage: "client attestation pop jwt verification failed",
|
|
879
|
+
expectedNonce: options.expectedNonce,
|
|
880
|
+
header,
|
|
881
|
+
now: options.now,
|
|
882
|
+
payload,
|
|
883
|
+
signer: {
|
|
884
|
+
alg: header.alg,
|
|
885
|
+
method: "jwk",
|
|
886
|
+
publicJwk: options.clientAttestationPublicJwk
|
|
887
|
+
},
|
|
888
|
+
verifyJwtCallback: options.callbacks.verifyJwt
|
|
889
|
+
});
|
|
890
|
+
return {
|
|
891
|
+
header,
|
|
892
|
+
payload,
|
|
893
|
+
signer
|
|
894
|
+
};
|
|
895
|
+
} catch (error) {
|
|
896
|
+
if (error instanceof Oauth2Error) throw error;
|
|
897
|
+
throw new Oauth2Error(
|
|
898
|
+
`Error creating client attestation pop jwt : ${error instanceof Error ? error.message : String(error)}`
|
|
899
|
+
);
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
async function createClientAttestationPopJwt(options) {
|
|
903
|
+
try {
|
|
904
|
+
const clientAttestation = decodeJwt({
|
|
905
|
+
errorMessagePrefix: "Error decoding client attestation JWT:",
|
|
906
|
+
jwt: options.clientAttestation
|
|
907
|
+
});
|
|
908
|
+
const jwk = clientAttestation.payload.cnf?.jwk;
|
|
909
|
+
if (!jwk) {
|
|
910
|
+
throw new Oauth2Error(
|
|
911
|
+
"Client attestation does not contain 'cnf.jwk', cannot create client attestation pop jwt"
|
|
912
|
+
);
|
|
913
|
+
}
|
|
914
|
+
const sub = clientAttestation.payload.sub;
|
|
915
|
+
if (!sub || typeof sub !== "string") {
|
|
916
|
+
throw new Oauth2Error(
|
|
917
|
+
"Client attestation does not contain 'sub', cannot create client attestation pop jwt"
|
|
918
|
+
);
|
|
919
|
+
}
|
|
920
|
+
const signer = options.signer ?? {
|
|
921
|
+
alg: clientAttestation.header.alg,
|
|
922
|
+
method: "jwk",
|
|
923
|
+
publicJwk: jwk
|
|
924
|
+
};
|
|
925
|
+
const header = {
|
|
926
|
+
alg: signer.alg,
|
|
927
|
+
typ: "oauth-client-attestation-pop+jwt"
|
|
928
|
+
};
|
|
929
|
+
const issuedAt = options.issuedAt ?? /* @__PURE__ */ new Date();
|
|
930
|
+
const expiresAt = options.expiresAt ?? addSecondsToDate2(issuedAt, 1 * 60);
|
|
931
|
+
const jti = options.jti ?? (options.callbacks.generateRandom ? encodeToBase64Url3(await options.callbacks.generateRandom(32)) : void 0);
|
|
932
|
+
if (!jti) {
|
|
933
|
+
throw new Oauth2Error(
|
|
934
|
+
"Error: neither a default jti nor a generateRandom callback have been provided"
|
|
935
|
+
);
|
|
936
|
+
}
|
|
937
|
+
const payload = {
|
|
938
|
+
aud: options.authorizationServer,
|
|
939
|
+
exp: dateToSeconds3(expiresAt),
|
|
940
|
+
iat: dateToSeconds3(issuedAt),
|
|
941
|
+
iss: sub,
|
|
942
|
+
jti
|
|
943
|
+
};
|
|
944
|
+
const { jwt } = await options.callbacks.signJwt(signer, {
|
|
945
|
+
header,
|
|
946
|
+
payload
|
|
947
|
+
});
|
|
948
|
+
return jwt;
|
|
949
|
+
} catch (error) {
|
|
950
|
+
if (error instanceof Oauth2Error) throw error;
|
|
951
|
+
throw new Oauth2Error(
|
|
952
|
+
`Error creating client attestation pop jwt : ${error instanceof Error ? error.message : String(error)}`
|
|
953
|
+
);
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
// src/client-attestation/verify-client-attestation.ts
|
|
958
|
+
async function verifyClientAttestation(options) {
|
|
959
|
+
if (!options.clientAttestation.walletAttestationJwt || !options.clientAttestation.clientAttestationPopJwt) {
|
|
960
|
+
throw new Oauth2Error(
|
|
961
|
+
`Missing required client attestation parameters in the request. Make sure to provide the '${oauthClientAttestationHeader}' and '${oauthClientAttestationPopHeader}' header values.`
|
|
962
|
+
);
|
|
963
|
+
}
|
|
964
|
+
const clientAttestation = await verifyWalletAttestationJwt4({
|
|
965
|
+
callbacks: options.callbacks,
|
|
966
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
967
|
+
config: options.config,
|
|
968
|
+
now: options.now,
|
|
969
|
+
walletAttestationJwt: options.clientAttestation.walletAttestationJwt
|
|
970
|
+
});
|
|
971
|
+
const clientAttestationPop = await verifyClientAttestationPopJwt({
|
|
972
|
+
authorizationServer: options.authorizationServerMetadata.issuer,
|
|
973
|
+
callbacks: options.callbacks,
|
|
974
|
+
clientAttestationPopJwt: options.clientAttestation.clientAttestationPopJwt,
|
|
975
|
+
clientAttestationPublicJwk: clientAttestation.payload.cnf.jwk,
|
|
976
|
+
now: options.now
|
|
977
|
+
});
|
|
978
|
+
if (options.requestClientId && options.requestClientId !== clientAttestation.payload.sub) {
|
|
979
|
+
throw new Oauth2Error(
|
|
980
|
+
`The client_id '${options.requestClientId}' in the request does not match the client id '${clientAttestation.payload.sub}' in the client attestation`
|
|
981
|
+
);
|
|
982
|
+
}
|
|
983
|
+
if (options.clientAttestation.ensureConfirmationKeyMatchesDpopKey && options.dpopJwkThumbprint) {
|
|
984
|
+
const clientAttestationJkt = await calculateJwkThumbprint2({
|
|
985
|
+
hashAlgorithm: HashAlgorithm3.Sha256,
|
|
986
|
+
hashCallback: options.callbacks.hash,
|
|
987
|
+
jwk: clientAttestation.payload.cnf.jwk
|
|
988
|
+
});
|
|
989
|
+
if (clientAttestationJkt !== options.dpopJwkThumbprint) {
|
|
990
|
+
throw new Oauth2Error(
|
|
991
|
+
"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."
|
|
992
|
+
);
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
return {
|
|
996
|
+
clientAttestation,
|
|
997
|
+
clientAttestationPop
|
|
998
|
+
};
|
|
999
|
+
}
|
|
1000
|
+
|
|
1167
1001
|
// src/pkce.ts
|
|
1168
1002
|
import {
|
|
1169
|
-
HashAlgorithm as
|
|
1003
|
+
HashAlgorithm as HashAlgorithm4
|
|
1170
1004
|
} from "@openid4vc/oauth2";
|
|
1171
|
-
import { decodeUtf8String as
|
|
1005
|
+
import { decodeUtf8String as decodeUtf8String2, encodeToBase64Url as encodeToBase64Url4 } from "@pagopa/io-wallet-utils";
|
|
1172
1006
|
var PkceCodeChallengeMethod = {
|
|
1173
1007
|
Plain: "plain",
|
|
1174
1008
|
S256: "S256"
|
|
@@ -1186,7 +1020,7 @@ async function createPkce(options) {
|
|
|
1186
1020
|
const codeChallengeMethod = allowedCodeChallengeMethods.includes(
|
|
1187
1021
|
PkceCodeChallengeMethod.S256
|
|
1188
1022
|
) ? PkceCodeChallengeMethod.S256 : PkceCodeChallengeMethod.Plain;
|
|
1189
|
-
const codeVerifier = options.codeVerifier ??
|
|
1023
|
+
const codeVerifier = options.codeVerifier ?? encodeToBase64Url4(await options.callbacks.generateRandom(64));
|
|
1190
1024
|
return {
|
|
1191
1025
|
codeChallenge: await calculateCodeChallenge({
|
|
1192
1026
|
codeChallengeMethod,
|
|
@@ -1205,7 +1039,7 @@ async function verifyPkce(options) {
|
|
|
1205
1039
|
});
|
|
1206
1040
|
if (options.codeChallenge !== calculatedCodeChallenge) {
|
|
1207
1041
|
throw new Oauth2Error(
|
|
1208
|
-
`
|
|
1042
|
+
`PKCE verification failed: code_verifier does not match the stored code_challenge`
|
|
1209
1043
|
);
|
|
1210
1044
|
}
|
|
1211
1045
|
}
|
|
@@ -1214,20 +1048,130 @@ async function calculateCodeChallenge(options) {
|
|
|
1214
1048
|
return options.codeVerifier;
|
|
1215
1049
|
}
|
|
1216
1050
|
if (options.codeChallengeMethod === PkceCodeChallengeMethod.S256) {
|
|
1217
|
-
return
|
|
1051
|
+
return encodeToBase64Url4(
|
|
1218
1052
|
await options.hashCallback(
|
|
1219
|
-
|
|
1053
|
+
decodeUtf8String2(options.codeVerifier),
|
|
1054
|
+
HashAlgorithm4.Sha256
|
|
1055
|
+
)
|
|
1056
|
+
);
|
|
1057
|
+
}
|
|
1058
|
+
throw new Oauth2Error(
|
|
1059
|
+
`Unsupported code challenge method ${options.codeChallengeMethod}`
|
|
1060
|
+
);
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
// src/token-dpop/verify-token-dpop.ts
|
|
1064
|
+
import {
|
|
1065
|
+
HashAlgorithm as HashAlgorithm5,
|
|
1066
|
+
calculateJwkThumbprint as calculateJwkThumbprint3,
|
|
1067
|
+
verifyJwt as verifyJwt3
|
|
1068
|
+
} from "@openid4vc/oauth2";
|
|
1069
|
+
import {
|
|
1070
|
+
decodeUtf8String as decodeUtf8String3,
|
|
1071
|
+
encodeToBase64Url as encodeToBase64Url5,
|
|
1072
|
+
verifyJwtIatOrThrow
|
|
1073
|
+
} from "@pagopa/io-wallet-utils";
|
|
1074
|
+
async function verifyTokenDPoP(options) {
|
|
1075
|
+
const { header, payload } = decodeJwt({
|
|
1076
|
+
errorMessagePrefix: "Error decoding access token DPoP JWT:",
|
|
1077
|
+
headerSchema: zDpopJwtHeader,
|
|
1078
|
+
jwt: options.dpopJwt,
|
|
1079
|
+
payloadSchema: zDpopJwtPayload
|
|
1080
|
+
});
|
|
1081
|
+
if (options.allowedSigningAlgs && !options.allowedSigningAlgs.includes(header.alg)) {
|
|
1082
|
+
throw new Oauth2Error(
|
|
1083
|
+
`dpop jwt uses alg value '${header.alg}' but allowed dpop signing alg values are ${options.allowedSigningAlgs.join(", ")}.`
|
|
1084
|
+
);
|
|
1085
|
+
}
|
|
1086
|
+
if (options.expectedNonce !== void 0) {
|
|
1087
|
+
if (options.expectedNonce === "") {
|
|
1088
|
+
throw new Oauth2Error(`Invalid 'expectedNonce' provided`);
|
|
1089
|
+
}
|
|
1090
|
+
if (!payload.nonce) {
|
|
1091
|
+
throw new Oauth2Error(
|
|
1092
|
+
`Dpop jwt does not have a nonce value, but expected nonce value '${options.expectedNonce}'`
|
|
1093
|
+
);
|
|
1094
|
+
}
|
|
1095
|
+
if (payload.nonce !== options.expectedNonce) {
|
|
1096
|
+
throw new Oauth2Error(
|
|
1097
|
+
`Dpop jwt contains nonce value '${payload.nonce}', but expected nonce value '${options.expectedNonce}'`
|
|
1098
|
+
);
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
if (options.request.method !== payload.htm) {
|
|
1102
|
+
throw new Oauth2Error(
|
|
1103
|
+
`Dpop jwt contains htm value '${payload.htm}', but expected htm value '${options.request.method}'`
|
|
1104
|
+
);
|
|
1105
|
+
}
|
|
1106
|
+
const expectedHtu = htuFromRequestUrl(options.request.url);
|
|
1107
|
+
if (expectedHtu !== payload.htu) {
|
|
1108
|
+
throw new Oauth2Error(
|
|
1109
|
+
`Dpop jwt contains htu value '${payload.htu}', but expected htu value '${expectedHtu}'.`
|
|
1110
|
+
);
|
|
1111
|
+
}
|
|
1112
|
+
if (options.accessToken) {
|
|
1113
|
+
const expectedAth = encodeToBase64Url5(
|
|
1114
|
+
await options.callbacks.hash(
|
|
1115
|
+
decodeUtf8String3(options.accessToken),
|
|
1220
1116
|
HashAlgorithm5.Sha256
|
|
1221
1117
|
)
|
|
1222
1118
|
);
|
|
1119
|
+
if (!payload.ath) {
|
|
1120
|
+
throw new Oauth2Error(
|
|
1121
|
+
`Dpop jwt does not have a ath value, but expected ath value '${expectedAth}'.`
|
|
1122
|
+
);
|
|
1123
|
+
}
|
|
1124
|
+
if (payload.ath !== expectedAth) {
|
|
1125
|
+
throw new Oauth2Error(
|
|
1126
|
+
`Dpop jwt contains ath value '${payload.ath}', but expected ath value '${expectedAth}'.`
|
|
1127
|
+
);
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
const jwkThumbprint = await calculateJwkThumbprint3({
|
|
1131
|
+
hashAlgorithm: HashAlgorithm5.Sha256,
|
|
1132
|
+
hashCallback: options.callbacks.hash,
|
|
1133
|
+
jwk: header.jwk
|
|
1134
|
+
});
|
|
1135
|
+
if (options.expectedJwkThumbprint && options.expectedJwkThumbprint !== jwkThumbprint) {
|
|
1136
|
+
throw new Oauth2Error(
|
|
1137
|
+
`Dpop is signed with jwk with thumbprint value '${jwkThumbprint}', but expect jwk thumbprint value '${options.expectedJwkThumbprint}'`
|
|
1138
|
+
);
|
|
1139
|
+
}
|
|
1140
|
+
try {
|
|
1141
|
+
verifyJwtIatOrThrow({
|
|
1142
|
+
iat: payload.iat,
|
|
1143
|
+
now: options.now
|
|
1144
|
+
});
|
|
1145
|
+
} catch (error) {
|
|
1146
|
+
if (error instanceof Error) {
|
|
1147
|
+
throw new Oauth2Error(`Invalid iat claim in dpop JWT: ${error.message}`);
|
|
1148
|
+
}
|
|
1223
1149
|
}
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1150
|
+
await verifyJwt3({
|
|
1151
|
+
compact: options.dpopJwt,
|
|
1152
|
+
errorMessage: "dpop jwt verification failed",
|
|
1153
|
+
header,
|
|
1154
|
+
now: options.now,
|
|
1155
|
+
payload,
|
|
1156
|
+
signer: {
|
|
1157
|
+
alg: header.alg,
|
|
1158
|
+
method: "jwk",
|
|
1159
|
+
publicJwk: header.jwk
|
|
1160
|
+
},
|
|
1161
|
+
verifyJwtCallback: options.callbacks.verifyJwt
|
|
1162
|
+
});
|
|
1163
|
+
return {
|
|
1164
|
+
header,
|
|
1165
|
+
jwkThumbprint,
|
|
1166
|
+
payload
|
|
1167
|
+
};
|
|
1227
1168
|
}
|
|
1228
1169
|
|
|
1229
1170
|
// src/access-token/verify-access-token-request.ts
|
|
1230
1171
|
async function verifyAccessTokenRequest(options) {
|
|
1172
|
+
if (options.dpop.expectedNonce === "") {
|
|
1173
|
+
throw new Oauth2Error(`Invalid 'dpop.expectedNonce' provided`);
|
|
1174
|
+
}
|
|
1231
1175
|
await verifyPkce({
|
|
1232
1176
|
callbacks: options.callbacks,
|
|
1233
1177
|
codeChallenge: options.pkce.codeChallenge,
|
|
@@ -1238,6 +1182,7 @@ async function verifyAccessTokenRequest(options) {
|
|
|
1238
1182
|
allowedSigningAlgs: options.dpop.allowedSigningAlgs,
|
|
1239
1183
|
callbacks: options.callbacks,
|
|
1240
1184
|
dpopJwt: options.dpop.jwt,
|
|
1185
|
+
expectedNonce: options.dpop.expectedNonce,
|
|
1241
1186
|
now: options.now,
|
|
1242
1187
|
request: options.request
|
|
1243
1188
|
});
|
|
@@ -1269,40 +1214,40 @@ async function verifyAccessTokenRequest(options) {
|
|
|
1269
1214
|
|
|
1270
1215
|
// src/authorization-request/create-authorization-request.ts
|
|
1271
1216
|
import {
|
|
1272
|
-
addSecondsToDate as
|
|
1273
|
-
dateToSeconds as
|
|
1217
|
+
addSecondsToDate as addSecondsToDate3,
|
|
1218
|
+
dateToSeconds as dateToSeconds4,
|
|
1274
1219
|
encodeToBase64Url as encodeToBase64Url6
|
|
1275
1220
|
} from "@pagopa/io-wallet-utils";
|
|
1276
1221
|
|
|
1277
1222
|
// src/authorization-request/z-authorization-request.ts
|
|
1278
|
-
import
|
|
1279
|
-
var zOpenidCredentialAuthorizationDetails =
|
|
1280
|
-
credential_configuration_id:
|
|
1281
|
-
type:
|
|
1223
|
+
import z11 from "zod";
|
|
1224
|
+
var zOpenidCredentialAuthorizationDetails = z11.object({
|
|
1225
|
+
credential_configuration_id: z11.string(),
|
|
1226
|
+
type: z11.literal("openid_credential")
|
|
1282
1227
|
});
|
|
1283
|
-
var zItL2DocumentProofAuthorizationDetails =
|
|
1284
|
-
challenge_method:
|
|
1285
|
-
challenge_redirect_uri:
|
|
1286
|
-
idphinting:
|
|
1287
|
-
type:
|
|
1228
|
+
var zItL2DocumentProofAuthorizationDetails = z11.object({
|
|
1229
|
+
challenge_method: z11.literal("mrtd+ias"),
|
|
1230
|
+
challenge_redirect_uri: z11.url(),
|
|
1231
|
+
idphinting: z11.url(),
|
|
1232
|
+
type: z11.literal("it_l2+document_proof")
|
|
1288
1233
|
});
|
|
1289
|
-
var zAuthorizationRequest =
|
|
1290
|
-
authorization_details:
|
|
1291
|
-
|
|
1234
|
+
var zAuthorizationRequest = z11.looseObject({
|
|
1235
|
+
authorization_details: z11.array(
|
|
1236
|
+
z11.discriminatedUnion("type", [
|
|
1292
1237
|
zOpenidCredentialAuthorizationDetails,
|
|
1293
1238
|
zItL2DocumentProofAuthorizationDetails
|
|
1294
1239
|
])
|
|
1295
1240
|
).optional(),
|
|
1296
|
-
client_id:
|
|
1297
|
-
code_challenge:
|
|
1298
|
-
code_challenge_method:
|
|
1299
|
-
issuer_state:
|
|
1300
|
-
jti:
|
|
1301
|
-
redirect_uri:
|
|
1302
|
-
response_mode:
|
|
1303
|
-
response_type:
|
|
1304
|
-
scope:
|
|
1305
|
-
state:
|
|
1241
|
+
client_id: z11.string(),
|
|
1242
|
+
code_challenge: z11.string(),
|
|
1243
|
+
code_challenge_method: z11.string(),
|
|
1244
|
+
issuer_state: z11.optional(z11.string()),
|
|
1245
|
+
jti: z11.string().max(MAX_JTI_LENGTH),
|
|
1246
|
+
redirect_uri: z11.url(),
|
|
1247
|
+
response_mode: z11.string(),
|
|
1248
|
+
response_type: z11.string(),
|
|
1249
|
+
scope: z11.string().optional(),
|
|
1250
|
+
state: z11.string()
|
|
1306
1251
|
}).refine(
|
|
1307
1252
|
(data) => data.authorization_details !== void 0 || data.scope !== void 0,
|
|
1308
1253
|
{
|
|
@@ -1310,25 +1255,25 @@ var zAuthorizationRequest = z10.looseObject({
|
|
|
1310
1255
|
path: ["authorization_details"]
|
|
1311
1256
|
}
|
|
1312
1257
|
);
|
|
1313
|
-
var zPushedAuthorizationRequestSigned =
|
|
1314
|
-
client_id:
|
|
1258
|
+
var zPushedAuthorizationRequestSigned = z11.looseObject({
|
|
1259
|
+
client_id: z11.string().describe(
|
|
1315
1260
|
"MUST be set to the thumbprint of the jwk value in the cnf parameter inside the Wallet Attestation."
|
|
1316
1261
|
),
|
|
1317
|
-
pkceCodeVerifier:
|
|
1262
|
+
pkceCodeVerifier: z11.string().describe(
|
|
1318
1263
|
"Code verifier for PKCE. If not provided in CreatePushedAuthorizationRequestOptions, SDK will generate one."
|
|
1319
1264
|
),
|
|
1320
|
-
request:
|
|
1265
|
+
request: z11.string().describe(
|
|
1321
1266
|
"It MUST be a signed JWT. The private key corresponding to the public one in the cnf parameter inside the Wallet Attestation MUST be used for signing the Request Object."
|
|
1322
1267
|
)
|
|
1323
1268
|
});
|
|
1324
|
-
var zPushedAuthorizationRequestUnsigned =
|
|
1269
|
+
var zPushedAuthorizationRequestUnsigned = z11.looseObject({
|
|
1325
1270
|
authorizationRequest: zAuthorizationRequest.describe(
|
|
1326
1271
|
"The authorization request parameters as a plain object. Used when require_signed_request_object is false."
|
|
1327
1272
|
),
|
|
1328
|
-
client_id:
|
|
1273
|
+
client_id: z11.string().describe(
|
|
1329
1274
|
"Thumbprint of the jwk value in the cnf parameter inside Wallet Attestation."
|
|
1330
1275
|
),
|
|
1331
|
-
pkceCodeVerifier:
|
|
1276
|
+
pkceCodeVerifier: z11.string().describe("PKCE code verifier. Auto-generated if not provided in options.")
|
|
1332
1277
|
});
|
|
1333
1278
|
function isPushedAuthorizationRequestSigned(par) {
|
|
1334
1279
|
return "request" in par && typeof par.request === "string";
|
|
@@ -1336,9 +1281,9 @@ function isPushedAuthorizationRequestSigned(par) {
|
|
|
1336
1281
|
function isPushedAuthorizationRequestUnsigned(par) {
|
|
1337
1282
|
return "authorizationRequest" in par;
|
|
1338
1283
|
}
|
|
1339
|
-
var zPushedAuthorizationResponse =
|
|
1340
|
-
expires_in:
|
|
1341
|
-
request_uri:
|
|
1284
|
+
var zPushedAuthorizationResponse = z11.looseObject({
|
|
1285
|
+
expires_in: z11.number().int(),
|
|
1286
|
+
request_uri: z11.string()
|
|
1342
1287
|
});
|
|
1343
1288
|
|
|
1344
1289
|
// src/authorization-request/create-authorization-request.ts
|
|
@@ -1375,7 +1320,7 @@ async function createPushedAuthorizationRequest(options) {
|
|
|
1375
1320
|
);
|
|
1376
1321
|
}
|
|
1377
1322
|
const iat = options.issuedAt ?? /* @__PURE__ */ new Date();
|
|
1378
|
-
const exp = options.expiresAt ??
|
|
1323
|
+
const exp = options.expiresAt ?? addSecondsToDate3(iat, JWT_EXPIRY_SECONDS);
|
|
1379
1324
|
const requestJwt = await options.callbacks.signJwt(dpop.signer, {
|
|
1380
1325
|
header: {
|
|
1381
1326
|
alg: dpop.signer.alg,
|
|
@@ -1384,8 +1329,8 @@ async function createPushedAuthorizationRequest(options) {
|
|
|
1384
1329
|
},
|
|
1385
1330
|
payload: {
|
|
1386
1331
|
aud: options.audience,
|
|
1387
|
-
exp:
|
|
1388
|
-
iat:
|
|
1332
|
+
exp: dateToSeconds4(exp),
|
|
1333
|
+
iat: dateToSeconds4(iat),
|
|
1389
1334
|
iss: dpop.signer.publicJwk.kid,
|
|
1390
1335
|
...authorizationRequest
|
|
1391
1336
|
}
|
|
@@ -1409,7 +1354,7 @@ import {
|
|
|
1409
1354
|
CONTENT_TYPES as CONTENT_TYPES2,
|
|
1410
1355
|
HEADERS as HEADERS2,
|
|
1411
1356
|
UnexpectedStatusCodeError as UnexpectedStatusCodeError2,
|
|
1412
|
-
ValidationError as
|
|
1357
|
+
ValidationError as ValidationError3,
|
|
1413
1358
|
createFetcher as createFetcher2,
|
|
1414
1359
|
hasStatusOrThrow as hasStatusOrThrow2
|
|
1415
1360
|
} from "@pagopa/io-wallet-utils";
|
|
@@ -1440,14 +1385,14 @@ async function fetchPushedAuthorizationResponse(options) {
|
|
|
1440
1385
|
const parResponseJson = await parResponse.json();
|
|
1441
1386
|
const parsedParResponse = zPushedAuthorizationResponse.safeParse(parResponseJson);
|
|
1442
1387
|
if (!parsedParResponse.success) {
|
|
1443
|
-
throw new
|
|
1388
|
+
throw new ValidationError3(
|
|
1444
1389
|
`Failed to parse pushed authorization response`,
|
|
1445
1390
|
parsedParResponse.error
|
|
1446
1391
|
);
|
|
1447
1392
|
}
|
|
1448
1393
|
return parsedParResponse.data;
|
|
1449
1394
|
} catch (error) {
|
|
1450
|
-
if (error instanceof UnexpectedStatusCodeError2 || error instanceof
|
|
1395
|
+
if (error instanceof UnexpectedStatusCodeError2 || error instanceof ValidationError3) {
|
|
1451
1396
|
throw error;
|
|
1452
1397
|
}
|
|
1453
1398
|
throw new PushedAuthorizationRequestError(
|
|
@@ -1495,56 +1440,9 @@ function parseAuthorizationRequest(options) {
|
|
|
1495
1440
|
// src/authorization-request/parse-pushed-authorization-request.ts
|
|
1496
1441
|
import {
|
|
1497
1442
|
formatZodError as formatZodError2,
|
|
1498
|
-
parseWithErrorHandling as
|
|
1443
|
+
parseWithErrorHandling as parseWithErrorHandling6
|
|
1499
1444
|
} from "@pagopa/io-wallet-utils";
|
|
1500
|
-
import
|
|
1501
|
-
|
|
1502
|
-
// src/jar/create-jar-request.ts
|
|
1503
|
-
import { addSecondsToDate as addSecondsToDate6, dateToSeconds as dateToSeconds7 } from "@pagopa/io-wallet-utils";
|
|
1504
|
-
async function createJarRequest(options) {
|
|
1505
|
-
const {
|
|
1506
|
-
authorizationRequestHeader,
|
|
1507
|
-
authorizationRequestPayload,
|
|
1508
|
-
callbacks,
|
|
1509
|
-
jweEncryptor,
|
|
1510
|
-
jwtSigner,
|
|
1511
|
-
requestUri
|
|
1512
|
-
} = options;
|
|
1513
|
-
let authorizationRequestJwt;
|
|
1514
|
-
let encryptionJwk;
|
|
1515
|
-
const now = options.now ?? /* @__PURE__ */ new Date();
|
|
1516
|
-
const { jwt, signerJwk } = await callbacks.signJwt(jwtSigner, {
|
|
1517
|
-
header: authorizationRequestHeader,
|
|
1518
|
-
payload: {
|
|
1519
|
-
...options.additionalJwtPayload,
|
|
1520
|
-
...authorizationRequestPayload,
|
|
1521
|
-
exp: dateToSeconds7(addSecondsToDate6(now, options.expiresInSeconds)),
|
|
1522
|
-
iat: dateToSeconds7(now)
|
|
1523
|
-
}
|
|
1524
|
-
});
|
|
1525
|
-
authorizationRequestJwt = jwt;
|
|
1526
|
-
if (jweEncryptor) {
|
|
1527
|
-
if (!callbacks.encryptJwe) {
|
|
1528
|
-
throw new Oauth2Error(
|
|
1529
|
-
"callbacks.encryptJwe is required when jweEncryptor is provided"
|
|
1530
|
-
);
|
|
1531
|
-
}
|
|
1532
|
-
const encryptionResult = await callbacks.encryptJwe(
|
|
1533
|
-
jweEncryptor,
|
|
1534
|
-
authorizationRequestJwt
|
|
1535
|
-
);
|
|
1536
|
-
authorizationRequestJwt = encryptionResult.jwe;
|
|
1537
|
-
encryptionJwk = encryptionResult.encryptionJwk;
|
|
1538
|
-
}
|
|
1539
|
-
const client_id = authorizationRequestPayload.client_id;
|
|
1540
|
-
const jarAuthorizationRequest = requestUri ? { client_id, request_uri: requestUri } : { client_id, request: authorizationRequestJwt };
|
|
1541
|
-
return {
|
|
1542
|
-
authorizationRequestJwt,
|
|
1543
|
-
encryptionJwk,
|
|
1544
|
-
jarAuthorizationRequest,
|
|
1545
|
-
signerJwk
|
|
1546
|
-
};
|
|
1547
|
-
}
|
|
1445
|
+
import z13 from "zod";
|
|
1548
1446
|
|
|
1549
1447
|
// src/jar/fetch-jar-request-object.ts
|
|
1550
1448
|
import {
|
|
@@ -1609,130 +1507,32 @@ async function parseJarRequest(options) {
|
|
|
1609
1507
|
return { authorizationRequestJwt, sendBy };
|
|
1610
1508
|
}
|
|
1611
1509
|
|
|
1612
|
-
// src/jar/verify-jar-request.ts
|
|
1613
|
-
import {
|
|
1614
|
-
decodeJwt as decodeJwt2,
|
|
1615
|
-
verifyJwt as verifyJwt4,
|
|
1616
|
-
zCompactJwe,
|
|
1617
|
-
zCompactJwt as zCompactJwt4
|
|
1618
|
-
} from "@openid4vc/oauth2";
|
|
1619
|
-
import { parseWithErrorHandling as parseWithErrorHandling6 } from "@pagopa/io-wallet-utils";
|
|
1620
|
-
|
|
1621
1510
|
// src/jar/z-jar.ts
|
|
1622
|
-
import
|
|
1623
|
-
var zJarAuthorizationRequest =
|
|
1624
|
-
client_id:
|
|
1625
|
-
request:
|
|
1626
|
-
request_uri:
|
|
1511
|
+
import z12 from "zod";
|
|
1512
|
+
var zJarAuthorizationRequest = z12.looseObject({
|
|
1513
|
+
client_id: z12.optional(z12.string()),
|
|
1514
|
+
request: z12.optional(z12.string()),
|
|
1515
|
+
request_uri: z12.url().optional()
|
|
1627
1516
|
});
|
|
1628
|
-
var zJarRequestObjectPayload =
|
|
1517
|
+
var zJarRequestObjectPayload = z12.looseObject({
|
|
1629
1518
|
...zJwtPayload.shape,
|
|
1630
|
-
client_id:
|
|
1519
|
+
client_id: z12.string()
|
|
1631
1520
|
});
|
|
1632
|
-
var zSignedAuthorizationRequestJwtHeaderTyp =
|
|
1521
|
+
var zSignedAuthorizationRequestJwtHeaderTyp = z12.literal(
|
|
1633
1522
|
"oauth-authz-req+jwt"
|
|
1634
1523
|
);
|
|
1635
|
-
var zJarRequestObjectHeader =
|
|
1524
|
+
var zJarRequestObjectHeader = z12.looseObject({
|
|
1636
1525
|
...zJwtHeader.shape,
|
|
1637
1526
|
typ: zSignedAuthorizationRequestJwtHeaderTyp
|
|
1638
1527
|
});
|
|
1639
1528
|
var signedAuthorizationRequestJwtHeaderTyp = zSignedAuthorizationRequestJwtHeaderTyp.value;
|
|
1640
|
-
var zJwtAuthorizationRequestJwtHeaderTyp =
|
|
1529
|
+
var zJwtAuthorizationRequestJwtHeaderTyp = z12.literal("jwt");
|
|
1641
1530
|
var jwtAuthorizationRequestJwtHeaderTyp = zJwtAuthorizationRequestJwtHeaderTyp.value;
|
|
1642
1531
|
|
|
1643
|
-
// src/jar/verify-jar-request.ts
|
|
1644
|
-
async function verifyJarRequest(options) {
|
|
1645
|
-
const { authorizationRequestJwt, callbacks, jarRequestParams, jwtSigner } = options;
|
|
1646
|
-
const requestObjectIsEncrypted = zCompactJwe.safeParse(
|
|
1647
|
-
authorizationRequestJwt
|
|
1648
|
-
).success;
|
|
1649
|
-
if (requestObjectIsEncrypted) {
|
|
1650
|
-
throw new Oauth2Error("Encrypted JWE request objects are not supported.");
|
|
1651
|
-
}
|
|
1652
|
-
const requestIsSigned = zCompactJwt4.safeParse(
|
|
1653
|
-
authorizationRequestJwt
|
|
1654
|
-
).success;
|
|
1655
|
-
if (!requestIsSigned) {
|
|
1656
|
-
throw new Oauth2Error("JAR request object is not a valid JWT.");
|
|
1657
|
-
}
|
|
1658
|
-
const { authorizationRequestPayload, jwt, signer } = await verifyJarRequestObject({
|
|
1659
|
-
authorizationRequestJwt,
|
|
1660
|
-
callbacks,
|
|
1661
|
-
jwtSigner
|
|
1662
|
-
});
|
|
1663
|
-
if (!authorizationRequestPayload.client_id) {
|
|
1664
|
-
throw new Oauth2Error(
|
|
1665
|
-
'Jar Request Object is missing the required "client_id" field.'
|
|
1666
|
-
);
|
|
1667
|
-
}
|
|
1668
|
-
if (jarRequestParams.client_id !== authorizationRequestPayload.client_id) {
|
|
1669
|
-
throw new Oauth2Error(
|
|
1670
|
-
"client_id does not match the request object client_id."
|
|
1671
|
-
);
|
|
1672
|
-
}
|
|
1673
|
-
if (jwt.payload.iss !== authorizationRequestPayload.client_id) {
|
|
1674
|
-
throw new Oauth2Error("iss claim in request JWT does not match client_id");
|
|
1675
|
-
}
|
|
1676
|
-
if (jwt.payload.exp === void 0) {
|
|
1677
|
-
throw new Oauth2Error("exp claim in request JWT is missing");
|
|
1678
|
-
}
|
|
1679
|
-
const now = options.now ?? /* @__PURE__ */ new Date();
|
|
1680
|
-
const nowSeconds = Math.floor(now.getTime() / 1e3);
|
|
1681
|
-
if (nowSeconds > jwt.payload.exp) {
|
|
1682
|
-
throw new Oauth2Error("exp claim in request JWT is expired");
|
|
1683
|
-
}
|
|
1684
|
-
if (jwt.payload.iat === void 0) {
|
|
1685
|
-
throw new Oauth2Error("iat claim in request JWT is missing");
|
|
1686
|
-
}
|
|
1687
|
-
const MAX_IAT_AGE_SECONDS = 5 * 60;
|
|
1688
|
-
if (nowSeconds - jwt.payload.iat > MAX_IAT_AGE_SECONDS) {
|
|
1689
|
-
throw new Oauth2Error(
|
|
1690
|
-
"iat claim in request JWT is too old (must be within 5 minutes)"
|
|
1691
|
-
);
|
|
1692
|
-
}
|
|
1693
|
-
const CLOCK_SKEW_TOLERANCE_SECONDS = 60;
|
|
1694
|
-
if (jwt.payload.iat - nowSeconds > CLOCK_SKEW_TOLERANCE_SECONDS) {
|
|
1695
|
-
throw new Oauth2Error("iat claim in request JWT is too far in the future");
|
|
1696
|
-
}
|
|
1697
|
-
return {
|
|
1698
|
-
authorizationRequestPayload,
|
|
1699
|
-
jwt,
|
|
1700
|
-
signer
|
|
1701
|
-
};
|
|
1702
|
-
}
|
|
1703
|
-
async function verifyJarRequestObject(options) {
|
|
1704
|
-
const { authorizationRequestJwt, callbacks, jwtSigner } = options;
|
|
1705
|
-
const jwt = decodeJwt2({ jwt: authorizationRequestJwt });
|
|
1706
|
-
const authorizationRequestPayload = parseWithErrorHandling6(
|
|
1707
|
-
zJarRequestObjectPayload,
|
|
1708
|
-
jwt.payload
|
|
1709
|
-
);
|
|
1710
|
-
const { signer } = await verifyJwt4({
|
|
1711
|
-
compact: authorizationRequestJwt,
|
|
1712
|
-
header: jwt.header,
|
|
1713
|
-
payload: authorizationRequestPayload,
|
|
1714
|
-
signer: jwtSigner,
|
|
1715
|
-
verifyJwtCallback: callbacks.verifyJwt
|
|
1716
|
-
});
|
|
1717
|
-
if (jwt.header.typ !== signedAuthorizationRequestJwtHeaderTyp && jwt.header.typ !== jwtAuthorizationRequestJwtHeaderTyp) {
|
|
1718
|
-
throw new Oauth2Error(
|
|
1719
|
-
`Invalid Jar Request Object typ header. Expected "oauth-authz-req+jwt" or "jwt", received "${jwt.header.typ}".`
|
|
1720
|
-
);
|
|
1721
|
-
}
|
|
1722
|
-
return {
|
|
1723
|
-
authorizationRequestPayload,
|
|
1724
|
-
jwt: {
|
|
1725
|
-
...jwt,
|
|
1726
|
-
payload: authorizationRequestPayload
|
|
1727
|
-
},
|
|
1728
|
-
signer
|
|
1729
|
-
};
|
|
1730
|
-
}
|
|
1731
|
-
|
|
1732
1532
|
// src/authorization-request/parse-pushed-authorization-request.ts
|
|
1733
1533
|
async function parsePushedAuthorizationRequest(options) {
|
|
1734
|
-
const parsed =
|
|
1735
|
-
|
|
1534
|
+
const parsed = parseWithErrorHandling6(
|
|
1535
|
+
z13.union([zAuthorizationRequest, zJarAuthorizationRequest]),
|
|
1736
1536
|
options.authorizationRequest,
|
|
1737
1537
|
"Invalid authorization request. Could not parse authorization request or jar."
|
|
1738
1538
|
);
|
|
@@ -1743,7 +1543,10 @@ async function parsePushedAuthorizationRequest(options) {
|
|
|
1743
1543
|
callbacks: options.callbacks,
|
|
1744
1544
|
jarRequestParams: parsed
|
|
1745
1545
|
});
|
|
1746
|
-
const jwt = decodeJwt({
|
|
1546
|
+
const jwt = decodeJwt({
|
|
1547
|
+
errorMessagePrefix: "Error decoding pushed authorization request JWT:",
|
|
1548
|
+
jwt: parsedJar.authorizationRequestJwt
|
|
1549
|
+
});
|
|
1747
1550
|
parsedAuthorizationRequest = zAuthorizationRequest.safeParse(jwt.payload);
|
|
1748
1551
|
if (!parsedAuthorizationRequest.success) {
|
|
1749
1552
|
throw new Oauth2Error(
|
|
@@ -1793,29 +1596,127 @@ async function verifyAuthorizationRequest(options) {
|
|
|
1793
1596
|
requestClientId: options.authorizationRequest.client_id
|
|
1794
1597
|
});
|
|
1795
1598
|
return {
|
|
1796
|
-
clientAttestation: clientAttestationResult,
|
|
1797
|
-
dpop: dpopResult?.jwkThumbprint ? {
|
|
1798
|
-
jwk: dpopResult.jwk,
|
|
1799
|
-
jwkThumbprint: dpopResult.jwkThumbprint
|
|
1800
|
-
} : void 0
|
|
1599
|
+
clientAttestation: clientAttestationResult,
|
|
1600
|
+
dpop: dpopResult?.jwkThumbprint ? {
|
|
1601
|
+
jwk: dpopResult.jwk,
|
|
1602
|
+
jwkThumbprint: dpopResult.jwkThumbprint
|
|
1603
|
+
} : void 0
|
|
1604
|
+
};
|
|
1605
|
+
}
|
|
1606
|
+
async function verifyAuthorizationRequestDpop(options, request, callbacks, now) {
|
|
1607
|
+
if (options.required && !options.jwt) {
|
|
1608
|
+
throw new Oauth2Error(
|
|
1609
|
+
`Missing required DPoP parameters in authorization request. DPoP header is required.`
|
|
1610
|
+
);
|
|
1611
|
+
}
|
|
1612
|
+
const verifyDpopResult = options.jwt ? await verifyTokenDPoP({
|
|
1613
|
+
allowedSigningAlgs: options.allowedSigningAlgs,
|
|
1614
|
+
callbacks,
|
|
1615
|
+
dpopJwt: options.jwt,
|
|
1616
|
+
now,
|
|
1617
|
+
request
|
|
1618
|
+
}) : void 0;
|
|
1619
|
+
return {
|
|
1620
|
+
jwk: verifyDpopResult?.header.jwk,
|
|
1621
|
+
jwkThumbprint: verifyDpopResult?.jwkThumbprint
|
|
1622
|
+
};
|
|
1623
|
+
}
|
|
1624
|
+
|
|
1625
|
+
// src/jar/verify-jar-request.ts
|
|
1626
|
+
import {
|
|
1627
|
+
verifyJwt as verifyJwt4,
|
|
1628
|
+
zCompactJwe,
|
|
1629
|
+
zCompactJwt as zCompactJwt4
|
|
1630
|
+
} from "@openid4vc/oauth2";
|
|
1631
|
+
import { parseWithErrorHandling as parseWithErrorHandling7 } from "@pagopa/io-wallet-utils";
|
|
1632
|
+
async function verifyJarRequest(options) {
|
|
1633
|
+
const { authorizationRequestJwt, callbacks, jarRequestParams, jwtSigner } = options;
|
|
1634
|
+
const requestObjectIsEncrypted = zCompactJwe.safeParse(
|
|
1635
|
+
authorizationRequestJwt
|
|
1636
|
+
).success;
|
|
1637
|
+
if (requestObjectIsEncrypted) {
|
|
1638
|
+
throw new Oauth2Error("Encrypted JWE request objects are not supported.");
|
|
1639
|
+
}
|
|
1640
|
+
const requestIsSigned = zCompactJwt4.safeParse(
|
|
1641
|
+
authorizationRequestJwt
|
|
1642
|
+
).success;
|
|
1643
|
+
if (!requestIsSigned) {
|
|
1644
|
+
throw new Oauth2Error("JAR request object is not a valid JWT.");
|
|
1645
|
+
}
|
|
1646
|
+
const { authorizationRequestPayload, jwt, signer } = await verifyJarRequestObject({
|
|
1647
|
+
authorizationRequestJwt,
|
|
1648
|
+
callbacks,
|
|
1649
|
+
jwtSigner
|
|
1650
|
+
});
|
|
1651
|
+
if (!authorizationRequestPayload.client_id) {
|
|
1652
|
+
throw new Oauth2Error(
|
|
1653
|
+
'Jar Request Object is missing the required "client_id" field.'
|
|
1654
|
+
);
|
|
1655
|
+
}
|
|
1656
|
+
if (jarRequestParams.client_id !== authorizationRequestPayload.client_id) {
|
|
1657
|
+
throw new Oauth2Error(
|
|
1658
|
+
"client_id does not match the request object client_id."
|
|
1659
|
+
);
|
|
1660
|
+
}
|
|
1661
|
+
if (jwt.payload.iss !== authorizationRequestPayload.client_id) {
|
|
1662
|
+
throw new Oauth2Error("iss claim in request JWT does not match client_id");
|
|
1663
|
+
}
|
|
1664
|
+
if (jwt.payload.exp === void 0) {
|
|
1665
|
+
throw new Oauth2Error("exp claim in request JWT is missing");
|
|
1666
|
+
}
|
|
1667
|
+
const now = options.now ?? /* @__PURE__ */ new Date();
|
|
1668
|
+
const nowSeconds = Math.floor(now.getTime() / 1e3);
|
|
1669
|
+
if (nowSeconds > jwt.payload.exp) {
|
|
1670
|
+
throw new Oauth2Error("exp claim in request JWT is expired");
|
|
1671
|
+
}
|
|
1672
|
+
if (jwt.payload.iat === void 0) {
|
|
1673
|
+
throw new Oauth2Error("iat claim in request JWT is missing");
|
|
1674
|
+
}
|
|
1675
|
+
const MAX_IAT_AGE_SECONDS = 5 * 60;
|
|
1676
|
+
if (nowSeconds - jwt.payload.iat > MAX_IAT_AGE_SECONDS) {
|
|
1677
|
+
throw new Oauth2Error(
|
|
1678
|
+
"iat claim in request JWT is too old (must be within 5 minutes)"
|
|
1679
|
+
);
|
|
1680
|
+
}
|
|
1681
|
+
const CLOCK_SKEW_TOLERANCE_SECONDS = 60;
|
|
1682
|
+
if (jwt.payload.iat - nowSeconds > CLOCK_SKEW_TOLERANCE_SECONDS) {
|
|
1683
|
+
throw new Oauth2Error("iat claim in request JWT is too far in the future");
|
|
1684
|
+
}
|
|
1685
|
+
return {
|
|
1686
|
+
authorizationRequestPayload,
|
|
1687
|
+
jwt,
|
|
1688
|
+
signer
|
|
1801
1689
|
};
|
|
1802
1690
|
}
|
|
1803
|
-
async function
|
|
1804
|
-
|
|
1691
|
+
async function verifyJarRequestObject(options) {
|
|
1692
|
+
const { authorizationRequestJwt, callbacks, jwtSigner } = options;
|
|
1693
|
+
const jwt = decodeJwt({
|
|
1694
|
+
errorMessagePrefix: "Error decoding JAR authorization request JWT:",
|
|
1695
|
+
jwt: authorizationRequestJwt
|
|
1696
|
+
});
|
|
1697
|
+
const authorizationRequestPayload = parseWithErrorHandling7(
|
|
1698
|
+
zJarRequestObjectPayload,
|
|
1699
|
+
jwt.payload
|
|
1700
|
+
);
|
|
1701
|
+
const { signer } = await verifyJwt4({
|
|
1702
|
+
compact: authorizationRequestJwt,
|
|
1703
|
+
header: jwt.header,
|
|
1704
|
+
payload: authorizationRequestPayload,
|
|
1705
|
+
signer: jwtSigner,
|
|
1706
|
+
verifyJwtCallback: callbacks.verifyJwt
|
|
1707
|
+
});
|
|
1708
|
+
if (jwt.header.typ !== signedAuthorizationRequestJwtHeaderTyp && jwt.header.typ !== jwtAuthorizationRequestJwtHeaderTyp) {
|
|
1805
1709
|
throw new Oauth2Error(
|
|
1806
|
-
`
|
|
1710
|
+
`Invalid Jar Request Object typ header. Expected "oauth-authz-req+jwt" or "jwt", received "${jwt.header.typ}".`
|
|
1807
1711
|
);
|
|
1808
1712
|
}
|
|
1809
|
-
const verifyDpopResult = options.jwt ? await verifyTokenDPoP({
|
|
1810
|
-
allowedSigningAlgs: options.allowedSigningAlgs,
|
|
1811
|
-
callbacks,
|
|
1812
|
-
dpopJwt: options.jwt,
|
|
1813
|
-
now,
|
|
1814
|
-
request
|
|
1815
|
-
}) : void 0;
|
|
1816
1713
|
return {
|
|
1817
|
-
|
|
1818
|
-
|
|
1714
|
+
authorizationRequestPayload,
|
|
1715
|
+
jwt: {
|
|
1716
|
+
...jwt,
|
|
1717
|
+
payload: authorizationRequestPayload
|
|
1718
|
+
},
|
|
1719
|
+
signer
|
|
1819
1720
|
};
|
|
1820
1721
|
}
|
|
1821
1722
|
|
|
@@ -1830,7 +1731,10 @@ async function verifyPushedAuthorizationRequest(options) {
|
|
|
1830
1731
|
let jar;
|
|
1831
1732
|
if (options.authorizationRequestJwt) {
|
|
1832
1733
|
if (requireSigned) {
|
|
1833
|
-
const decoded = decodeJwt({
|
|
1734
|
+
const decoded = decodeJwt({
|
|
1735
|
+
errorMessagePrefix: "Error decoding pushed authorization request JWT:",
|
|
1736
|
+
jwt: options.authorizationRequestJwt.jwt
|
|
1737
|
+
});
|
|
1834
1738
|
if (decoded.header.alg === "none") {
|
|
1835
1739
|
throw new PushedAuthorizationRequestError(
|
|
1836
1740
|
'Authorization Server requires signed request objects, but JAR has algorithm "none"'
|
|
@@ -1879,15 +1783,259 @@ async function verifyPushedAuthorizationRequest(options) {
|
|
|
1879
1783
|
};
|
|
1880
1784
|
}
|
|
1881
1785
|
|
|
1786
|
+
// src/client-attestation/client-authentication.ts
|
|
1787
|
+
var SupportedClientAuthenticationMethod = {
|
|
1788
|
+
ClientSecretBasic: "client_secret_basic",
|
|
1789
|
+
ClientSecretPost: "client_secret_post",
|
|
1790
|
+
None: "none",
|
|
1791
|
+
WalletAttestationJwt: "attest_jwt_client_auth"
|
|
1792
|
+
};
|
|
1793
|
+
function isClientAttestationSupported(options) {
|
|
1794
|
+
if (!options.authorizationServerMetadata.token_endpoint_auth_methods_supported || !options.authorizationServerMetadata.token_endpoint_auth_methods_supported.includes(
|
|
1795
|
+
SupportedClientAuthenticationMethod.WalletAttestationJwt
|
|
1796
|
+
)) {
|
|
1797
|
+
return {
|
|
1798
|
+
supported: false
|
|
1799
|
+
};
|
|
1800
|
+
}
|
|
1801
|
+
return {
|
|
1802
|
+
supported: true
|
|
1803
|
+
};
|
|
1804
|
+
}
|
|
1805
|
+
function clientAuthenticationAnonymous() {
|
|
1806
|
+
return () => {
|
|
1807
|
+
};
|
|
1808
|
+
}
|
|
1809
|
+
function clientAuthenticationWalletAttestationJwt(options) {
|
|
1810
|
+
return async ({ authorizationServerMetadata, headers }) => {
|
|
1811
|
+
const clientAttestationPop = await createClientAttestationPopJwt({
|
|
1812
|
+
authorizationServer: authorizationServerMetadata.issuer,
|
|
1813
|
+
callbacks: options.callbacks,
|
|
1814
|
+
clientAttestation: options.walletAttestationJwt
|
|
1815
|
+
});
|
|
1816
|
+
headers.set(oauthClientAttestationHeader, options.walletAttestationJwt);
|
|
1817
|
+
headers.set(oauthClientAttestationPopHeader, clientAttestationPop);
|
|
1818
|
+
};
|
|
1819
|
+
}
|
|
1820
|
+
|
|
1821
|
+
// src/client-attestation/v1.0/create-wallet-attestation-jwt.ts
|
|
1822
|
+
import {
|
|
1823
|
+
ValidationError as ValidationError4,
|
|
1824
|
+
addSecondsToDate as addSecondsToDate4,
|
|
1825
|
+
dateToSeconds as dateToSeconds5
|
|
1826
|
+
} from "@pagopa/io-wallet-utils";
|
|
1827
|
+
var createWalletAttestationJwt = async (options) => {
|
|
1828
|
+
try {
|
|
1829
|
+
const { signJwt } = options.callbacks;
|
|
1830
|
+
const iat = /* @__PURE__ */ new Date();
|
|
1831
|
+
const exp = options.expiresAt ?? addSecondsToDate4(iat, 3600);
|
|
1832
|
+
const payload = {
|
|
1833
|
+
cnf: { jwk: options.dpopJwkPublic },
|
|
1834
|
+
exp: dateToSeconds5(exp),
|
|
1835
|
+
iat: dateToSeconds5(iat),
|
|
1836
|
+
iss: options.issuer,
|
|
1837
|
+
sub: options.dpopJwkPublic.kid,
|
|
1838
|
+
...options.walletLink && { wallet_link: options.walletLink },
|
|
1839
|
+
...options.walletName && { wallet_name: options.walletName },
|
|
1840
|
+
aal: options.authenticatorAssuranceLevel
|
|
1841
|
+
};
|
|
1842
|
+
const header = {
|
|
1843
|
+
alg: options.signer.alg,
|
|
1844
|
+
kid: options.signer.kid,
|
|
1845
|
+
trust_chain: options.signer.trustChain,
|
|
1846
|
+
typ: "oauth-client-attestation+jwt"
|
|
1847
|
+
};
|
|
1848
|
+
const result = await signJwt(options.signer, {
|
|
1849
|
+
header,
|
|
1850
|
+
payload
|
|
1851
|
+
});
|
|
1852
|
+
decodeJwt({
|
|
1853
|
+
errorMessagePrefix: "Error decoding wallet attestation JWT:",
|
|
1854
|
+
headerSchema: zWalletAttestationJwtHeaderV1_0,
|
|
1855
|
+
jwt: result.jwt,
|
|
1856
|
+
payloadSchema: zWalletAttestationJwtPayloadV1_0
|
|
1857
|
+
});
|
|
1858
|
+
return result.jwt;
|
|
1859
|
+
} catch (error) {
|
|
1860
|
+
if (error instanceof ValidationError4) {
|
|
1861
|
+
throw error;
|
|
1862
|
+
}
|
|
1863
|
+
throw new ClientAttestationError(
|
|
1864
|
+
`Unexpected error during wallet attestation creation: ${error instanceof Error ? error.message : String(error)}`
|
|
1865
|
+
);
|
|
1866
|
+
}
|
|
1867
|
+
};
|
|
1868
|
+
|
|
1869
|
+
// src/client-attestation/v1.3/create-wallet-attestation-jwt.ts
|
|
1870
|
+
import {
|
|
1871
|
+
ValidationError as ValidationError5,
|
|
1872
|
+
addSecondsToDate as addSecondsToDate5,
|
|
1873
|
+
dateToSeconds as dateToSeconds6
|
|
1874
|
+
} from "@pagopa/io-wallet-utils";
|
|
1875
|
+
var createWalletAttestationJwt2 = async (options) => {
|
|
1876
|
+
try {
|
|
1877
|
+
const { signJwt } = options.callbacks;
|
|
1878
|
+
const iat = /* @__PURE__ */ new Date();
|
|
1879
|
+
const exp = options.expiresAt ?? addSecondsToDate5(iat, 3600);
|
|
1880
|
+
if (options.nbf && options.nbf >= exp) {
|
|
1881
|
+
throw new ValidationError5("nbf must be before exp");
|
|
1882
|
+
}
|
|
1883
|
+
const payload = {
|
|
1884
|
+
cnf: { jwk: options.dpopJwkPublic },
|
|
1885
|
+
exp: dateToSeconds6(exp),
|
|
1886
|
+
iat: dateToSeconds6(iat),
|
|
1887
|
+
iss: options.issuer,
|
|
1888
|
+
sub: options.dpopJwkPublic.kid,
|
|
1889
|
+
...options.nbf && { nbf: dateToSeconds6(options.nbf) },
|
|
1890
|
+
...options.status && { status: options.status },
|
|
1891
|
+
...options.walletLink && { wallet_link: options.walletLink },
|
|
1892
|
+
...options.walletName && { wallet_name: options.walletName }
|
|
1893
|
+
};
|
|
1894
|
+
const header = {
|
|
1895
|
+
alg: options.signer.alg,
|
|
1896
|
+
kid: options.signer.kid,
|
|
1897
|
+
typ: "oauth-client-attestation+jwt",
|
|
1898
|
+
x5c: options.signer.x5c,
|
|
1899
|
+
// REQUIRED
|
|
1900
|
+
...options.signer.trustChain && {
|
|
1901
|
+
trust_chain: options.signer.trustChain
|
|
1902
|
+
}
|
|
1903
|
+
};
|
|
1904
|
+
const result = await signJwt(options.signer, {
|
|
1905
|
+
header,
|
|
1906
|
+
payload
|
|
1907
|
+
});
|
|
1908
|
+
decodeJwt({
|
|
1909
|
+
errorMessagePrefix: "Error decoding wallet attestation JWT:",
|
|
1910
|
+
headerSchema: zWalletAttestationJwtHeaderV1_3,
|
|
1911
|
+
jwt: result.jwt,
|
|
1912
|
+
payloadSchema: zWalletAttestationJwtPayloadV1_3
|
|
1913
|
+
});
|
|
1914
|
+
return result.jwt;
|
|
1915
|
+
} catch (error) {
|
|
1916
|
+
if (error instanceof ValidationError5) {
|
|
1917
|
+
throw error;
|
|
1918
|
+
}
|
|
1919
|
+
throw new ClientAttestationError(
|
|
1920
|
+
`Unexpected error during wallet attestation creation: ${error instanceof Error ? error.message : String(error)}`
|
|
1921
|
+
);
|
|
1922
|
+
}
|
|
1923
|
+
};
|
|
1924
|
+
|
|
1925
|
+
// src/client-attestation/v1.4/create-wallet-attestation-jwt.ts
|
|
1926
|
+
import {
|
|
1927
|
+
ValidationError as ValidationError6,
|
|
1928
|
+
addSecondsToDate as addSecondsToDate6,
|
|
1929
|
+
dateToSeconds as dateToSeconds7
|
|
1930
|
+
} from "@pagopa/io-wallet-utils";
|
|
1931
|
+
var createWalletAttestationJwt3 = async (options) => {
|
|
1932
|
+
try {
|
|
1933
|
+
const { signJwt } = options.callbacks;
|
|
1934
|
+
const iat = /* @__PURE__ */ new Date();
|
|
1935
|
+
const exp = options.expiresAt ?? addSecondsToDate6(iat, 3600);
|
|
1936
|
+
if (options.nbf && options.nbf >= exp) {
|
|
1937
|
+
throw new ValidationError6("nbf must be before exp");
|
|
1938
|
+
}
|
|
1939
|
+
const payload = {
|
|
1940
|
+
cnf: { jwk: options.dpopJwkPublic },
|
|
1941
|
+
exp: dateToSeconds7(exp),
|
|
1942
|
+
iat: dateToSeconds7(iat),
|
|
1943
|
+
iss: options.issuer,
|
|
1944
|
+
status: options.status,
|
|
1945
|
+
sub: options.dpopJwkPublic.kid,
|
|
1946
|
+
wallet_link: options.walletLink,
|
|
1947
|
+
wallet_name: options.walletName,
|
|
1948
|
+
...options.nbf && { nbf: dateToSeconds7(options.nbf) },
|
|
1949
|
+
...options.eudiWalletInfo && {
|
|
1950
|
+
eudi_wallet_info: options.eudiWalletInfo
|
|
1951
|
+
}
|
|
1952
|
+
};
|
|
1953
|
+
const header = {
|
|
1954
|
+
alg: options.signer.alg,
|
|
1955
|
+
kid: options.signer.kid,
|
|
1956
|
+
typ: "oauth-client-attestation+jwt",
|
|
1957
|
+
x5c: options.signer.x5c,
|
|
1958
|
+
...options.signer.trustChain && {
|
|
1959
|
+
trust_chain: options.signer.trustChain
|
|
1960
|
+
}
|
|
1961
|
+
};
|
|
1962
|
+
const result = await signJwt(options.signer, {
|
|
1963
|
+
header,
|
|
1964
|
+
payload
|
|
1965
|
+
});
|
|
1966
|
+
decodeJwt({
|
|
1967
|
+
errorMessagePrefix: "Error decoding wallet attestation JWT:",
|
|
1968
|
+
headerSchema: zWalletAttestationJwtHeaderV1_4,
|
|
1969
|
+
jwt: result.jwt,
|
|
1970
|
+
payloadSchema: zWalletAttestationJwtPayloadV1_4
|
|
1971
|
+
});
|
|
1972
|
+
return result.jwt;
|
|
1973
|
+
} catch (error) {
|
|
1974
|
+
if (error instanceof ValidationError6) {
|
|
1975
|
+
throw error;
|
|
1976
|
+
}
|
|
1977
|
+
throw new ClientAttestationError(
|
|
1978
|
+
`Unexpected error during wallet attestation creation: ${error instanceof Error ? error.message : String(error)}`
|
|
1979
|
+
);
|
|
1980
|
+
}
|
|
1981
|
+
};
|
|
1982
|
+
|
|
1882
1983
|
// src/common/jwt/z-jwe.ts
|
|
1883
|
-
import { z as
|
|
1884
|
-
var zCompactJwe2 =
|
|
1984
|
+
import { z as z14 } from "zod";
|
|
1985
|
+
var zCompactJwe2 = z14.string().regex(
|
|
1885
1986
|
/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]*\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/,
|
|
1886
1987
|
{
|
|
1887
1988
|
message: "Not a valid compact jwe"
|
|
1888
1989
|
}
|
|
1889
1990
|
);
|
|
1890
1991
|
|
|
1992
|
+
// src/jar/create-jar-request.ts
|
|
1993
|
+
import { addSecondsToDate as addSecondsToDate7, dateToSeconds as dateToSeconds8 } from "@pagopa/io-wallet-utils";
|
|
1994
|
+
async function createJarRequest(options) {
|
|
1995
|
+
const {
|
|
1996
|
+
authorizationRequestHeader,
|
|
1997
|
+
authorizationRequestPayload,
|
|
1998
|
+
callbacks,
|
|
1999
|
+
jweEncryptor,
|
|
2000
|
+
jwtSigner,
|
|
2001
|
+
requestUri
|
|
2002
|
+
} = options;
|
|
2003
|
+
let authorizationRequestJwt;
|
|
2004
|
+
let encryptionJwk;
|
|
2005
|
+
const now = options.now ?? /* @__PURE__ */ new Date();
|
|
2006
|
+
const { jwt, signerJwk } = await callbacks.signJwt(jwtSigner, {
|
|
2007
|
+
header: authorizationRequestHeader,
|
|
2008
|
+
payload: {
|
|
2009
|
+
...options.additionalJwtPayload,
|
|
2010
|
+
...authorizationRequestPayload,
|
|
2011
|
+
exp: dateToSeconds8(addSecondsToDate7(now, options.expiresInSeconds)),
|
|
2012
|
+
iat: dateToSeconds8(now)
|
|
2013
|
+
}
|
|
2014
|
+
});
|
|
2015
|
+
authorizationRequestJwt = jwt;
|
|
2016
|
+
if (jweEncryptor) {
|
|
2017
|
+
if (!callbacks.encryptJwe) {
|
|
2018
|
+
throw new Oauth2Error(
|
|
2019
|
+
"callbacks.encryptJwe is required when jweEncryptor is provided"
|
|
2020
|
+
);
|
|
2021
|
+
}
|
|
2022
|
+
const encryptionResult = await callbacks.encryptJwe(
|
|
2023
|
+
jweEncryptor,
|
|
2024
|
+
authorizationRequestJwt
|
|
2025
|
+
);
|
|
2026
|
+
authorizationRequestJwt = encryptionResult.jwe;
|
|
2027
|
+
encryptionJwk = encryptionResult.encryptionJwk;
|
|
2028
|
+
}
|
|
2029
|
+
const client_id = authorizationRequestPayload.client_id;
|
|
2030
|
+
const jarAuthorizationRequest = requestUri ? { client_id, request_uri: requestUri } : { client_id, request: authorizationRequestJwt };
|
|
2031
|
+
return {
|
|
2032
|
+
authorizationRequestJwt,
|
|
2033
|
+
encryptionJwk,
|
|
2034
|
+
jarAuthorizationRequest,
|
|
2035
|
+
signerJwk
|
|
2036
|
+
};
|
|
2037
|
+
}
|
|
2038
|
+
|
|
1891
2039
|
// src/jarm-form-post-jwt.ts
|
|
1892
2040
|
var getJwtFromFormPost = async (options) => {
|
|
1893
2041
|
const inputRegex = /<input[^<>]*>/gi;
|
|
@@ -1904,6 +2052,7 @@ var getJwtFromFormPost = async (options) => {
|
|
|
1904
2052
|
if (responseJwt) {
|
|
1905
2053
|
const jwt = responseJwt.replace(lineExpressionRegex, "");
|
|
1906
2054
|
const decodedJwt = decodeJwt({
|
|
2055
|
+
errorMessagePrefix: "Error decoding JARM form post JWT:",
|
|
1907
2056
|
jwt,
|
|
1908
2057
|
payloadSchema: options.schema
|
|
1909
2058
|
});
|
|
@@ -1924,73 +2073,73 @@ var getJwtFromFormPost = async (options) => {
|
|
|
1924
2073
|
};
|
|
1925
2074
|
|
|
1926
2075
|
// src/mrtd-pop/create-mrtd-validation-jwt.ts
|
|
1927
|
-
import { dateToSeconds as
|
|
2076
|
+
import { dateToSeconds as dateToSeconds9, parseWithErrorHandling as parseWithErrorHandling8 } from "@pagopa/io-wallet-utils";
|
|
1928
2077
|
|
|
1929
2078
|
// src/mrtd-pop/z-mrtd-pop.ts
|
|
1930
|
-
import
|
|
1931
|
-
var zMrtdChallengeJwtHeader =
|
|
1932
|
-
alg:
|
|
1933
|
-
kid:
|
|
1934
|
-
typ:
|
|
2079
|
+
import z15 from "zod";
|
|
2080
|
+
var zMrtdChallengeJwtHeader = z15.looseObject({
|
|
2081
|
+
alg: z15.string(),
|
|
2082
|
+
kid: z15.string(),
|
|
2083
|
+
typ: z15.literal("mrtd-ias+jwt")
|
|
1935
2084
|
});
|
|
1936
|
-
var zMrtdChallengeJwtPayload =
|
|
1937
|
-
aud:
|
|
1938
|
-
exp:
|
|
1939
|
-
htm:
|
|
1940
|
-
htu:
|
|
1941
|
-
iat:
|
|
1942
|
-
iss:
|
|
1943
|
-
mrtd_auth_session:
|
|
1944
|
-
mrtd_pop_jwt_nonce:
|
|
1945
|
-
state:
|
|
1946
|
-
status:
|
|
1947
|
-
type:
|
|
2085
|
+
var zMrtdChallengeJwtPayload = z15.looseObject({
|
|
2086
|
+
aud: z15.string(),
|
|
2087
|
+
exp: z15.number(),
|
|
2088
|
+
htm: z15.literal("POST"),
|
|
2089
|
+
htu: z15.url(),
|
|
2090
|
+
iat: z15.number(),
|
|
2091
|
+
iss: z15.string(),
|
|
2092
|
+
mrtd_auth_session: z15.string(),
|
|
2093
|
+
mrtd_pop_jwt_nonce: z15.string(),
|
|
2094
|
+
state: z15.string(),
|
|
2095
|
+
status: z15.literal("require_interaction"),
|
|
2096
|
+
type: z15.literal("mrtd+ias")
|
|
1948
2097
|
});
|
|
1949
|
-
var zMrtdPopInitResponseJwtHeader =
|
|
1950
|
-
alg:
|
|
1951
|
-
kid:
|
|
1952
|
-
typ:
|
|
2098
|
+
var zMrtdPopInitResponseJwtHeader = z15.looseObject({
|
|
2099
|
+
alg: z15.string(),
|
|
2100
|
+
kid: z15.string(),
|
|
2101
|
+
typ: z15.literal("mrtd-ias-pop+jwt")
|
|
1953
2102
|
});
|
|
1954
|
-
var zMrtdPopInitResponseJwtPayload =
|
|
1955
|
-
aud:
|
|
1956
|
-
challenge:
|
|
1957
|
-
exp:
|
|
1958
|
-
htm:
|
|
1959
|
-
htu:
|
|
1960
|
-
iat:
|
|
1961
|
-
iss:
|
|
1962
|
-
mrtd_pop_nonce:
|
|
1963
|
-
mrz:
|
|
2103
|
+
var zMrtdPopInitResponseJwtPayload = z15.looseObject({
|
|
2104
|
+
aud: z15.string(),
|
|
2105
|
+
challenge: z15.string(),
|
|
2106
|
+
exp: z15.number(),
|
|
2107
|
+
htm: z15.literal("POST"),
|
|
2108
|
+
htu: z15.url(),
|
|
2109
|
+
iat: z15.number(),
|
|
2110
|
+
iss: z15.string(),
|
|
2111
|
+
mrtd_pop_nonce: z15.string(),
|
|
2112
|
+
mrz: z15.string().optional()
|
|
1964
2113
|
});
|
|
1965
|
-
var zMrtdData =
|
|
1966
|
-
dg1:
|
|
1967
|
-
dg11:
|
|
1968
|
-
sod_mrtd:
|
|
2114
|
+
var zMrtdData = z15.looseObject({
|
|
2115
|
+
dg1: z15.string(),
|
|
2116
|
+
dg11: z15.string(),
|
|
2117
|
+
sod_mrtd: z15.string()
|
|
1969
2118
|
});
|
|
1970
|
-
var zIasData =
|
|
1971
|
-
challenge_signed:
|
|
1972
|
-
ias_pk:
|
|
1973
|
-
sod_ias:
|
|
2119
|
+
var zIasData = z15.looseObject({
|
|
2120
|
+
challenge_signed: z15.string(),
|
|
2121
|
+
ias_pk: z15.string(),
|
|
2122
|
+
sod_ias: z15.string()
|
|
1974
2123
|
});
|
|
1975
|
-
var zMrtdValidationJwtHeader =
|
|
1976
|
-
alg:
|
|
1977
|
-
kid:
|
|
1978
|
-
typ:
|
|
2124
|
+
var zMrtdValidationJwtHeader = z15.looseObject({
|
|
2125
|
+
alg: z15.string(),
|
|
2126
|
+
kid: z15.string(),
|
|
2127
|
+
typ: z15.literal("mrtd-ias+jwt")
|
|
1979
2128
|
});
|
|
1980
|
-
var zMrtdValidationJwtPayload =
|
|
1981
|
-
aud:
|
|
1982
|
-
document_type:
|
|
1983
|
-
exp:
|
|
2129
|
+
var zMrtdValidationJwtPayload = z15.looseObject({
|
|
2130
|
+
aud: z15.string(),
|
|
2131
|
+
document_type: z15.literal("cie"),
|
|
2132
|
+
exp: z15.number(),
|
|
1984
2133
|
ias: zIasData,
|
|
1985
|
-
iat:
|
|
1986
|
-
iss:
|
|
2134
|
+
iat: z15.number(),
|
|
2135
|
+
iss: z15.string(),
|
|
1987
2136
|
mrtd: zMrtdData
|
|
1988
2137
|
});
|
|
1989
|
-
var zMrtdPopVerifyResponse =
|
|
1990
|
-
mrtd_val_pop_nonce:
|
|
1991
|
-
redirect_uri:
|
|
1992
|
-
status:
|
|
1993
|
-
type:
|
|
2138
|
+
var zMrtdPopVerifyResponse = z15.looseObject({
|
|
2139
|
+
mrtd_val_pop_nonce: z15.string(),
|
|
2140
|
+
redirect_uri: z15.url(),
|
|
2141
|
+
status: z15.literal("require_interaction"),
|
|
2142
|
+
type: z15.literal("redirect_to_web")
|
|
1994
2143
|
});
|
|
1995
2144
|
|
|
1996
2145
|
// src/mrtd-pop/create-mrtd-validation-jwt.ts
|
|
@@ -2001,7 +2150,7 @@ async function createMrtdValidationJwt(options) {
|
|
|
2001
2150
|
if (!kid) {
|
|
2002
2151
|
throw new MrtdPopError("Signer must have a publicJwk.kid property");
|
|
2003
2152
|
}
|
|
2004
|
-
const iat =
|
|
2153
|
+
const iat = dateToSeconds9(options.issuedAt);
|
|
2005
2154
|
const header = parseWithErrorHandling8(zMrtdValidationJwtHeader, {
|
|
2006
2155
|
alg: options.signer.alg,
|
|
2007
2156
|
kid,
|
|
@@ -2048,7 +2197,7 @@ import {
|
|
|
2048
2197
|
CONTENT_TYPES as CONTENT_TYPES3,
|
|
2049
2198
|
HEADERS as HEADERS3,
|
|
2050
2199
|
UnexpectedStatusCodeError as UnexpectedStatusCodeError4,
|
|
2051
|
-
ValidationError as
|
|
2200
|
+
ValidationError as ValidationError7,
|
|
2052
2201
|
createFetcher as createFetcher4,
|
|
2053
2202
|
hasStatusOrThrow as hasStatusOrThrow4
|
|
2054
2203
|
} from "@pagopa/io-wallet-utils";
|
|
@@ -2070,6 +2219,7 @@ async function fetchMrtdPopInit(options) {
|
|
|
2070
2219
|
await hasStatusOrThrow4(202, UnexpectedStatusCodeError4)(response);
|
|
2071
2220
|
const responseJwt = await response.text();
|
|
2072
2221
|
const jwt = decodeJwt({
|
|
2222
|
+
errorMessagePrefix: "Error decoding MRTD PoP init response JWT:",
|
|
2073
2223
|
headerSchema: zMrtdPopInitResponseJwtHeader,
|
|
2074
2224
|
jwt: responseJwt,
|
|
2075
2225
|
payloadSchema: zMrtdPopInitResponseJwtPayload
|
|
@@ -2090,7 +2240,7 @@ async function fetchMrtdPopInit(options) {
|
|
|
2090
2240
|
signer
|
|
2091
2241
|
};
|
|
2092
2242
|
} catch (error) {
|
|
2093
|
-
if (error instanceof UnexpectedStatusCodeError4 || error instanceof
|
|
2243
|
+
if (error instanceof UnexpectedStatusCodeError4 || error instanceof ValidationError7) {
|
|
2094
2244
|
throw error;
|
|
2095
2245
|
}
|
|
2096
2246
|
throw new MrtdPopError(
|
|
@@ -2104,7 +2254,7 @@ import {
|
|
|
2104
2254
|
CONTENT_TYPES as CONTENT_TYPES4,
|
|
2105
2255
|
HEADERS as HEADERS4,
|
|
2106
2256
|
UnexpectedStatusCodeError as UnexpectedStatusCodeError5,
|
|
2107
|
-
ValidationError as
|
|
2257
|
+
ValidationError as ValidationError8,
|
|
2108
2258
|
createFetcher as createFetcher5,
|
|
2109
2259
|
hasStatusOrThrow as hasStatusOrThrow5,
|
|
2110
2260
|
parseWithErrorHandling as parseWithErrorHandling9
|
|
@@ -2136,7 +2286,7 @@ async function fetchMrtdPopVerify(options) {
|
|
|
2136
2286
|
redirectUri: parsed.redirect_uri
|
|
2137
2287
|
};
|
|
2138
2288
|
} catch (error) {
|
|
2139
|
-
if (error instanceof UnexpectedStatusCodeError5 || error instanceof
|
|
2289
|
+
if (error instanceof UnexpectedStatusCodeError5 || error instanceof ValidationError8) {
|
|
2140
2290
|
throw error;
|
|
2141
2291
|
}
|
|
2142
2292
|
throw new MrtdPopError(
|
|
@@ -2161,6 +2311,7 @@ function parseMrtdChallenge(options) {
|
|
|
2161
2311
|
);
|
|
2162
2312
|
}
|
|
2163
2313
|
const { header, payload } = decodeJwt({
|
|
2314
|
+
errorMessagePrefix: "Error decoding MRTD challenge JWT:",
|
|
2164
2315
|
headerSchema: zMrtdChallengeJwtHeader,
|
|
2165
2316
|
jwt: challengeJwt,
|
|
2166
2317
|
payloadSchema: zMrtdChallengeJwtPayload
|
|
@@ -2176,6 +2327,7 @@ import {
|
|
|
2176
2327
|
async function verifyMrtdChallenge(options) {
|
|
2177
2328
|
const { callbacks, challengeJwt, clientId } = options;
|
|
2178
2329
|
const jwt = decodeJwt({
|
|
2330
|
+
errorMessagePrefix: "Error decoding MRTD challenge JWT:",
|
|
2179
2331
|
headerSchema: zMrtdChallengeJwtHeader,
|
|
2180
2332
|
jwt: challengeJwt,
|
|
2181
2333
|
payloadSchema: zMrtdChallengeJwtPayload
|
|
@@ -2209,14 +2361,13 @@ export {
|
|
|
2209
2361
|
CreateTokenResponseError,
|
|
2210
2362
|
FetchTokenResponseError,
|
|
2211
2363
|
HashAlgorithm6 as HashAlgorithm,
|
|
2364
|
+
MAX_JTI_LENGTH,
|
|
2212
2365
|
MrtdPopError,
|
|
2213
2366
|
Oauth2Error,
|
|
2214
2367
|
Oauth2JwtParseError3 as Oauth2JwtParseError,
|
|
2215
2368
|
PkceCodeChallengeMethod,
|
|
2216
2369
|
PushedAuthorizationRequestError,
|
|
2217
2370
|
SupportedClientAuthenticationMethod,
|
|
2218
|
-
v1_exports as V1_0,
|
|
2219
|
-
v1_exports2 as V1_3,
|
|
2220
2371
|
authorizationCodeGrantIdentifier,
|
|
2221
2372
|
clientAuthenticationAnonymous,
|
|
2222
2373
|
clientAuthenticationWalletAttestationJwt,
|
|
@@ -2228,6 +2379,9 @@ export {
|
|
|
2228
2379
|
createPushedAuthorizationRequest,
|
|
2229
2380
|
createTokenDPoP,
|
|
2230
2381
|
createTokenRequest,
|
|
2382
|
+
createWalletAttestationJwt as createWalletAttestationJwtV1_0,
|
|
2383
|
+
createWalletAttestationJwt2 as createWalletAttestationJwtV1_3,
|
|
2384
|
+
createWalletAttestationJwt3 as createWalletAttestationJwtV1_4,
|
|
2231
2385
|
decodeJwt,
|
|
2232
2386
|
decodeJwtHeader,
|
|
2233
2387
|
extractClientAttestationJwtsFromHeaders,
|
|
@@ -2264,7 +2418,10 @@ export {
|
|
|
2264
2418
|
verifyPkce,
|
|
2265
2419
|
verifyPushedAuthorizationRequest,
|
|
2266
2420
|
verifyTokenDPoP,
|
|
2267
|
-
|
|
2421
|
+
verifyWalletAttestationJwt4 as verifyWalletAttestationJwt,
|
|
2422
|
+
verifyWalletAttestationJwt as verifyWalletAttestationJwtV1_0,
|
|
2423
|
+
verifyWalletAttestationJwt2 as verifyWalletAttestationJwtV1_3,
|
|
2424
|
+
verifyWalletAttestationJwt3 as verifyWalletAttestationJwtV1_4,
|
|
2268
2425
|
zAccessTokenProfileJwtHeader,
|
|
2269
2426
|
zAccessTokenProfileJwtPayload,
|
|
2270
2427
|
zAccessTokenRequest,
|
|
@@ -2297,6 +2454,15 @@ export {
|
|
|
2297
2454
|
zPushedAuthorizationResponse,
|
|
2298
2455
|
zRefreshTokenGrantIdentifier,
|
|
2299
2456
|
zSignedAuthorizationRequestJwtHeaderTyp,
|
|
2300
|
-
zTrustChain
|
|
2457
|
+
zTrustChain,
|
|
2458
|
+
zWalletAttestationJwtHeaderV1_0,
|
|
2459
|
+
zWalletAttestationJwtHeaderV1_3,
|
|
2460
|
+
zWalletAttestationJwtHeaderV1_4,
|
|
2461
|
+
zWalletAttestationJwtPayloadV1_0,
|
|
2462
|
+
zWalletAttestationJwtPayloadV1_3,
|
|
2463
|
+
zWalletAttestationJwtPayloadV1_4,
|
|
2464
|
+
zWalletAttestationJwtV1_0,
|
|
2465
|
+
zWalletAttestationJwtV1_3,
|
|
2466
|
+
zWalletAttestationJwtV1_4
|
|
2301
2467
|
};
|
|
2302
2468
|
//# sourceMappingURL=index.mjs.map
|