@openid4vc/openid4vp 0.3.0-alpha-20250307131618 → 0.3.0-alpha-20250315153009
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 +11394 -7826
- package/dist/index.d.ts +11394 -7826
- package/dist/index.js +410 -443
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +383 -417
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -11,140 +11,48 @@ var zClientIdScheme = z.enum([
|
|
|
11
11
|
"web-origin"
|
|
12
12
|
]);
|
|
13
13
|
|
|
14
|
-
// src/jarm/jarm-
|
|
14
|
+
// src/jarm/jarm-authorization-response/verify-jarm-authorization-response.ts
|
|
15
15
|
import {
|
|
16
|
-
Oauth2Error as
|
|
16
|
+
Oauth2Error as Oauth2Error3,
|
|
17
17
|
decodeJwt,
|
|
18
|
-
decodeJwtHeader,
|
|
19
18
|
jwtSignerFromJwt,
|
|
20
19
|
zCompactJwe,
|
|
21
20
|
zCompactJwt,
|
|
22
21
|
zJwtHeader as zJwtHeader2
|
|
23
22
|
} from "@openid4vc/oauth2";
|
|
24
|
-
import
|
|
25
|
-
|
|
26
|
-
// src/jarm/jarm-auth-response/jarm-validate-auth-response.ts
|
|
27
|
-
import { Oauth2Error } from "@openid4vc/oauth2";
|
|
28
|
-
import { dateToSeconds } from "@openid4vc/utils";
|
|
29
|
-
|
|
30
|
-
// src/jarm/jarm-auth-response/z-jarm-auth-response.ts
|
|
31
|
-
import { zJwtHeader, zJwtPayload } from "@openid4vc/oauth2";
|
|
32
|
-
import { z as z2 } from "zod";
|
|
33
|
-
var zJarmHeader = z2.object({ ...zJwtHeader.shape, apu: z2.string().optional(), apv: z2.string().optional() });
|
|
34
|
-
var zJarmAuthResponse = z2.object({
|
|
35
|
-
/**
|
|
36
|
-
* iss: The issuer URL of the authorization server that created the response
|
|
37
|
-
* aud: The client_id of the client the response is intended for
|
|
38
|
-
* exp: The expiration time of the JWT. A maximum JWT lifetime of 10 minutes is RECOMMENDED.
|
|
39
|
-
*/
|
|
40
|
-
...zJwtPayload.shape,
|
|
41
|
-
...zJwtPayload.pick({ iss: true, aud: true, exp: true }).required().shape,
|
|
42
|
-
state: z2.optional(z2.string())
|
|
43
|
-
}).passthrough();
|
|
44
|
-
var zJarmAuthResponseEncryptedOnly = z2.object({
|
|
45
|
-
...zJwtPayload.shape,
|
|
46
|
-
state: z2.optional(z2.string())
|
|
47
|
-
}).passthrough();
|
|
48
|
-
|
|
49
|
-
// src/jarm/jarm-auth-response/jarm-validate-auth-response.ts
|
|
50
|
-
var jarmAuthResponseValidate = (options) => {
|
|
51
|
-
const { clientId, authorizationResponse } = options;
|
|
52
|
-
if (!zJarmAuthResponse.safeParse(authorizationResponse).success) {
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
if (clientId !== authorizationResponse.aud) {
|
|
56
|
-
throw new Oauth2Error(
|
|
57
|
-
`Invalid 'aud' claim in JARM authorization response. Expected '${clientId}' received '${JSON.stringify(authorizationResponse.aud)}'.`
|
|
58
|
-
);
|
|
59
|
-
}
|
|
60
|
-
if (authorizationResponse.exp !== void 0 && authorizationResponse.exp < dateToSeconds()) {
|
|
61
|
-
throw new Oauth2Error("Jarm auth response is expired.");
|
|
62
|
-
}
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
// src/jarm/jarm-auth-response/verify-jarm-auth-response.ts
|
|
66
|
-
var decryptJarmRequestData = async (options) => {
|
|
67
|
-
const { requestData, callbacks } = options;
|
|
68
|
-
const { header } = decodeJwtHeader({ jwt: requestData });
|
|
69
|
-
if (!header.kid) {
|
|
70
|
-
throw new Oauth2Error2('Jarm JWE is missing the protected header field "kid".');
|
|
71
|
-
}
|
|
72
|
-
const result = await callbacks.decryptJwe(requestData);
|
|
73
|
-
if (!result.decrypted) {
|
|
74
|
-
throw new Oauth2Error2("Failed to decrypt jarm auth response.");
|
|
75
|
-
}
|
|
76
|
-
return result.payload;
|
|
77
|
-
};
|
|
78
|
-
async function verifyJarmAuthorizationResponse(options) {
|
|
79
|
-
const { jarmAuthorizationResponseJwt, callbacks } = options;
|
|
80
|
-
const requestDataIsEncrypted = zCompactJwe.safeParse(jarmAuthorizationResponseJwt).success;
|
|
81
|
-
const decryptedRequestData = requestDataIsEncrypted ? await decryptJarmRequestData({ requestData: jarmAuthorizationResponseJwt, callbacks }) : jarmAuthorizationResponseJwt;
|
|
82
|
-
const responseIsSigned = zCompactJwt.safeParse(decryptedRequestData).success;
|
|
83
|
-
if (!requestDataIsEncrypted && !responseIsSigned) {
|
|
84
|
-
throw new Oauth2Error2("Jarm Auth Response must be either encrypted, signed, or signed and encrypted.");
|
|
85
|
-
}
|
|
86
|
-
let jarmAuthResponse;
|
|
87
|
-
if (responseIsSigned) {
|
|
88
|
-
const { header: jwsProtectedHeader, payload: jwsPayload } = decodeJwt({
|
|
89
|
-
jwt: decryptedRequestData,
|
|
90
|
-
headerSchema: z3.object({ ...zJwtHeader2.shape, kid: z3.string() })
|
|
91
|
-
});
|
|
92
|
-
const response = zJarmAuthResponse.parse(jwsPayload);
|
|
93
|
-
const jwtSigner = jwtSignerFromJwt({ header: jwsProtectedHeader, payload: jwsPayload });
|
|
94
|
-
const verificationResult = await options.callbacks.verifyJwt(jwtSigner, {
|
|
95
|
-
compact: decryptedRequestData,
|
|
96
|
-
header: jwsProtectedHeader,
|
|
97
|
-
payload: jwsPayload
|
|
98
|
-
});
|
|
99
|
-
if (!verificationResult.verified) {
|
|
100
|
-
throw new Oauth2Error2("Jarm Auth Response is not valid.");
|
|
101
|
-
}
|
|
102
|
-
jarmAuthResponse = response;
|
|
103
|
-
} else {
|
|
104
|
-
const jsonRequestData = JSON.parse(decryptedRequestData);
|
|
105
|
-
jarmAuthResponse = zJarmAuthResponseEncryptedOnly.parse(jsonRequestData);
|
|
106
|
-
}
|
|
107
|
-
const { authorizationRequest } = await callbacks.getOpenid4vpAuthorizationRequest(jarmAuthResponse);
|
|
108
|
-
jarmAuthResponseValidate({
|
|
109
|
-
clientId: authorizationRequest.client_id,
|
|
110
|
-
authorizationResponse: jarmAuthResponse
|
|
111
|
-
});
|
|
112
|
-
const type = requestDataIsEncrypted && responseIsSigned ? "SignedEncrypted" /* SignedEncrypted */ : requestDataIsEncrypted ? "Encrypted" /* Encrypted */ : "Signed" /* Signed */;
|
|
113
|
-
const issuer = jarmAuthResponse.iss;
|
|
114
|
-
return { authorizationRequest, jarmAuthResponse, type, issuer };
|
|
115
|
-
}
|
|
23
|
+
import z4 from "zod";
|
|
116
24
|
|
|
117
25
|
// src/jarm/metadata/z-jarm-client-metadata.ts
|
|
118
|
-
import { Oauth2Error
|
|
26
|
+
import { Oauth2Error, zAlgValueNotNone } from "@openid4vc/oauth2";
|
|
119
27
|
import { parseWithErrorHandling } from "@openid4vc/utils";
|
|
120
|
-
import { z as
|
|
121
|
-
var zJarmSignOnlyClientMetadata =
|
|
28
|
+
import { z as z2 } from "zod";
|
|
29
|
+
var zJarmSignOnlyClientMetadata = z2.object({
|
|
122
30
|
authorization_signed_response_alg: zAlgValueNotNone,
|
|
123
|
-
authorization_encrypted_response_alg:
|
|
124
|
-
authorization_encrypted_response_enc:
|
|
31
|
+
authorization_encrypted_response_alg: z2.optional(z2.never()),
|
|
32
|
+
authorization_encrypted_response_enc: z2.optional(z2.never())
|
|
125
33
|
});
|
|
126
|
-
var zJarmEncryptOnlyClientMetadata =
|
|
127
|
-
authorization_signed_response_alg:
|
|
128
|
-
authorization_encrypted_response_alg:
|
|
129
|
-
authorization_encrypted_response_enc:
|
|
34
|
+
var zJarmEncryptOnlyClientMetadata = z2.object({
|
|
35
|
+
authorization_signed_response_alg: z2.optional(z2.never()),
|
|
36
|
+
authorization_encrypted_response_alg: z2.string(),
|
|
37
|
+
authorization_encrypted_response_enc: z2.optional(z2.string())
|
|
130
38
|
});
|
|
131
|
-
var zJarmSignEncryptClientMetadata =
|
|
39
|
+
var zJarmSignEncryptClientMetadata = z2.object({
|
|
132
40
|
authorization_signed_response_alg: zJarmSignOnlyClientMetadata.shape.authorization_signed_response_alg,
|
|
133
41
|
authorization_encrypted_response_alg: zJarmEncryptOnlyClientMetadata.shape.authorization_encrypted_response_alg,
|
|
134
42
|
authorization_encrypted_response_enc: zJarmEncryptOnlyClientMetadata.shape.authorization_encrypted_response_enc
|
|
135
43
|
});
|
|
136
|
-
var zJarmClientMetadata =
|
|
137
|
-
authorization_signed_response_alg:
|
|
138
|
-
authorization_encrypted_response_alg:
|
|
44
|
+
var zJarmClientMetadata = z2.object({
|
|
45
|
+
authorization_signed_response_alg: z2.optional(zJarmSignOnlyClientMetadata.shape.authorization_signed_response_alg),
|
|
46
|
+
authorization_encrypted_response_alg: z2.optional(
|
|
139
47
|
zJarmEncryptOnlyClientMetadata.shape.authorization_encrypted_response_alg
|
|
140
48
|
),
|
|
141
|
-
authorization_encrypted_response_enc:
|
|
49
|
+
authorization_encrypted_response_enc: z2.optional(
|
|
142
50
|
zJarmEncryptOnlyClientMetadata.shape.authorization_encrypted_response_enc
|
|
143
51
|
)
|
|
144
52
|
});
|
|
145
53
|
var zJarmClientMetadataParsed = zJarmClientMetadata.transform((client_metadata) => {
|
|
146
54
|
const parsedClientMeta = parseWithErrorHandling(
|
|
147
|
-
|
|
55
|
+
z2.union([zJarmEncryptOnlyClientMetadata, zJarmSignOnlyClientMetadata, zJarmSignEncryptClientMetadata]),
|
|
148
56
|
client_metadata,
|
|
149
57
|
"Invalid jarm client metadata."
|
|
150
58
|
);
|
|
@@ -178,34 +86,140 @@ var zJarmClientMetadataParsed = zJarmClientMetadata.transform((client_metadata)
|
|
|
178
86
|
}
|
|
179
87
|
};
|
|
180
88
|
}
|
|
181
|
-
throw new
|
|
89
|
+
throw new Oauth2Error("Invalid jarm client metadata. Failed to parse.");
|
|
182
90
|
});
|
|
183
91
|
|
|
92
|
+
// src/jarm/jarm-extract-jwks.ts
|
|
93
|
+
function extractJwksFromClientMetadata(clientMetadata) {
|
|
94
|
+
const parsed = zJarmClientMetadataParsed.parse(clientMetadata);
|
|
95
|
+
const encryptionAlg = parsed.client_metadata.authorization_encrypted_response_enc;
|
|
96
|
+
const signingAlg = parsed.client_metadata.authorization_signed_response_alg;
|
|
97
|
+
const encJwk = clientMetadata.jwks.keys.find((key) => key.use === "enc" && key.alg === encryptionAlg) ?? clientMetadata.jwks.keys.find((key) => key.use === "enc") ?? // fallback, take first key. HAIP does not specify requirement on enc
|
|
98
|
+
clientMetadata.jwks.keys?.[0];
|
|
99
|
+
const sigJwk = clientMetadata.jwks.keys.find((key) => key.use === "sig" && key.alg === signingAlg) ?? clientMetadata.jwks.keys.find((key) => key.use === "sig") ?? // falback, take first key
|
|
100
|
+
clientMetadata.jwks.keys?.[0];
|
|
101
|
+
return { encJwk, sigJwk };
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// src/jarm/jarm-authorization-response/jarm-validate-authorization-response.ts
|
|
105
|
+
import { Oauth2Error as Oauth2Error2 } from "@openid4vc/oauth2";
|
|
106
|
+
import { dateToSeconds } from "@openid4vc/utils";
|
|
107
|
+
|
|
108
|
+
// src/jarm/jarm-authorization-response/z-jarm-authorization-response.ts
|
|
109
|
+
import { zJwtHeader, zJwtPayload } from "@openid4vc/oauth2";
|
|
110
|
+
import { z as z3 } from "zod";
|
|
111
|
+
var zJarmHeader = z3.object({ ...zJwtHeader.shape, apu: z3.string().optional(), apv: z3.string().optional() });
|
|
112
|
+
var zJarmAuthorizationResponse = z3.object({
|
|
113
|
+
/**
|
|
114
|
+
* iss: The issuer URL of the authorization server that created the response
|
|
115
|
+
* aud: The client_id of the client the response is intended for
|
|
116
|
+
* exp: The expiration time of the JWT. A maximum JWT lifetime of 10 minutes is RECOMMENDED.
|
|
117
|
+
*/
|
|
118
|
+
...zJwtPayload.shape,
|
|
119
|
+
...zJwtPayload.pick({ iss: true, aud: true, exp: true }).required().shape,
|
|
120
|
+
state: z3.optional(z3.string())
|
|
121
|
+
}).passthrough();
|
|
122
|
+
var zJarmAuthorizationResponseEncryptedOnly = z3.object({
|
|
123
|
+
...zJwtPayload.shape,
|
|
124
|
+
state: z3.optional(z3.string())
|
|
125
|
+
}).passthrough();
|
|
126
|
+
|
|
127
|
+
// src/jarm/jarm-authorization-response/jarm-validate-authorization-response.ts
|
|
128
|
+
var jarmAuthorizationResponseValidate = (options) => {
|
|
129
|
+
const { expectedClientId, authorizationResponse } = options;
|
|
130
|
+
if (!zJarmAuthorizationResponse.safeParse(authorizationResponse).success) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
if (expectedClientId !== authorizationResponse.aud) {
|
|
134
|
+
throw new Oauth2Error2(
|
|
135
|
+
`Invalid 'aud' claim in JARM authorization response. Expected '${expectedClientId}' received '${JSON.stringify(authorizationResponse.aud)}'.`
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
if (authorizationResponse.exp !== void 0 && authorizationResponse.exp < dateToSeconds()) {
|
|
139
|
+
throw new Oauth2Error2("Jarm auth response is expired.");
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
// src/jarm/jarm-authorization-response/verify-jarm-authorization-response.ts
|
|
144
|
+
var decryptJarmAuthorizationResponseJwt = async (options) => {
|
|
145
|
+
const { jarmAuthorizationResponseJwt, callbacks, authorizationRequestPayload } = options;
|
|
146
|
+
const encryptionJwk = authorizationRequestPayload.client_metadata?.jwks ? extractJwksFromClientMetadata({
|
|
147
|
+
...authorizationRequestPayload.client_metadata,
|
|
148
|
+
jwks: authorizationRequestPayload.client_metadata.jwks
|
|
149
|
+
}).encJwk : void 0;
|
|
150
|
+
const result = await callbacks.decryptJwe(jarmAuthorizationResponseJwt, { jwk: encryptionJwk });
|
|
151
|
+
if (!result.decrypted) {
|
|
152
|
+
throw new Oauth2Error3("Failed to decrypt jarm auth response.");
|
|
153
|
+
}
|
|
154
|
+
return result.payload;
|
|
155
|
+
};
|
|
156
|
+
async function verifyJarmAuthorizationResponse(options) {
|
|
157
|
+
const { jarmAuthorizationResponseJwt, callbacks, expectedClientId, authorizationRequestPayload } = options;
|
|
158
|
+
const requestDataIsEncrypted = zCompactJwe.safeParse(jarmAuthorizationResponseJwt).success;
|
|
159
|
+
const decryptedRequestData = requestDataIsEncrypted ? await decryptJarmAuthorizationResponseJwt({
|
|
160
|
+
jarmAuthorizationResponseJwt,
|
|
161
|
+
callbacks,
|
|
162
|
+
authorizationRequestPayload
|
|
163
|
+
}) : jarmAuthorizationResponseJwt;
|
|
164
|
+
const responseIsSigned = zCompactJwt.safeParse(decryptedRequestData).success;
|
|
165
|
+
if (!requestDataIsEncrypted && !responseIsSigned) {
|
|
166
|
+
throw new Oauth2Error3("Jarm Auth Response must be either encrypted, signed, or signed and encrypted.");
|
|
167
|
+
}
|
|
168
|
+
let jarmAuthorizationResponse;
|
|
169
|
+
if (responseIsSigned) {
|
|
170
|
+
const { header: jwsProtectedHeader, payload: jwsPayload } = decodeJwt({
|
|
171
|
+
jwt: decryptedRequestData,
|
|
172
|
+
headerSchema: z4.object({ ...zJwtHeader2.shape, kid: z4.string() })
|
|
173
|
+
});
|
|
174
|
+
const response = zJarmAuthorizationResponse.parse(jwsPayload);
|
|
175
|
+
const jwtSigner = jwtSignerFromJwt({ header: jwsProtectedHeader, payload: jwsPayload });
|
|
176
|
+
const verificationResult = await options.callbacks.verifyJwt(jwtSigner, {
|
|
177
|
+
compact: decryptedRequestData,
|
|
178
|
+
header: jwsProtectedHeader,
|
|
179
|
+
payload: jwsPayload
|
|
180
|
+
});
|
|
181
|
+
if (!verificationResult.verified) {
|
|
182
|
+
throw new Oauth2Error3("Jarm Auth Response is not valid.");
|
|
183
|
+
}
|
|
184
|
+
jarmAuthorizationResponse = response;
|
|
185
|
+
} else {
|
|
186
|
+
const jsonRequestData = JSON.parse(decryptedRequestData);
|
|
187
|
+
jarmAuthorizationResponse = zJarmAuthorizationResponseEncryptedOnly.parse(jsonRequestData);
|
|
188
|
+
}
|
|
189
|
+
jarmAuthorizationResponseValidate({
|
|
190
|
+
expectedClientId,
|
|
191
|
+
authorizationResponse: jarmAuthorizationResponse
|
|
192
|
+
});
|
|
193
|
+
const type = requestDataIsEncrypted && responseIsSigned ? "SignedEncrypted" /* SignedEncrypted */ : requestDataIsEncrypted ? "Encrypted" /* Encrypted */ : "Signed" /* Signed */;
|
|
194
|
+
const issuer = jarmAuthorizationResponse.iss;
|
|
195
|
+
return { jarmAuthorizationResponse, type, issuer };
|
|
196
|
+
}
|
|
197
|
+
|
|
184
198
|
// src/authorization-request/create-authorization-request.ts
|
|
185
199
|
import { Oauth2Error as Oauth2Error4 } from "@openid4vc/oauth2";
|
|
186
200
|
import { URL, URLSearchParams, objectToQueryParams, parseWithErrorHandling as parseWithErrorHandling2 } from "@openid4vc/utils";
|
|
187
201
|
|
|
188
|
-
// src/jar/create-jar-
|
|
202
|
+
// src/jar/create-jar-authorization-request.ts
|
|
189
203
|
import {
|
|
190
204
|
jwtHeaderFromJwtSigner
|
|
191
205
|
} from "@openid4vc/oauth2";
|
|
192
|
-
async function
|
|
193
|
-
const { jwtSigner, jweEncryptor,
|
|
194
|
-
let
|
|
206
|
+
async function createJarAuthorizationRequest(options) {
|
|
207
|
+
const { jwtSigner, jweEncryptor, authorizationRequestPayload, requestUri, callbacks } = options;
|
|
208
|
+
let authorizationRequestJwt;
|
|
195
209
|
let encryptionJwk;
|
|
196
210
|
const { jwt, signerJwk } = await callbacks.signJwt(jwtSigner, {
|
|
197
211
|
header: { ...jwtHeaderFromJwtSigner(jwtSigner), typ: "oauth-authz-req+jwt" },
|
|
198
|
-
payload: { ...options.additionalJwtPayload, ...
|
|
212
|
+
payload: { ...options.additionalJwtPayload, ...authorizationRequestPayload }
|
|
199
213
|
});
|
|
200
|
-
|
|
214
|
+
authorizationRequestJwt = jwt;
|
|
201
215
|
if (jweEncryptor) {
|
|
202
|
-
const encryptionResult = await callbacks.encryptJwe(jweEncryptor,
|
|
203
|
-
|
|
216
|
+
const encryptionResult = await callbacks.encryptJwe(jweEncryptor, authorizationRequestJwt);
|
|
217
|
+
authorizationRequestJwt = encryptionResult.jwe;
|
|
204
218
|
encryptionJwk = encryptionResult.encryptionJwk;
|
|
205
219
|
}
|
|
206
|
-
const client_id =
|
|
207
|
-
const
|
|
208
|
-
return {
|
|
220
|
+
const client_id = authorizationRequestPayload.client_id;
|
|
221
|
+
const jarAuthorizationRequest = requestUri ? { client_id, request_uri: requestUri } : { client_id, request: authorizationRequestJwt };
|
|
222
|
+
return { jarAuthorizationRequest, signerJwk, encryptionJwk, authorizationRequestJwt };
|
|
209
223
|
}
|
|
210
224
|
|
|
211
225
|
// src/authorization-request/validate-authorization-request.ts
|
|
@@ -274,20 +288,20 @@ var validateOpenid4vpAuthorizationRequestPayload = (options) => {
|
|
|
274
288
|
// src/authorization-request/validate-authorization-request-dc-api.ts
|
|
275
289
|
import { Oauth2ErrorCodes as Oauth2ErrorCodes2, Oauth2ServerErrorResponseError as Oauth2ServerErrorResponseError2 } from "@openid4vc/oauth2";
|
|
276
290
|
var validateOpenid4vpAuthorizationRequestDcApiPayload = (options) => {
|
|
277
|
-
const { params, isJarRequest,
|
|
291
|
+
const { params, isJarRequest, disableOriginValidation, origin } = options;
|
|
278
292
|
if (isJarRequest && !params.expected_origins) {
|
|
279
293
|
throw new Oauth2ServerErrorResponseError2({
|
|
280
294
|
error: Oauth2ErrorCodes2.InvalidRequest,
|
|
281
295
|
error_description: `The 'expected_origins' parameter MUST be present when using the dc_api response mode in combinaction with jar.`
|
|
282
296
|
});
|
|
283
297
|
}
|
|
284
|
-
if ([params.presentation_definition, params.dcql_query].filter(Boolean).length
|
|
298
|
+
if ([params.presentation_definition, params.dcql_query].filter(Boolean).length !== 1) {
|
|
285
299
|
throw new Oauth2ServerErrorResponseError2({
|
|
286
300
|
error: Oauth2ErrorCodes2.InvalidRequest,
|
|
287
|
-
error_description: "Exactly one of the following parameters MUST be present in the Authorization Request: dcql_query
|
|
301
|
+
error_description: "Exactly one of the following parameters MUST be present in the Authorization Request: dcql_query or presentation_definition"
|
|
288
302
|
});
|
|
289
303
|
}
|
|
290
|
-
if (params.expected_origins && !
|
|
304
|
+
if (params.expected_origins && !disableOriginValidation) {
|
|
291
305
|
if (!origin) {
|
|
292
306
|
throw new Oauth2ServerErrorResponseError2({
|
|
293
307
|
error: Oauth2ErrorCodes2.InvalidRequest,
|
|
@@ -371,7 +385,8 @@ var zOpenid4vpAuthorizationRequestDcApi = zOpenid4vpAuthorizationRequest.pick({
|
|
|
371
385
|
presentation_definition: true,
|
|
372
386
|
client_metadata: true,
|
|
373
387
|
transaction_data: true,
|
|
374
|
-
dcql_query: true
|
|
388
|
+
dcql_query: true,
|
|
389
|
+
trust_chain: true
|
|
375
390
|
}).extend({
|
|
376
391
|
client_id: z8.optional(z8.string()),
|
|
377
392
|
expected_origins: z8.array(z8.string()).optional(),
|
|
@@ -392,64 +407,67 @@ function isOpenid4vpAuthorizationRequestDcApi(request) {
|
|
|
392
407
|
|
|
393
408
|
// src/authorization-request/create-authorization-request.ts
|
|
394
409
|
async function createOpenid4vpAuthorizationRequest(options) {
|
|
395
|
-
const { jar, scheme = "openid4vp://",
|
|
410
|
+
const { jar, scheme = "openid4vp://", wallet, callbacks } = options;
|
|
396
411
|
let additionalJwtPayload;
|
|
397
|
-
let
|
|
398
|
-
if (isOpenid4vpAuthorizationRequestDcApi(
|
|
399
|
-
|
|
412
|
+
let authorizationRequestPayload;
|
|
413
|
+
if (isOpenid4vpAuthorizationRequestDcApi(options.authorizationRequestPayload)) {
|
|
414
|
+
authorizationRequestPayload = parseWithErrorHandling2(
|
|
400
415
|
zOpenid4vpAuthorizationRequestDcApi,
|
|
401
|
-
|
|
416
|
+
options.authorizationRequestPayload,
|
|
402
417
|
"Invalid authorization request. Could not parse openid4vp dc_api authorization request."
|
|
403
418
|
);
|
|
404
|
-
if (jar && !
|
|
419
|
+
if (jar && !authorizationRequestPayload.expected_origins) {
|
|
405
420
|
throw new Oauth2Error4(
|
|
406
421
|
`The 'expected_origins' parameter MUST be present when using the dc_api response mode in combination with jar.`
|
|
407
422
|
);
|
|
408
423
|
}
|
|
409
424
|
validateOpenid4vpAuthorizationRequestDcApiPayload({
|
|
410
|
-
params:
|
|
425
|
+
params: authorizationRequestPayload,
|
|
411
426
|
isJarRequest: Boolean(jar),
|
|
412
|
-
|
|
427
|
+
disableOriginValidation: true
|
|
413
428
|
});
|
|
414
429
|
} else {
|
|
415
|
-
|
|
430
|
+
authorizationRequestPayload = parseWithErrorHandling2(
|
|
416
431
|
zOpenid4vpAuthorizationRequest,
|
|
417
|
-
|
|
432
|
+
options.authorizationRequestPayload,
|
|
418
433
|
"Invalid authorization request. Could not parse openid4vp authorization request."
|
|
419
434
|
);
|
|
420
|
-
validateOpenid4vpAuthorizationRequestPayload({
|
|
435
|
+
validateOpenid4vpAuthorizationRequestPayload({
|
|
436
|
+
params: authorizationRequestPayload,
|
|
437
|
+
walletVerificationOptions: wallet
|
|
438
|
+
});
|
|
421
439
|
}
|
|
422
440
|
if (jar) {
|
|
423
441
|
if (!jar.additionalJwtPayload?.aud) {
|
|
424
442
|
additionalJwtPayload = { ...jar.additionalJwtPayload, aud: jar.requestUri };
|
|
425
443
|
}
|
|
426
|
-
|
|
427
|
-
if (jar) {
|
|
428
|
-
const jarResult = await createJarAuthRequest({
|
|
444
|
+
const jarResult = await createJarAuthorizationRequest({
|
|
429
445
|
...jar,
|
|
430
|
-
|
|
446
|
+
authorizationRequestPayload,
|
|
431
447
|
additionalJwtPayload,
|
|
432
448
|
callbacks
|
|
433
449
|
});
|
|
434
450
|
const url2 = new URL(scheme);
|
|
435
451
|
url2.search = `?${new URLSearchParams([
|
|
436
452
|
...url2.searchParams.entries(),
|
|
437
|
-
...objectToQueryParams(jarResult.
|
|
453
|
+
...objectToQueryParams(jarResult.jarAuthorizationRequest).entries()
|
|
438
454
|
]).toString()}`;
|
|
439
455
|
return {
|
|
440
|
-
|
|
441
|
-
|
|
456
|
+
authorizationRequestPayload,
|
|
457
|
+
authorizationRequestObject: jarResult.jarAuthorizationRequest,
|
|
458
|
+
authorizationRequest: url2.toString(),
|
|
442
459
|
jar: { ...jar, ...jarResult }
|
|
443
460
|
};
|
|
444
461
|
}
|
|
445
462
|
const url = new URL(scheme);
|
|
446
463
|
url.search = `?${new URLSearchParams([
|
|
447
464
|
...url.searchParams.entries(),
|
|
448
|
-
...objectToQueryParams(
|
|
465
|
+
...objectToQueryParams(authorizationRequestPayload).entries()
|
|
449
466
|
]).toString()}`;
|
|
450
467
|
return {
|
|
451
|
-
|
|
452
|
-
|
|
468
|
+
authorizationRequestPayload,
|
|
469
|
+
authorizationRequestObject: authorizationRequestPayload,
|
|
470
|
+
authorizationRequest: url.toString(),
|
|
453
471
|
jar: void 0
|
|
454
472
|
};
|
|
455
473
|
}
|
|
@@ -460,11 +478,11 @@ import { URL as URL2 } from "@openid4vc/utils";
|
|
|
460
478
|
import { parseWithErrorHandling as parseWithErrorHandling3 } from "@openid4vc/utils";
|
|
461
479
|
import z10 from "zod";
|
|
462
480
|
|
|
463
|
-
// src/jar/z-jar-
|
|
481
|
+
// src/jar/z-jar-authorization-request.ts
|
|
464
482
|
import { Oauth2ServerErrorResponseError as Oauth2ServerErrorResponseError3 } from "@openid4vc/oauth2";
|
|
465
483
|
import { zHttpsUrl as zHttpsUrl4 } from "@openid4vc/utils";
|
|
466
484
|
import { z as z9 } from "zod";
|
|
467
|
-
var
|
|
485
|
+
var zJarAuthorizationRequest = z9.object({
|
|
468
486
|
request: z9.optional(z9.string()),
|
|
469
487
|
request_uri: z9.optional(zHttpsUrl4),
|
|
470
488
|
request_uri_method: z9.optional(z9.string()),
|
|
@@ -486,7 +504,7 @@ function validateJarRequestParams(options) {
|
|
|
486
504
|
}
|
|
487
505
|
return jarRequestParams;
|
|
488
506
|
}
|
|
489
|
-
function
|
|
507
|
+
function isJarAuthorizationRequest(request) {
|
|
490
508
|
return "request" in request || "request_uri" in request;
|
|
491
509
|
}
|
|
492
510
|
|
|
@@ -509,10 +527,10 @@ function parseOpenid4vpAuthorizationRequestPayload(options) {
|
|
|
509
527
|
params = authorizationRequest;
|
|
510
528
|
}
|
|
511
529
|
const parsedRequest = parseWithErrorHandling3(
|
|
512
|
-
z10.union([zOpenid4vpAuthorizationRequest,
|
|
530
|
+
z10.union([zOpenid4vpAuthorizationRequest, zJarAuthorizationRequest, zOpenid4vpAuthorizationRequestDcApi]),
|
|
513
531
|
params
|
|
514
532
|
);
|
|
515
|
-
if (
|
|
533
|
+
if (isJarAuthorizationRequest(parsedRequest)) {
|
|
516
534
|
return {
|
|
517
535
|
type: "jar",
|
|
518
536
|
provided,
|
|
@@ -536,16 +554,16 @@ function parseOpenid4vpAuthorizationRequestPayload(options) {
|
|
|
536
554
|
// src/authorization-request/resolve-authorization-request.ts
|
|
537
555
|
import { Oauth2ErrorCodes as Oauth2ErrorCodes9, Oauth2ServerErrorResponseError as Oauth2ServerErrorResponseError10 } from "@openid4vc/oauth2";
|
|
538
556
|
import { parseWithErrorHandling as parseWithErrorHandling4 } from "@openid4vc/utils";
|
|
539
|
-
import
|
|
557
|
+
import z14 from "zod";
|
|
540
558
|
|
|
541
559
|
// src/client-identifier-scheme/parse-client-identifier-scheme.ts
|
|
542
560
|
import { Oauth2ErrorCodes as Oauth2ErrorCodes4, Oauth2ServerErrorResponseError as Oauth2ServerErrorResponseError5, getGlobalConfig } from "@openid4vc/oauth2";
|
|
561
|
+
import { URL as URL3 } from "@openid4vc/utils";
|
|
543
562
|
|
|
544
563
|
// src/version.ts
|
|
545
564
|
import { Oauth2ErrorCodes as Oauth2ErrorCodes3, Oauth2ServerErrorResponseError as Oauth2ServerErrorResponseError4 } from "@openid4vc/oauth2";
|
|
546
565
|
function parseAuthorizationRequestVersion(request) {
|
|
547
566
|
const requirements = [];
|
|
548
|
-
const vp_formats = request.client_metadata?.vp_formats;
|
|
549
567
|
if (isOpenid4vpAuthorizationRequestDcApi(request) && (request.response_mode === "w3c_dc_api" || request.response_mode === "w3c_dc_api.jwt")) {
|
|
550
568
|
requirements.push(["<", 23]);
|
|
551
569
|
requirements.push([">=", 21]);
|
|
@@ -606,70 +624,56 @@ function parseAuthorizationRequestVersion(request) {
|
|
|
606
624
|
|
|
607
625
|
// src/client-identifier-scheme/parse-client-identifier-scheme.ts
|
|
608
626
|
function getClientId(options) {
|
|
609
|
-
|
|
627
|
+
const version = parseAuthorizationRequestVersion(options.authorizationRequestPayload);
|
|
628
|
+
if (version < 22) {
|
|
629
|
+
return getLegacyClientId(options);
|
|
630
|
+
}
|
|
631
|
+
if (isOpenid4vpAuthorizationRequestDcApi(options.authorizationRequestPayload)) {
|
|
610
632
|
if (!options.origin) {
|
|
611
633
|
throw new Oauth2ServerErrorResponseError5({
|
|
612
634
|
error: Oauth2ErrorCodes4.InvalidRequest,
|
|
613
635
|
error_description: "Failed to parse client identifier. 'origin' is required for requests with response_mode 'dc_api' and 'dc_api.jwt'"
|
|
614
636
|
});
|
|
615
637
|
}
|
|
616
|
-
if (!options.jar || !options.
|
|
617
|
-
return options.
|
|
638
|
+
if (!options.jar || !options.authorizationRequestPayload.client_id) return `web-origin:${options.origin}`;
|
|
639
|
+
return options.authorizationRequestPayload.client_id;
|
|
618
640
|
}
|
|
619
|
-
return options.
|
|
641
|
+
return options.authorizationRequestPayload.client_id;
|
|
620
642
|
}
|
|
621
643
|
function getLegacyClientId(options) {
|
|
622
|
-
const legacyClientIdScheme = options.
|
|
623
|
-
|
|
624
|
-
if (
|
|
625
|
-
clientIdScheme = "https";
|
|
626
|
-
} else {
|
|
627
|
-
clientIdScheme = legacyClientIdScheme;
|
|
628
|
-
}
|
|
629
|
-
if (isOpenid4vpAuthorizationRequestDcApi(options.request)) {
|
|
644
|
+
const legacyClientIdScheme = options.authorizationRequestPayload.client_id_scheme ?? "pre-registered";
|
|
645
|
+
const clientIdScheme = legacyClientIdScheme === "entity_id" ? "https" : legacyClientIdScheme;
|
|
646
|
+
if (isOpenid4vpAuthorizationRequestDcApi(options.authorizationRequestPayload)) {
|
|
630
647
|
if (!options.origin) {
|
|
631
648
|
throw new Oauth2ServerErrorResponseError5({
|
|
632
649
|
error: Oauth2ErrorCodes4.InvalidRequest,
|
|
633
650
|
error_description: "Failed to parse client identifier. 'origin' is required for requests with response_mode 'dc_api' and 'dc_api.jwt'"
|
|
634
651
|
});
|
|
635
652
|
}
|
|
636
|
-
if (!options.jar || !options.
|
|
637
|
-
return `${clientIdScheme}:${options.
|
|
653
|
+
if (!options.jar || !options.authorizationRequestPayload.client_id) return `web-origin:${options.origin}`;
|
|
654
|
+
return `${clientIdScheme}:${options.authorizationRequestPayload.client_id}`;
|
|
638
655
|
}
|
|
639
656
|
if (clientIdScheme === "https" || clientIdScheme === "did") {
|
|
640
|
-
return options.
|
|
657
|
+
return options.authorizationRequestPayload.client_id;
|
|
641
658
|
}
|
|
642
659
|
if (clientIdScheme === "pre-registered") {
|
|
643
|
-
return options.
|
|
660
|
+
return options.authorizationRequestPayload.client_id;
|
|
644
661
|
}
|
|
645
|
-
return `${clientIdScheme}:${options.
|
|
662
|
+
return `${clientIdScheme}:${options.authorizationRequestPayload.client_id}`;
|
|
646
663
|
}
|
|
647
664
|
function parseClientIdentifier(options, parserConfig) {
|
|
648
|
-
const {
|
|
649
|
-
const version = parseAuthorizationRequestVersion(request);
|
|
650
|
-
if (version < 22) {
|
|
651
|
-
const legacyClientIdScheme = request.client_id_scheme ?? "pre-registered";
|
|
652
|
-
let clientIdSchem;
|
|
653
|
-
if (legacyClientIdScheme) {
|
|
654
|
-
if (legacyClientIdScheme === "entity_id") {
|
|
655
|
-
clientIdSchem = "https";
|
|
656
|
-
} else {
|
|
657
|
-
clientIdSchem = legacyClientIdScheme;
|
|
658
|
-
}
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
const isDcApiRequest = isOpenid4vpAuthorizationRequestDcApi(request);
|
|
662
|
-
const clientId = version < 22 ? getLegacyClientId(options) : getClientId(options);
|
|
665
|
+
const { authorizationRequestPayload, jar } = options;
|
|
663
666
|
const parserConfigWithDefaults = {
|
|
664
667
|
supportedSchemes: parserConfig?.supportedSchemes || Object.values(zClientIdScheme.options)
|
|
665
668
|
};
|
|
669
|
+
const clientId = getClientId(options);
|
|
666
670
|
const colonIndex = clientId.indexOf(":");
|
|
667
671
|
if (colonIndex === -1) {
|
|
668
672
|
return {
|
|
669
673
|
scheme: "pre-registered",
|
|
670
674
|
identifier: clientId,
|
|
671
675
|
originalValue: clientId,
|
|
672
|
-
clientMetadata:
|
|
676
|
+
clientMetadata: authorizationRequestPayload.client_metadata
|
|
673
677
|
};
|
|
674
678
|
}
|
|
675
679
|
const schemePart = clientId.substring(0, colonIndex);
|
|
@@ -682,12 +686,6 @@ function parseClientIdentifier(options, parserConfig) {
|
|
|
682
686
|
}
|
|
683
687
|
const scheme = schemePart;
|
|
684
688
|
if (scheme === "https") {
|
|
685
|
-
if (isDcApiRequest) {
|
|
686
|
-
throw new Oauth2ServerErrorResponseError5({
|
|
687
|
-
error: Oauth2ErrorCodes4.InvalidRequest,
|
|
688
|
-
error_description: `The client identifier scheme 'https' is not supported when using the dc_api response mode.`
|
|
689
|
-
});
|
|
690
|
-
}
|
|
691
689
|
if (!clientId.startsWith("https://") && !(getGlobalConfig().allowInsecureUrls && clientId.startsWith("http://"))) {
|
|
692
690
|
throw new Oauth2ServerErrorResponseError5({
|
|
693
691
|
error: Oauth2ErrorCodes4.InvalidRequest,
|
|
@@ -698,7 +696,7 @@ function parseClientIdentifier(options, parserConfig) {
|
|
|
698
696
|
scheme,
|
|
699
697
|
identifier: clientId,
|
|
700
698
|
originalValue: clientId,
|
|
701
|
-
trustChain:
|
|
699
|
+
trustChain: authorizationRequestPayload.trust_chain
|
|
702
700
|
};
|
|
703
701
|
}
|
|
704
702
|
if (scheme === "redirect_uri") {
|
|
@@ -708,7 +706,7 @@ function parseClientIdentifier(options, parserConfig) {
|
|
|
708
706
|
error_description: 'Using client identifier scheme "redirect_uri" the request MUST NOT be signed.'
|
|
709
707
|
});
|
|
710
708
|
}
|
|
711
|
-
if (isOpenid4vpAuthorizationRequestDcApi(
|
|
709
|
+
if (isOpenid4vpAuthorizationRequestDcApi(authorizationRequestPayload)) {
|
|
712
710
|
throw new Oauth2ServerErrorResponseError5({
|
|
713
711
|
error: Oauth2ErrorCodes4.InvalidRequest,
|
|
714
712
|
error_description: `The client identifier scheme 'redirect_uri' is not supported when using the dc_api response mode.`
|
|
@@ -718,7 +716,7 @@ function parseClientIdentifier(options, parserConfig) {
|
|
|
718
716
|
scheme,
|
|
719
717
|
identifier: identifierPart,
|
|
720
718
|
originalValue: clientId,
|
|
721
|
-
redirectUri:
|
|
719
|
+
redirectUri: authorizationRequestPayload.redirect_uri ?? authorizationRequestPayload.response_uri
|
|
722
720
|
};
|
|
723
721
|
}
|
|
724
722
|
if (scheme === "did") {
|
|
@@ -784,9 +782,9 @@ function parseClientIdentifier(options, parserConfig) {
|
|
|
784
782
|
error_description: `Invalid client identifier. One of the leaf certificates san dns names [${sanDnsNames.join(", ")}] must match the client identifier '${identifierPart}'. `
|
|
785
783
|
});
|
|
786
784
|
}
|
|
787
|
-
if (!isOpenid4vpAuthorizationRequestDcApi(
|
|
788
|
-
const uri =
|
|
789
|
-
if (!uri ||
|
|
785
|
+
if (!isOpenid4vpAuthorizationRequestDcApi(authorizationRequestPayload)) {
|
|
786
|
+
const uri = authorizationRequestPayload.redirect_uri ?? authorizationRequestPayload.response_uri;
|
|
787
|
+
if (!uri || new URL3(uri).hostname !== identifierPart) {
|
|
790
788
|
throw new Oauth2ServerErrorResponseError5({
|
|
791
789
|
error: Oauth2ErrorCodes4.InvalidRequest,
|
|
792
790
|
error_description: "Invalid client identifier. The fully qualified domain name of the redirect_uri value MUST match the Client Identifier without the prefix x509_san_dns."
|
|
@@ -811,8 +809,8 @@ function parseClientIdentifier(options, parserConfig) {
|
|
|
811
809
|
error_description: `Invalid client identifier. One of the leaf certificates san uri names [${sanUriNames.join(", ")}] must match the client identifier '${identifierPart}'.`
|
|
812
810
|
});
|
|
813
811
|
}
|
|
814
|
-
if (!isOpenid4vpAuthorizationRequestDcApi(
|
|
815
|
-
const uri =
|
|
812
|
+
if (!isOpenid4vpAuthorizationRequestDcApi(authorizationRequestPayload)) {
|
|
813
|
+
const uri = authorizationRequestPayload.redirect_uri || authorizationRequestPayload.response_uri;
|
|
816
814
|
if (!uri || uri !== identifierPart) {
|
|
817
815
|
throw new Oauth2ServerErrorResponseError5({
|
|
818
816
|
error: Oauth2ErrorCodes4.InvalidRequest,
|
|
@@ -833,7 +831,7 @@ function parseClientIdentifier(options, parserConfig) {
|
|
|
833
831
|
scheme,
|
|
834
832
|
identifier: identifierPart,
|
|
835
833
|
originalValue: clientId,
|
|
836
|
-
clientMetadata:
|
|
834
|
+
clientMetadata: authorizationRequestPayload.client_metadata
|
|
837
835
|
};
|
|
838
836
|
}
|
|
839
837
|
if (scheme === "verifier_attestation") {
|
|
@@ -850,39 +848,14 @@ function parseClientIdentifier(options, parserConfig) {
|
|
|
850
848
|
originalValue: clientId
|
|
851
849
|
};
|
|
852
850
|
}
|
|
853
|
-
function getDomainFromUrl(url) {
|
|
854
|
-
try {
|
|
855
|
-
const regex = /[#/?]/;
|
|
856
|
-
const domain = url.split("://")[1].split(regex)[0];
|
|
857
|
-
return domain;
|
|
858
|
-
} catch (error) {
|
|
859
|
-
throw new Oauth2ServerErrorResponseError5({
|
|
860
|
-
error: Oauth2ErrorCodes4.ServerError,
|
|
861
|
-
error_description: `Url '${url}' is not a valid URL`
|
|
862
|
-
});
|
|
863
|
-
}
|
|
864
|
-
}
|
|
865
851
|
|
|
866
852
|
// src/fetch-client-metadata.ts
|
|
867
853
|
import { Oauth2ErrorCodes as Oauth2ErrorCodes5, Oauth2ServerErrorResponseError as Oauth2ServerErrorResponseError6 } from "@openid4vc/oauth2";
|
|
868
854
|
import { ContentType, createZodFetcher } from "@openid4vc/utils";
|
|
869
|
-
|
|
870
|
-
// src/models/z-wallet-metadata.ts
|
|
871
|
-
import { z as z11 } from "zod";
|
|
872
|
-
var zWalletMetadata = z11.object({
|
|
873
|
-
presentation_definition_uri_supported: z11.optional(z11.boolean()),
|
|
874
|
-
vp_formats_supported: zVpFormatsSupported,
|
|
875
|
-
client_id_schemes_supported: z11.optional(z11.array(zClientIdScheme)),
|
|
876
|
-
request_object_signing_alg_values_supported: z11.optional(z11.array(z11.string())),
|
|
877
|
-
authorization_encryption_alg_values_supported: z11.optional(z11.array(z11.string())),
|
|
878
|
-
authorization_encryption_enc_values_supported: z11.optional(z11.array(z11.string()))
|
|
879
|
-
});
|
|
880
|
-
|
|
881
|
-
// src/fetch-client-metadata.ts
|
|
882
855
|
async function fetchClientMetadata(options) {
|
|
883
856
|
const { fetch, clientMetadataUri } = options;
|
|
884
857
|
const fetcher = createZodFetcher(fetch);
|
|
885
|
-
const { result, response } = await fetcher(
|
|
858
|
+
const { result, response } = await fetcher(zClientMetadata, ContentType.Json, clientMetadataUri, {
|
|
886
859
|
method: "GET",
|
|
887
860
|
headers: {
|
|
888
861
|
Accept: ContentType.Json
|
|
@@ -917,7 +890,7 @@ import {
|
|
|
917
890
|
// src/jar/jar-request-object/fetch-jar-request-object.ts
|
|
918
891
|
import { Oauth2ErrorCodes as Oauth2ErrorCodes6, Oauth2ServerErrorResponseError as Oauth2ServerErrorResponseError7 } from "@openid4vc/oauth2";
|
|
919
892
|
import { ContentType as ContentType2, createZodFetcher as createZodFetcher2, objectToQueryParams as objectToQueryParams2 } from "@openid4vc/utils";
|
|
920
|
-
import { z as
|
|
893
|
+
import { z as z11 } from "zod";
|
|
921
894
|
async function fetchJarRequestObject(options) {
|
|
922
895
|
const { requestUri, clientIdentifierScheme, method, wallet, fetch } = options;
|
|
923
896
|
const fetcher = createZodFetcher2(fetch);
|
|
@@ -926,10 +899,10 @@ async function fetchJarRequestObject(options) {
|
|
|
926
899
|
const { request_object_signing_alg_values_supported, ...rest } = requestBody.wallet_metadata;
|
|
927
900
|
requestBody = { ...requestBody, wallet_metadata: { ...rest } };
|
|
928
901
|
}
|
|
929
|
-
const { result, response } = await fetcher(
|
|
902
|
+
const { result, response } = await fetcher(z11.string(), ContentType2.OAuthAuthorizationRequestJwt, requestUri, {
|
|
930
903
|
method,
|
|
931
904
|
headers: {
|
|
932
|
-
Accept: `${ContentType2.
|
|
905
|
+
Accept: `${ContentType2.OAuthAuthorizationRequestJwt}, ${ContentType2.Jwt};q=0.9`,
|
|
933
906
|
"Content-Type": ContentType2.XWwwFormUrlencoded
|
|
934
907
|
},
|
|
935
908
|
body: method === "POST" ? objectToQueryParams2(wallet.metadata ?? {}) : void 0
|
|
@@ -951,10 +924,10 @@ async function fetchJarRequestObject(options) {
|
|
|
951
924
|
|
|
952
925
|
// src/jar/jar-request-object/z-jar-request-object.ts
|
|
953
926
|
import { zJwtPayload as zJwtPayload2 } from "@openid4vc/oauth2";
|
|
954
|
-
import { z as
|
|
955
|
-
var zJarRequestObjectPayload =
|
|
927
|
+
import { z as z12 } from "zod";
|
|
928
|
+
var zJarRequestObjectPayload = z12.object({
|
|
956
929
|
...zJwtPayload2.shape,
|
|
957
|
-
client_id:
|
|
930
|
+
client_id: z12.string()
|
|
958
931
|
}).passthrough();
|
|
959
932
|
|
|
960
933
|
// src/jar/handle-jar-request/verify-jar-request.ts
|
|
@@ -985,17 +958,17 @@ async function verifyJarRequest(options) {
|
|
|
985
958
|
error_description: "Jar Request Object is not a valid JWS."
|
|
986
959
|
});
|
|
987
960
|
}
|
|
988
|
-
const {
|
|
961
|
+
const { authorizationRequestParams, signer } = await verifyJarRequestObject({
|
|
989
962
|
decryptedRequestObject,
|
|
990
963
|
callbacks
|
|
991
964
|
});
|
|
992
|
-
if (!
|
|
965
|
+
if (!authorizationRequestParams.client_id) {
|
|
993
966
|
throw new Oauth2ServerErrorResponseError8({
|
|
994
967
|
error: Oauth2ErrorCodes7.InvalidRequestObject,
|
|
995
968
|
error_description: 'Jar Request Object is missing the required "client_id" field.'
|
|
996
969
|
});
|
|
997
970
|
}
|
|
998
|
-
if (jarRequestParams.client_id !==
|
|
971
|
+
if (jarRequestParams.client_id !== authorizationRequestParams.client_id) {
|
|
999
972
|
throw new Oauth2ServerErrorResponseError8({
|
|
1000
973
|
error: Oauth2ErrorCodes7.InvalidRequest,
|
|
1001
974
|
error_description: "client_id does not match the request object client_id."
|
|
@@ -1003,7 +976,7 @@ async function verifyJarRequest(options) {
|
|
|
1003
976
|
}
|
|
1004
977
|
return {
|
|
1005
978
|
sendBy,
|
|
1006
|
-
|
|
979
|
+
authorizationRequestParams,
|
|
1007
980
|
signer,
|
|
1008
981
|
decryptionJwk
|
|
1009
982
|
};
|
|
@@ -1044,7 +1017,7 @@ async function verifyJarRequestObject(options) {
|
|
|
1044
1017
|
error_description: `Invalid Jar Request Object typ header. Expected "oauth-authz-req+jwt", received "${jwt.header.typ}".`
|
|
1045
1018
|
});
|
|
1046
1019
|
}
|
|
1047
|
-
return {
|
|
1020
|
+
return { authorizationRequestParams: jwt.payload, signer };
|
|
1048
1021
|
}
|
|
1049
1022
|
|
|
1050
1023
|
// src/transaction-data/parse-transaction-data.ts
|
|
@@ -1052,13 +1025,13 @@ import { Oauth2ErrorCodes as Oauth2ErrorCodes8, Oauth2ServerErrorResponseError a
|
|
|
1052
1025
|
import { decodeBase64, encodeToUtf8String, parseIfJson } from "@openid4vc/utils";
|
|
1053
1026
|
|
|
1054
1027
|
// src/transaction-data/z-transaction-data.ts
|
|
1055
|
-
import { z as
|
|
1056
|
-
var zTransactionEntry =
|
|
1057
|
-
type:
|
|
1058
|
-
credential_ids:
|
|
1059
|
-
transaction_data_hashes_alg:
|
|
1028
|
+
import { z as z13 } from "zod";
|
|
1029
|
+
var zTransactionEntry = z13.object({
|
|
1030
|
+
type: z13.string(),
|
|
1031
|
+
credential_ids: z13.array(z13.string()).nonempty(),
|
|
1032
|
+
transaction_data_hashes_alg: z13.array(z13.string()).optional()
|
|
1060
1033
|
});
|
|
1061
|
-
var zTransactionData =
|
|
1034
|
+
var zTransactionData = z13.array(zTransactionEntry);
|
|
1062
1035
|
|
|
1063
1036
|
// src/transaction-data/parse-transaction-data.ts
|
|
1064
1037
|
function parseTransactionData(options) {
|
|
@@ -1080,87 +1053,93 @@ function parseTransactionData(options) {
|
|
|
1080
1053
|
|
|
1081
1054
|
// src/authorization-request/resolve-authorization-request.ts
|
|
1082
1055
|
async function resolveOpenid4vpAuthorizationRequest(options) {
|
|
1083
|
-
const {
|
|
1084
|
-
let
|
|
1056
|
+
const { wallet, callbacks, origin, disableOriginValidation } = options;
|
|
1057
|
+
let authorizationRequestPayload;
|
|
1085
1058
|
const parsed = parseWithErrorHandling4(
|
|
1086
|
-
|
|
1087
|
-
|
|
1059
|
+
z14.union([zOpenid4vpAuthorizationRequestDcApi, zOpenid4vpAuthorizationRequest, zJarAuthorizationRequest]),
|
|
1060
|
+
options.authorizationRequestPayload,
|
|
1088
1061
|
"Invalid authorization request. Could not parse openid4vp authorization request as openid4vp or jar auth request."
|
|
1089
1062
|
);
|
|
1090
1063
|
let jar;
|
|
1091
|
-
if (
|
|
1064
|
+
if (isJarAuthorizationRequest(parsed)) {
|
|
1092
1065
|
jar = await verifyJarRequest({ jarRequestParams: parsed, callbacks, wallet });
|
|
1093
|
-
const
|
|
1094
|
-
|
|
1095
|
-
jar.
|
|
1066
|
+
const parsedJarAuthorizationRequestPayload = parseWithErrorHandling4(
|
|
1067
|
+
z14.union([zOpenid4vpAuthorizationRequestDcApi, zOpenid4vpAuthorizationRequest]),
|
|
1068
|
+
jar.authorizationRequestParams,
|
|
1096
1069
|
"Invalid authorization request. Could not parse jar request payload as openid4vp auth request."
|
|
1097
1070
|
);
|
|
1098
|
-
|
|
1099
|
-
|
|
1071
|
+
authorizationRequestPayload = validateOpenId4vpAuthorizationRequestPayload({
|
|
1072
|
+
authorizationRequestPayload: parsedJarAuthorizationRequestPayload,
|
|
1100
1073
|
wallet,
|
|
1101
1074
|
jar: true,
|
|
1102
1075
|
origin,
|
|
1103
|
-
|
|
1076
|
+
disableOriginValidation
|
|
1104
1077
|
});
|
|
1105
1078
|
} else {
|
|
1106
|
-
|
|
1107
|
-
|
|
1079
|
+
authorizationRequestPayload = validateOpenId4vpAuthorizationRequestPayload({
|
|
1080
|
+
authorizationRequestPayload: parsed,
|
|
1108
1081
|
wallet,
|
|
1109
1082
|
jar: false,
|
|
1110
1083
|
origin,
|
|
1111
|
-
|
|
1084
|
+
disableOriginValidation
|
|
1112
1085
|
});
|
|
1113
1086
|
}
|
|
1114
|
-
let clientMetadata;
|
|
1115
|
-
if (!isOpenid4vpAuthorizationRequestDcApi(
|
|
1116
|
-
clientMetadata = await fetchClientMetadata({ clientMetadataUri:
|
|
1087
|
+
let clientMetadata = authorizationRequestPayload.client_metadata;
|
|
1088
|
+
if (!isOpenid4vpAuthorizationRequestDcApi(authorizationRequestPayload) && !clientMetadata && authorizationRequestPayload.client_metadata_uri) {
|
|
1089
|
+
clientMetadata = await fetchClientMetadata({ clientMetadataUri: authorizationRequestPayload.client_metadata_uri });
|
|
1117
1090
|
}
|
|
1118
1091
|
const clientMeta = parseClientIdentifier({
|
|
1119
|
-
|
|
1092
|
+
authorizationRequestPayload: {
|
|
1093
|
+
...authorizationRequestPayload,
|
|
1094
|
+
client_metadata: clientMetadata
|
|
1095
|
+
},
|
|
1120
1096
|
jar,
|
|
1121
1097
|
callbacks,
|
|
1122
1098
|
origin
|
|
1123
1099
|
});
|
|
1124
1100
|
let pex;
|
|
1125
1101
|
let dcql;
|
|
1126
|
-
if (
|
|
1127
|
-
if (
|
|
1102
|
+
if (authorizationRequestPayload.presentation_definition || authorizationRequestPayload.presentation_definition_uri) {
|
|
1103
|
+
if (authorizationRequestPayload.presentation_definition_uri) {
|
|
1128
1104
|
throw new Oauth2ServerErrorResponseError10({
|
|
1129
1105
|
error: Oauth2ErrorCodes9.InvalidRequest,
|
|
1130
1106
|
error_description: "Cannot fetch presentation definition from URI. Not supported."
|
|
1131
1107
|
});
|
|
1132
1108
|
}
|
|
1133
1109
|
pex = {
|
|
1134
|
-
presentation_definition:
|
|
1135
|
-
presentation_definition_uri:
|
|
1110
|
+
presentation_definition: authorizationRequestPayload.presentation_definition,
|
|
1111
|
+
presentation_definition_uri: authorizationRequestPayload.presentation_definition_uri
|
|
1136
1112
|
};
|
|
1137
1113
|
}
|
|
1138
|
-
if (
|
|
1139
|
-
dcql = { query:
|
|
1114
|
+
if (authorizationRequestPayload.dcql_query) {
|
|
1115
|
+
dcql = { query: authorizationRequestPayload.dcql_query };
|
|
1140
1116
|
}
|
|
1141
|
-
const transactionData =
|
|
1117
|
+
const transactionData = authorizationRequestPayload.transaction_data ? parseTransactionData({ transactionData: authorizationRequestPayload.transaction_data }) : void 0;
|
|
1142
1118
|
return {
|
|
1143
1119
|
transactionData,
|
|
1144
|
-
|
|
1120
|
+
authorizationRequestPayload,
|
|
1145
1121
|
jar,
|
|
1146
|
-
client:
|
|
1122
|
+
client: clientMeta,
|
|
1147
1123
|
pex,
|
|
1148
1124
|
dcql
|
|
1149
1125
|
};
|
|
1150
1126
|
}
|
|
1151
|
-
function
|
|
1152
|
-
const {
|
|
1153
|
-
if (isOpenid4vpAuthorizationRequestDcApi(
|
|
1127
|
+
function validateOpenId4vpAuthorizationRequestPayload(options) {
|
|
1128
|
+
const { authorizationRequestPayload, wallet, jar, origin, disableOriginValidation } = options;
|
|
1129
|
+
if (isOpenid4vpAuthorizationRequestDcApi(authorizationRequestPayload)) {
|
|
1154
1130
|
validateOpenid4vpAuthorizationRequestDcApiPayload({
|
|
1155
|
-
params:
|
|
1131
|
+
params: authorizationRequestPayload,
|
|
1156
1132
|
isJarRequest: jar,
|
|
1157
|
-
|
|
1133
|
+
disableOriginValidation,
|
|
1158
1134
|
origin
|
|
1159
1135
|
});
|
|
1160
|
-
return
|
|
1136
|
+
return authorizationRequestPayload;
|
|
1161
1137
|
}
|
|
1162
|
-
validateOpenid4vpAuthorizationRequestPayload({
|
|
1163
|
-
|
|
1138
|
+
validateOpenid4vpAuthorizationRequestPayload({
|
|
1139
|
+
params: authorizationRequestPayload,
|
|
1140
|
+
walletVerificationOptions: wallet
|
|
1141
|
+
});
|
|
1142
|
+
return authorizationRequestPayload;
|
|
1164
1143
|
}
|
|
1165
1144
|
|
|
1166
1145
|
// src/authorization-response/create-authorization-response.ts
|
|
@@ -1176,49 +1155,37 @@ function addSecondsToDate(date, seconds) {
|
|
|
1176
1155
|
return new Date(date.getTime() + seconds * 1e3);
|
|
1177
1156
|
}
|
|
1178
1157
|
|
|
1179
|
-
// src/jarm/jarm-
|
|
1158
|
+
// src/jarm/jarm-authorization-response-create.ts
|
|
1180
1159
|
import {
|
|
1181
1160
|
Oauth2Error as Oauth2Error5,
|
|
1182
1161
|
jwtHeaderFromJwtSigner as jwtHeaderFromJwtSigner2
|
|
1183
1162
|
} from "@openid4vc/oauth2";
|
|
1184
|
-
async function
|
|
1185
|
-
const {
|
|
1163
|
+
async function createJarmAuthorizationResponse(options) {
|
|
1164
|
+
const { jarmAuthorizationResponse, jweEncryptor, jwtSigner, callbacks } = options;
|
|
1186
1165
|
if (!jwtSigner && jweEncryptor) {
|
|
1187
|
-
const { jwe } = await callbacks.encryptJwe(jweEncryptor, JSON.stringify(
|
|
1188
|
-
return {
|
|
1166
|
+
const { jwe } = await callbacks.encryptJwe(jweEncryptor, JSON.stringify(jarmAuthorizationResponse));
|
|
1167
|
+
return { jarmAuthorizationResponseJwt: jwe };
|
|
1189
1168
|
}
|
|
1190
1169
|
if (jwtSigner && !jweEncryptor) {
|
|
1191
1170
|
const signed2 = await callbacks.signJwt(jwtSigner, {
|
|
1192
1171
|
header: jwtHeaderFromJwtSigner2(jwtSigner),
|
|
1193
|
-
payload:
|
|
1172
|
+
payload: jarmAuthorizationResponse
|
|
1194
1173
|
});
|
|
1195
|
-
return {
|
|
1174
|
+
return { jarmAuthorizationResponseJwt: signed2.jwt };
|
|
1196
1175
|
}
|
|
1197
1176
|
if (!jwtSigner || !jweEncryptor) {
|
|
1198
1177
|
throw new Oauth2Error5("JWT signer and/or encryptor are required to create a JARM auth response.");
|
|
1199
1178
|
}
|
|
1200
1179
|
const signed = await callbacks.signJwt(jwtSigner, {
|
|
1201
1180
|
header: jwtHeaderFromJwtSigner2(jwtSigner),
|
|
1202
|
-
payload:
|
|
1181
|
+
payload: jarmAuthorizationResponse
|
|
1203
1182
|
});
|
|
1204
1183
|
const encrypted = await callbacks.encryptJwe(jweEncryptor, signed.jwt);
|
|
1205
|
-
return {
|
|
1206
|
-
}
|
|
1207
|
-
|
|
1208
|
-
// src/jarm/jarm-extract-jwks.ts
|
|
1209
|
-
function extractJwksFromClientMetadata(clientMetadata) {
|
|
1210
|
-
const parsed = zJarmClientMetadataParsed.parse(clientMetadata);
|
|
1211
|
-
const encryptionAlg = parsed.client_metadata.authorization_encrypted_response_enc;
|
|
1212
|
-
const signingAlg = parsed.client_metadata.authorization_signed_response_alg;
|
|
1213
|
-
const encJwk = clientMetadata.jwks.keys.find((key) => key.use === "enc" && key.alg === encryptionAlg) ?? clientMetadata.jwks.keys.find((key) => key.use === "enc") ?? // fallback, take first key. HAIP does not specify requirement on enc
|
|
1214
|
-
clientMetadata.jwks.keys?.[0];
|
|
1215
|
-
const sigJwk = clientMetadata.jwks.keys.find((key) => key.use === "sig" && key.alg === signingAlg) ?? clientMetadata.jwks.keys.find((key) => key.use === "sig") ?? // falback, take first key
|
|
1216
|
-
clientMetadata.jwks.keys?.[0];
|
|
1217
|
-
return { encJwk, sigJwk };
|
|
1184
|
+
return { jarmAuthorizationResponseJwt: encrypted.jwe };
|
|
1218
1185
|
}
|
|
1219
1186
|
|
|
1220
1187
|
// src/jarm/jarm-response-mode.ts
|
|
1221
|
-
import { z as
|
|
1188
|
+
import { z as z15 } from "zod";
|
|
1222
1189
|
var jarmResponseMode = [
|
|
1223
1190
|
"jwt",
|
|
1224
1191
|
"query.jwt",
|
|
@@ -1227,7 +1194,7 @@ var jarmResponseMode = [
|
|
|
1227
1194
|
"direct_post.jwt",
|
|
1228
1195
|
"dc_api.jwt"
|
|
1229
1196
|
];
|
|
1230
|
-
var zJarmResponseMode =
|
|
1197
|
+
var zJarmResponseMode = z15.enum(jarmResponseMode);
|
|
1231
1198
|
var isJarmResponseMode = (responseMode) => {
|
|
1232
1199
|
return jarmResponseMode.includes(responseMode);
|
|
1233
1200
|
};
|
|
@@ -1273,37 +1240,37 @@ function jarmAssertMetadataSupported(options) {
|
|
|
1273
1240
|
|
|
1274
1241
|
// src/authorization-response/create-authorization-response.ts
|
|
1275
1242
|
async function createOpenid4vpAuthorizationResponse(options) {
|
|
1276
|
-
const {
|
|
1277
|
-
const
|
|
1278
|
-
...options.
|
|
1279
|
-
..."state" in
|
|
1243
|
+
const { authorizationRequestPayload, jarm, callbacks } = options;
|
|
1244
|
+
const authorizationResponsePayload = {
|
|
1245
|
+
...options.authorizationResponsePayload,
|
|
1246
|
+
..."state" in authorizationRequestPayload && { state: authorizationRequestPayload.state }
|
|
1280
1247
|
};
|
|
1281
|
-
if (
|
|
1248
|
+
if (authorizationRequestPayload.response_mode && isJarmResponseMode(authorizationRequestPayload.response_mode) && !jarm) {
|
|
1282
1249
|
throw new Oauth2Error7(
|
|
1283
|
-
`Missing jarm options for creating Jarm response with response mode '${
|
|
1250
|
+
`Missing jarm options for creating Jarm response with response mode '${authorizationRequestPayload.response_mode}'`
|
|
1284
1251
|
);
|
|
1285
1252
|
}
|
|
1286
1253
|
if (!jarm) {
|
|
1287
1254
|
return {
|
|
1288
|
-
|
|
1255
|
+
authorizationResponsePayload
|
|
1289
1256
|
};
|
|
1290
1257
|
}
|
|
1291
|
-
if (!
|
|
1258
|
+
if (!authorizationRequestPayload.client_metadata) {
|
|
1292
1259
|
throw new Oauth2Error7("Missing client metadata in the request params to assert Jarm metadata support.");
|
|
1293
1260
|
}
|
|
1294
|
-
if (!
|
|
1261
|
+
if (!authorizationRequestPayload.client_metadata.jwks) {
|
|
1295
1262
|
throw new Oauth2ServerErrorResponseError11({
|
|
1296
1263
|
error: Oauth2ErrorCodes10.InvalidRequest,
|
|
1297
1264
|
error_description: "Missing JWKS in client metadata. Cannot extract encryption JWK."
|
|
1298
1265
|
});
|
|
1299
1266
|
}
|
|
1300
1267
|
const supportedJarmMetadata = jarmAssertMetadataSupported({
|
|
1301
|
-
clientMetadata:
|
|
1268
|
+
clientMetadata: authorizationRequestPayload.client_metadata,
|
|
1302
1269
|
serverMetadata: jarm.serverMetadata
|
|
1303
1270
|
});
|
|
1304
1271
|
const clientMetaJwks = extractJwksFromClientMetadata({
|
|
1305
|
-
...
|
|
1306
|
-
jwks:
|
|
1272
|
+
...authorizationRequestPayload.client_metadata,
|
|
1273
|
+
jwks: authorizationRequestPayload.client_metadata.jwks
|
|
1307
1274
|
});
|
|
1308
1275
|
if (!clientMetaJwks?.encJwk) {
|
|
1309
1276
|
throw new Oauth2ServerErrorResponseError11({
|
|
@@ -1333,17 +1300,17 @@ async function createOpenid4vpAuthorizationResponse(options) {
|
|
|
1333
1300
|
};
|
|
1334
1301
|
}
|
|
1335
1302
|
const jarmResponsePayload = {
|
|
1336
|
-
...
|
|
1303
|
+
...authorizationResponsePayload,
|
|
1337
1304
|
...additionalJwtPayload
|
|
1338
1305
|
};
|
|
1339
|
-
const result = await
|
|
1340
|
-
|
|
1306
|
+
const result = await createJarmAuthorizationResponse({
|
|
1307
|
+
jarmAuthorizationResponse: jarmResponsePayload,
|
|
1341
1308
|
jwtSigner: jarm?.jwtSigner,
|
|
1342
1309
|
jweEncryptor: jarm?.encryption && (supportedJarmMetadata.type === "encrypt" || supportedJarmMetadata.type === "sign_encrypt") ? {
|
|
1343
1310
|
method: "jwk",
|
|
1344
1311
|
publicJwk: clientMetaJwks.encJwk,
|
|
1345
1312
|
apu: jarm.encryption?.nonce,
|
|
1346
|
-
apv:
|
|
1313
|
+
apv: authorizationRequestPayload.nonce,
|
|
1347
1314
|
alg: supportedJarmMetadata.client_metadata.authorization_encrypted_response_alg,
|
|
1348
1315
|
enc: supportedJarmMetadata.client_metadata.authorization_encrypted_response_enc
|
|
1349
1316
|
} : void 0,
|
|
@@ -1353,8 +1320,8 @@ async function createOpenid4vpAuthorizationResponse(options) {
|
|
|
1353
1320
|
}
|
|
1354
1321
|
});
|
|
1355
1322
|
return {
|
|
1356
|
-
|
|
1357
|
-
jarm: { responseJwt: result.
|
|
1323
|
+
authorizationResponsePayload: jarmResponsePayload,
|
|
1324
|
+
jarm: { responseJwt: result.jarmAuthorizationResponseJwt }
|
|
1358
1325
|
};
|
|
1359
1326
|
}
|
|
1360
1327
|
|
|
@@ -1363,17 +1330,17 @@ import { Oauth2Error as Oauth2Error9 } from "@openid4vc/oauth2";
|
|
|
1363
1330
|
import { ContentType as ContentType4, defaultFetcher as defaultFetcher2 } from "@openid4vc/utils";
|
|
1364
1331
|
import { objectToQueryParams as objectToQueryParams3 } from "@openid4vc/utils";
|
|
1365
1332
|
|
|
1366
|
-
// src/jarm/jarm-
|
|
1333
|
+
// src/jarm/jarm-authorizatino-response-send.ts
|
|
1367
1334
|
import { Oauth2Error as Oauth2Error8 } from "@openid4vc/oauth2";
|
|
1368
|
-
import { ContentType as ContentType3, URL as
|
|
1369
|
-
var
|
|
1370
|
-
const {
|
|
1371
|
-
const responseEndpoint =
|
|
1335
|
+
import { ContentType as ContentType3, URL as URL4, defaultFetcher } from "@openid4vc/utils";
|
|
1336
|
+
var jarmAuthorizationResponseSend = (options) => {
|
|
1337
|
+
const { authorizationRequestPayload, jarmAuthorizationResponseJwt, callbacks } = options;
|
|
1338
|
+
const responseEndpoint = authorizationRequestPayload.response_uri ?? authorizationRequestPayload.redirect_uri;
|
|
1372
1339
|
if (!responseEndpoint) {
|
|
1373
1340
|
throw new Oauth2Error8(`Either 'response_uri' or 'redirect_uri' MUST be present in the authorization request`);
|
|
1374
1341
|
}
|
|
1375
|
-
const responseEndpointUrl = new
|
|
1376
|
-
return handleDirectPostJwt(responseEndpointUrl,
|
|
1342
|
+
const responseEndpointUrl = new URL4(responseEndpoint);
|
|
1343
|
+
return handleDirectPostJwt(responseEndpointUrl, jarmAuthorizationResponseJwt, callbacks);
|
|
1377
1344
|
};
|
|
1378
1345
|
async function handleDirectPostJwt(responseEndpoint, responseJwt, callbacks) {
|
|
1379
1346
|
const response = await (callbacks.fetch ?? defaultFetcher)(responseEndpoint, {
|
|
@@ -1389,12 +1356,12 @@ async function handleDirectPostJwt(responseEndpoint, responseJwt, callbacks) {
|
|
|
1389
1356
|
|
|
1390
1357
|
// src/authorization-response/submit-authorization-response.ts
|
|
1391
1358
|
async function submitOpenid4vpAuthorizationResponse(options) {
|
|
1392
|
-
const {
|
|
1393
|
-
const url =
|
|
1359
|
+
const { authorizationRequestPayload, authorizationResponsePayload, jarm, callbacks } = options;
|
|
1360
|
+
const url = authorizationRequestPayload.response_uri;
|
|
1394
1361
|
if (jarm) {
|
|
1395
|
-
return
|
|
1396
|
-
|
|
1397
|
-
|
|
1362
|
+
return jarmAuthorizationResponseSend({
|
|
1363
|
+
authorizationRequestPayload,
|
|
1364
|
+
jarmAuthorizationResponseJwt: jarm.responseJwt,
|
|
1398
1365
|
callbacks
|
|
1399
1366
|
});
|
|
1400
1367
|
}
|
|
@@ -1404,7 +1371,7 @@ async function submitOpenid4vpAuthorizationResponse(options) {
|
|
|
1404
1371
|
);
|
|
1405
1372
|
}
|
|
1406
1373
|
const fetch = callbacks.fetch ?? defaultFetcher2;
|
|
1407
|
-
const encodedResponse = objectToQueryParams3(
|
|
1374
|
+
const encodedResponse = objectToQueryParams3(authorizationResponsePayload);
|
|
1408
1375
|
const submissionResponse = await fetch(url, {
|
|
1409
1376
|
method: "POST",
|
|
1410
1377
|
body: encodedResponse,
|
|
@@ -1425,17 +1392,17 @@ import { Oauth2Error as Oauth2Error10 } from "@openid4vc/oauth2";
|
|
|
1425
1392
|
import { parseIfJson as parseIfJson2, parseWithErrorHandling as parseWithErrorHandling5 } from "@openid4vc/utils";
|
|
1426
1393
|
|
|
1427
1394
|
// src/vp-token/z-vp-token.ts
|
|
1428
|
-
import { z as
|
|
1429
|
-
var zVpTokenPexEntry =
|
|
1395
|
+
import { z as z16 } from "zod";
|
|
1396
|
+
var zVpTokenPexEntry = z16.union([z16.string(), z16.record(z16.any())], {
|
|
1430
1397
|
message: "pex vp_token entry must be a string or object"
|
|
1431
1398
|
});
|
|
1432
|
-
var zVpTokenPex =
|
|
1433
|
-
[zVpTokenPexEntry,
|
|
1399
|
+
var zVpTokenPex = z16.union(
|
|
1400
|
+
[zVpTokenPexEntry, z16.array(zVpTokenPexEntry).nonempty("Must have at least entry in vp_token array")],
|
|
1434
1401
|
{
|
|
1435
1402
|
message: "pex vp_token must be a string, object or array of strings and objects"
|
|
1436
1403
|
}
|
|
1437
1404
|
);
|
|
1438
|
-
var zVpTokenDcql =
|
|
1405
|
+
var zVpTokenDcql = z16.record(z16.union([z16.string(), z16.record(z16.any())]), {
|
|
1439
1406
|
message: "dcql vp_token must be an object with keys referencing the dcql credential query id, and values the encoded (string or object) presentation"
|
|
1440
1407
|
});
|
|
1441
1408
|
var zVpToken = zVpTokenDcql.or(zVpTokenPex);
|
|
@@ -1459,39 +1426,39 @@ function parseDcqlVpToken(vpToken) {
|
|
|
1459
1426
|
|
|
1460
1427
|
// src/authorization-response/validate-authorization-response.ts
|
|
1461
1428
|
function validateOpenid4vpAuthorizationResponsePayload(options) {
|
|
1462
|
-
const {
|
|
1463
|
-
if ("state" in
|
|
1429
|
+
const { authorizationRequestPayload, authorizationResponsePayload } = options;
|
|
1430
|
+
if ("state" in authorizationRequestPayload && authorizationRequestPayload.state !== authorizationResponsePayload.state) {
|
|
1464
1431
|
throw new Oauth2Error10("OpenId4Vp Authorization Response state mismatch.");
|
|
1465
1432
|
}
|
|
1466
|
-
if (
|
|
1433
|
+
if (authorizationResponsePayload.id_token) {
|
|
1467
1434
|
throw new Oauth2Error10("OpenId4Vp Authorization Response id_token is not supported.");
|
|
1468
1435
|
}
|
|
1469
|
-
if (
|
|
1470
|
-
if (!
|
|
1436
|
+
if (authorizationResponsePayload.presentation_submission) {
|
|
1437
|
+
if (!authorizationRequestPayload.presentation_definition) {
|
|
1471
1438
|
throw new Oauth2Error10("OpenId4Vp Authorization Request is missing the required presentation_definition.");
|
|
1472
1439
|
}
|
|
1473
1440
|
return {
|
|
1474
1441
|
type: "pex",
|
|
1475
|
-
pex: "scope" in
|
|
1476
|
-
scope:
|
|
1477
|
-
presentationSubmission:
|
|
1478
|
-
presentations: parsePexVpToken(
|
|
1442
|
+
pex: "scope" in authorizationRequestPayload && authorizationRequestPayload.scope ? {
|
|
1443
|
+
scope: authorizationRequestPayload.scope,
|
|
1444
|
+
presentationSubmission: authorizationResponsePayload.presentation_submission,
|
|
1445
|
+
presentations: parsePexVpToken(authorizationResponsePayload.vp_token)
|
|
1479
1446
|
} : {
|
|
1480
|
-
presentationDefinition:
|
|
1481
|
-
presentationSubmission:
|
|
1482
|
-
presentations: parsePexVpToken(
|
|
1447
|
+
presentationDefinition: authorizationRequestPayload.presentation_definition,
|
|
1448
|
+
presentationSubmission: authorizationResponsePayload.presentation_submission,
|
|
1449
|
+
presentations: parsePexVpToken(authorizationResponsePayload.vp_token)
|
|
1483
1450
|
}
|
|
1484
1451
|
};
|
|
1485
1452
|
}
|
|
1486
|
-
if (
|
|
1487
|
-
const presentations = parseDcqlVpToken(
|
|
1453
|
+
if (authorizationRequestPayload.dcql_query) {
|
|
1454
|
+
const presentations = parseDcqlVpToken(authorizationResponsePayload.vp_token);
|
|
1488
1455
|
return {
|
|
1489
1456
|
type: "dcql",
|
|
1490
|
-
dcql: "scope" in
|
|
1491
|
-
scope:
|
|
1457
|
+
dcql: "scope" in authorizationRequestPayload && authorizationRequestPayload.scope ? {
|
|
1458
|
+
scope: authorizationRequestPayload.scope,
|
|
1492
1459
|
presentations
|
|
1493
1460
|
} : {
|
|
1494
|
-
query:
|
|
1461
|
+
query: authorizationRequestPayload.dcql_query,
|
|
1495
1462
|
presentations
|
|
1496
1463
|
}
|
|
1497
1464
|
};
|
|
@@ -1502,29 +1469,29 @@ function validateOpenid4vpAuthorizationResponsePayload(options) {
|
|
|
1502
1469
|
}
|
|
1503
1470
|
|
|
1504
1471
|
// src/authorization-response/parse-authorization-response.ts
|
|
1505
|
-
import {
|
|
1472
|
+
import { Oauth2ServerErrorResponseError as Oauth2ServerErrorResponseError12 } from "@openid4vc/oauth2";
|
|
1506
1473
|
|
|
1507
1474
|
// src/authorization-response/parse-authorization-response-payload.ts
|
|
1508
1475
|
import { parseWithErrorHandling as parseWithErrorHandling6 } from "@openid4vc/utils";
|
|
1509
1476
|
|
|
1510
1477
|
// src/authorization-response/z-authorization-response.ts
|
|
1511
|
-
import { z as
|
|
1478
|
+
import { z as z18 } from "zod";
|
|
1512
1479
|
|
|
1513
1480
|
// src/models/z-pex.ts
|
|
1514
|
-
import { z as
|
|
1515
|
-
var zPexPresentationDefinition =
|
|
1516
|
-
var zPexPresentationSubmission =
|
|
1481
|
+
import { z as z17 } from "zod";
|
|
1482
|
+
var zPexPresentationDefinition = z17.record(z17.any());
|
|
1483
|
+
var zPexPresentationSubmission = z17.record(z17.any());
|
|
1517
1484
|
|
|
1518
1485
|
// src/authorization-response/z-authorization-response.ts
|
|
1519
|
-
var zOpenid4vpAuthorizationResponse =
|
|
1520
|
-
state:
|
|
1521
|
-
id_token:
|
|
1486
|
+
var zOpenid4vpAuthorizationResponse = z18.object({
|
|
1487
|
+
state: z18.string().optional(),
|
|
1488
|
+
id_token: z18.string().optional(),
|
|
1522
1489
|
vp_token: zVpToken,
|
|
1523
1490
|
presentation_submission: zPexPresentationSubmission.optional(),
|
|
1524
|
-
refresh_token:
|
|
1525
|
-
token_type:
|
|
1526
|
-
access_token:
|
|
1527
|
-
expires_in:
|
|
1491
|
+
refresh_token: z18.string().optional(),
|
|
1492
|
+
token_type: z18.string().optional(),
|
|
1493
|
+
access_token: z18.string().optional(),
|
|
1494
|
+
expires_in: z18.number().optional()
|
|
1528
1495
|
}).passthrough();
|
|
1529
1496
|
|
|
1530
1497
|
// src/authorization-response/parse-authorization-response-payload.ts
|
|
@@ -1537,73 +1504,62 @@ function parseOpenid4VpAuthorizationResponsePayload(payload) {
|
|
|
1537
1504
|
}
|
|
1538
1505
|
|
|
1539
1506
|
// src/authorization-response/parse-jarm-authorization-response.ts
|
|
1540
|
-
import { Oauth2Error as Oauth2Error11, decodeJwtHeader
|
|
1541
|
-
import {
|
|
1542
|
-
import
|
|
1507
|
+
import { Oauth2Error as Oauth2Error11, decodeJwtHeader, zCompactJwe as zCompactJwe3, zCompactJwt as zCompactJwt3 } from "@openid4vc/oauth2";
|
|
1508
|
+
import { parseWithErrorHandling as parseWithErrorHandling7 } from "@openid4vc/utils";
|
|
1509
|
+
import z19 from "zod";
|
|
1543
1510
|
async function parseJarmAuthorizationResponse(options) {
|
|
1544
|
-
const { jarmResponseJwt, callbacks } = options;
|
|
1511
|
+
const { jarmResponseJwt, callbacks, authorizationRequestPayload, expectedClientId } = options;
|
|
1545
1512
|
const jarmAuthorizationResponseJwt = parseWithErrorHandling7(
|
|
1546
|
-
|
|
1513
|
+
z19.union([zCompactJwt3, zCompactJwe3]),
|
|
1547
1514
|
jarmResponseJwt,
|
|
1548
1515
|
"Invalid jarm authorization response jwt."
|
|
1549
1516
|
);
|
|
1550
|
-
const verifiedJarmResponse = await verifyJarmAuthorizationResponse({
|
|
1551
|
-
|
|
1517
|
+
const verifiedJarmResponse = await verifyJarmAuthorizationResponse({
|
|
1518
|
+
jarmAuthorizationResponseJwt,
|
|
1519
|
+
callbacks,
|
|
1520
|
+
expectedClientId,
|
|
1521
|
+
authorizationRequestPayload
|
|
1522
|
+
});
|
|
1523
|
+
const { header: jarmHeader } = decodeJwtHeader({
|
|
1552
1524
|
jwt: jarmAuthorizationResponseJwt,
|
|
1553
1525
|
headerSchema: zJarmHeader
|
|
1554
1526
|
});
|
|
1555
|
-
const
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
if (parsedAuthorizationRequest.type !== "openid4vp" && parsedAuthorizationRequest.type !== "openid4vp_dc_api") {
|
|
1559
|
-
throw new Oauth2Error11("Invalid authorization request. Could not parse openid4vp authorization request.");
|
|
1560
|
-
}
|
|
1561
|
-
const authorizationResponsePayload = parseOpenid4VpAuthorizationResponsePayload(verifiedJarmResponse.jarmAuthResponse);
|
|
1527
|
+
const authorizationResponsePayload = parseOpenid4VpAuthorizationResponsePayload(
|
|
1528
|
+
verifiedJarmResponse.jarmAuthorizationResponse
|
|
1529
|
+
);
|
|
1562
1530
|
const validateOpenId4vpResponse = validateOpenid4vpAuthorizationResponsePayload({
|
|
1563
|
-
|
|
1564
|
-
|
|
1531
|
+
authorizationRequestPayload,
|
|
1532
|
+
authorizationResponsePayload
|
|
1565
1533
|
});
|
|
1566
|
-
const authorizationRequestPayload = parsedAuthorizationRequest.params;
|
|
1567
1534
|
if (!authorizationRequestPayload.response_mode || !isJarmResponseMode(authorizationRequestPayload.response_mode)) {
|
|
1568
1535
|
throw new Oauth2Error11(
|
|
1569
1536
|
`Invalid response mode for jarm response. Response mode: '${authorizationRequestPayload.response_mode ?? "fragment"}'`
|
|
1570
1537
|
);
|
|
1571
1538
|
}
|
|
1572
|
-
let mdocGeneratedNonce = void 0;
|
|
1573
|
-
if (jarmHeader?.apu) {
|
|
1574
|
-
mdocGeneratedNonce = encodeToUtf8String2(decodeBase642(jarmHeader.apu));
|
|
1575
|
-
}
|
|
1576
|
-
if (jarmHeader?.apv) {
|
|
1577
|
-
const jarmRequestNonce = encodeToUtf8String2(decodeBase642(jarmHeader.apv));
|
|
1578
|
-
if (jarmRequestNonce !== authorizationRequestPayload.nonce) {
|
|
1579
|
-
throw new Oauth2Error11("The nonce in the jarm header does not match the nonce in the request.");
|
|
1580
|
-
}
|
|
1581
|
-
}
|
|
1582
1539
|
return {
|
|
1583
1540
|
...validateOpenId4vpResponse,
|
|
1584
|
-
jarm: { ...verifiedJarmResponse, jarmHeader
|
|
1541
|
+
jarm: { ...verifiedJarmResponse, jarmHeader },
|
|
1585
1542
|
expectedNonce: authorizationRequestPayload.nonce,
|
|
1586
|
-
authorizationResponsePayload
|
|
1587
|
-
authorizationRequestPayload
|
|
1543
|
+
authorizationResponsePayload
|
|
1588
1544
|
};
|
|
1589
1545
|
}
|
|
1590
1546
|
|
|
1591
1547
|
// src/authorization-response/parse-authorization-response.ts
|
|
1592
1548
|
async function parseOpenid4vpAuthorizationResponse(options) {
|
|
1593
|
-
const {
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1549
|
+
const { authorizationResponse, callbacks, authorizationRequestPayload, origin } = options;
|
|
1550
|
+
const expectedClientId = getClientId({ authorizationRequestPayload, origin });
|
|
1551
|
+
if (authorizationResponse.response) {
|
|
1552
|
+
return parseJarmAuthorizationResponse({
|
|
1553
|
+
jarmResponseJwt: authorizationResponse.response,
|
|
1554
|
+
callbacks,
|
|
1555
|
+
authorizationRequestPayload,
|
|
1556
|
+
expectedClientId
|
|
1557
|
+
});
|
|
1602
1558
|
}
|
|
1603
|
-
const
|
|
1604
|
-
const
|
|
1605
|
-
|
|
1606
|
-
|
|
1559
|
+
const authorizationResponsePayload = parseOpenid4VpAuthorizationResponsePayload(authorizationResponse);
|
|
1560
|
+
const validatedOpenId4vpResponse = validateOpenid4vpAuthorizationResponsePayload({
|
|
1561
|
+
authorizationRequestPayload,
|
|
1562
|
+
authorizationResponsePayload
|
|
1607
1563
|
});
|
|
1608
1564
|
if (authorizationRequestPayload.response_mode && isJarmResponseMode(authorizationRequestPayload.response_mode)) {
|
|
1609
1565
|
throw new Oauth2ServerErrorResponseError12(
|
|
@@ -1617,10 +1573,9 @@ async function parseOpenid4vpAuthorizationResponse(options) {
|
|
|
1617
1573
|
);
|
|
1618
1574
|
}
|
|
1619
1575
|
return {
|
|
1620
|
-
...
|
|
1576
|
+
...validatedOpenId4vpResponse,
|
|
1621
1577
|
expectedNonce: authorizationRequestPayload.nonce,
|
|
1622
1578
|
authorizationResponsePayload,
|
|
1623
|
-
authorizationRequestPayload,
|
|
1624
1579
|
jarm: void 0
|
|
1625
1580
|
};
|
|
1626
1581
|
}
|
|
@@ -1745,12 +1700,23 @@ var Openid4vpVerifier = class {
|
|
|
1745
1700
|
};
|
|
1746
1701
|
|
|
1747
1702
|
// src/models/z-credential-formats.ts
|
|
1748
|
-
import { z as
|
|
1749
|
-
var zCredentialFormat =
|
|
1703
|
+
import { z as z20 } from "zod";
|
|
1704
|
+
var zCredentialFormat = z20.enum(["jwt_vc_json", "ldp_vc", "ac_vc", "mso_mdoc", "dc+sd-jwt", "vc+sd-jwt"]);
|
|
1750
1705
|
|
|
1751
1706
|
// src/models/z-proof-formats.ts
|
|
1707
|
+
import { z as z21 } from "zod";
|
|
1708
|
+
var zProofFormat = z21.enum(["jwt_vp_json", "ldc_vp", "ac_vp", "dc+sd-jwt", "vc+sd-jwt", "mso_mdoc"]);
|
|
1709
|
+
|
|
1710
|
+
// src/models/z-wallet-metadata.ts
|
|
1752
1711
|
import { z as z22 } from "zod";
|
|
1753
|
-
var
|
|
1712
|
+
var zWalletMetadata = z22.object({
|
|
1713
|
+
presentation_definition_uri_supported: z22.optional(z22.boolean()),
|
|
1714
|
+
vp_formats_supported: zVpFormatsSupported,
|
|
1715
|
+
client_id_schemes_supported: z22.optional(z22.array(zClientIdScheme)),
|
|
1716
|
+
request_object_signing_alg_values_supported: z22.optional(z22.array(z22.string())),
|
|
1717
|
+
authorization_encryption_alg_values_supported: z22.optional(z22.array(z22.string())),
|
|
1718
|
+
authorization_encryption_enc_values_supported: z22.optional(z22.array(z22.string()))
|
|
1719
|
+
});
|
|
1754
1720
|
export {
|
|
1755
1721
|
Openid4vpClient,
|
|
1756
1722
|
Openid4vpVerifier,
|