@digitalbazaar/oid4-client 5.8.0 → 5.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/convert/index.js +24 -6
- package/lib/oid4vp/authorizationRequest.js +30 -9
- package/lib/util.js +9 -1
- package/package.json +1 -1
package/lib/convert/index.js
CHANGED
|
@@ -62,11 +62,18 @@ export function fromVpr({
|
|
|
62
62
|
if(verifiablePresentationRequest.domain) {
|
|
63
63
|
// since a `domain` was provided, set these defaults:
|
|
64
64
|
authorizationRequest.client_id = verifiablePresentationRequest.domain;
|
|
65
|
-
|
|
65
|
+
const usesRedirectUriPrefix =
|
|
66
|
+
authorizationRequest.client_id?.startsWith('redirect_uri:');
|
|
67
|
+
authorizationRequest.response_uri = usesRedirectUriPrefix ?
|
|
68
|
+
authorizationRequest.client_id.slice('redirect_uri:'.length) :
|
|
69
|
+
authorizationRequest.client_id;
|
|
66
70
|
if(useClientIdPrefix) {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
71
|
+
if(!usesRedirectUriPrefix) {
|
|
72
|
+
authorizationRequest.client_id =
|
|
73
|
+
`redirect_uri:${authorizationRequest.client_id}`;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if(usesRedirectUriPrefix) {
|
|
70
77
|
authorizationRequest.client_id_scheme = 'redirect_uri';
|
|
71
78
|
}
|
|
72
79
|
}
|
|
@@ -137,10 +144,13 @@ export function toVpr({authorizationRequest, strict = false} = {}) {
|
|
|
137
144
|
|
|
138
145
|
const {
|
|
139
146
|
client_id,
|
|
147
|
+
client_id_scheme,
|
|
140
148
|
client_metadata,
|
|
141
149
|
dcql_query,
|
|
150
|
+
expected_origins,
|
|
142
151
|
nonce,
|
|
143
152
|
presentation_definition,
|
|
153
|
+
response_mode,
|
|
144
154
|
response_uri
|
|
145
155
|
} = authorizationRequest;
|
|
146
156
|
|
|
@@ -186,9 +196,17 @@ export function toVpr({authorizationRequest, strict = false} = {}) {
|
|
|
186
196
|
verifiablePresentationRequest.query = [didAuthnQuery];
|
|
187
197
|
}
|
|
188
198
|
|
|
189
|
-
// map `
|
|
199
|
+
// map `expected_origins` / `client_id` / `response_uri` to `domain`
|
|
190
200
|
if(response_uri !== undefined || client_id !== undefined) {
|
|
191
|
-
|
|
201
|
+
if(response_mode?.startsWith('dc_api') && !response_uri &&
|
|
202
|
+
expected_origins?.length > 0) {
|
|
203
|
+
verifiablePresentationRequest.domain = expected_origins[0];
|
|
204
|
+
} else if(client_id_scheme === 'redirect_uri' ||
|
|
205
|
+
client_id?.startsWith('redirect_uri:')) {
|
|
206
|
+
verifiablePresentationRequest.domain = client_id ?? response_uri;
|
|
207
|
+
} else {
|
|
208
|
+
verifiablePresentationRequest.domain = response_uri;
|
|
209
|
+
}
|
|
192
210
|
}
|
|
193
211
|
|
|
194
212
|
// map `nonce` to `challenge`
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* Copyright (c) 2023-
|
|
2
|
+
* Copyright (c) 2023-2026 Digital Bazaar, Inc. All rights reserved.
|
|
3
3
|
*/
|
|
4
4
|
import {
|
|
5
5
|
assert, assertOptional, base64Encode,
|
|
@@ -23,13 +23,15 @@ const SUPPORTED_CLIENT_ID_SCHEMES = new Set([
|
|
|
23
23
|
|
|
24
24
|
// get an authorization request from a verifier
|
|
25
25
|
export async function get({
|
|
26
|
-
url, getTrustedCertificates, getVerificationKey, agent
|
|
26
|
+
url, getTrustedCertificates, getVerificationKey, getPostBody, agent,
|
|
27
|
+
overrideMethod
|
|
27
28
|
} = {}) {
|
|
28
29
|
try {
|
|
29
30
|
assert(url, 'url', 'string');
|
|
30
31
|
|
|
31
32
|
let authorizationRequest;
|
|
32
33
|
let requestUrl;
|
|
34
|
+
let requestUrlMethod = 'get';
|
|
33
35
|
let expectedClientId;
|
|
34
36
|
if(url.startsWith('https://')) {
|
|
35
37
|
// the request must be retrieved via HTTP
|
|
@@ -40,6 +42,10 @@ export async function get({
|
|
|
40
42
|
expectedClientId = authorizationRequest.client_id;
|
|
41
43
|
if(authorizationRequest.request_uri) {
|
|
42
44
|
requestUrl = authorizationRequest.request_uri;
|
|
45
|
+
if(authorizationRequest.request_uri_method === 'post' ||
|
|
46
|
+
authorizationRequest.request_uri_method === 'get') {
|
|
47
|
+
requestUrlMethod = authorizationRequest.request_uri_method;
|
|
48
|
+
}
|
|
43
49
|
}
|
|
44
50
|
// if whole request is passed by reference, then it MUST be a signed JWT
|
|
45
51
|
if(authorizationRequest.request) {
|
|
@@ -52,6 +58,11 @@ export async function get({
|
|
|
52
58
|
}
|
|
53
59
|
}
|
|
54
60
|
|
|
61
|
+
// allow method override
|
|
62
|
+
if(overrideMethod) {
|
|
63
|
+
requestUrlMethod = overrideMethod;
|
|
64
|
+
}
|
|
65
|
+
|
|
55
66
|
// fetch request if necessary...
|
|
56
67
|
let fetched = false;
|
|
57
68
|
let response;
|
|
@@ -60,8 +71,9 @@ export async function get({
|
|
|
60
71
|
fetched = true;
|
|
61
72
|
({
|
|
62
73
|
payload: authorizationRequest, response, jwt
|
|
63
|
-
} = await
|
|
64
|
-
|
|
74
|
+
} = await _fetchAuthzRequest({
|
|
75
|
+
method: requestUrlMethod, requestUrl, getPostBody,
|
|
76
|
+
getTrustedCertificates, getVerificationKey, agent
|
|
65
77
|
}));
|
|
66
78
|
}
|
|
67
79
|
|
|
@@ -268,8 +280,8 @@ async function _checkClientIdSchemeRequirements({
|
|
|
268
280
|
}
|
|
269
281
|
|
|
270
282
|
let {client_id: clientId} = authorizationRequest;
|
|
271
|
-
clientId = clientId
|
|
272
|
-
clientId.slice(clientIdScheme.length +
|
|
283
|
+
clientId = clientId?.startsWith(`${clientIdScheme}:`) ?
|
|
284
|
+
clientId.slice(clientIdScheme.length + 1) : clientId;
|
|
273
285
|
|
|
274
286
|
if(clientIdScheme === 'x509_san_dns') {
|
|
275
287
|
// `x509_san_dns` requires leaf cert to have a dNSName ("domain" type) in
|
|
@@ -324,14 +336,21 @@ async function _checkClientIdSchemeRequirements({
|
|
|
324
336
|
}
|
|
325
337
|
}
|
|
326
338
|
|
|
327
|
-
async function
|
|
328
|
-
|
|
339
|
+
async function _fetchAuthzRequest({
|
|
340
|
+
method = 'get', requestUrl, getPostBody,
|
|
341
|
+
getTrustedCertificates, getVerificationKey, agent
|
|
329
342
|
}) {
|
|
330
343
|
// FIXME: every `fetchJSON` call needs to use a block list or other
|
|
331
344
|
// protections to prevent a confused deputy attack where the `requestUrl`
|
|
332
345
|
// accesses a location it should not, e.g., a URL `localhost` is used when
|
|
333
346
|
// it shouldn't be
|
|
334
|
-
const
|
|
347
|
+
const options = {url: requestUrl, agent};
|
|
348
|
+
if(method === 'post') {
|
|
349
|
+
const {body} = await getPostBody?.() ?? new URLSearchParams();
|
|
350
|
+
options.method = 'post';
|
|
351
|
+
options.body = body ?? new URLSearchParams();
|
|
352
|
+
}
|
|
353
|
+
const response = await fetchJSON(options);
|
|
335
354
|
|
|
336
355
|
// parse payload from response data...
|
|
337
356
|
const contentType = response.headers.get('content-type');
|
|
@@ -422,6 +441,7 @@ function _parseOID4VPUrl({url}) {
|
|
|
422
441
|
const {searchParams} = new URL(url);
|
|
423
442
|
const request = _get(searchParams, 'request');
|
|
424
443
|
const request_uri = _get(searchParams, 'request_uri');
|
|
444
|
+
const request_uri_method = _get(searchParams, 'request_uri_method');
|
|
425
445
|
const response_type = _get(searchParams, 'response_type');
|
|
426
446
|
const response_mode = _get(searchParams, 'response_mode');
|
|
427
447
|
const presentation_definition = _get(
|
|
@@ -452,6 +472,7 @@ function _parseOID4VPUrl({url}) {
|
|
|
452
472
|
const authorizationRequest = {
|
|
453
473
|
request,
|
|
454
474
|
request_uri,
|
|
475
|
+
request_uri_method,
|
|
455
476
|
response_type,
|
|
456
477
|
response_mode,
|
|
457
478
|
presentation_definition: presentation_definition &&
|
package/lib/util.js
CHANGED
|
@@ -47,7 +47,7 @@ export function createNamedError({message, name, details, cause} = {}) {
|
|
|
47
47
|
return error;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
export function fetchJSON({url, agent} = {}) {
|
|
50
|
+
export function fetchJSON({method = 'get', url, body, json, agent} = {}) {
|
|
51
51
|
// allow these params to be passed / configured
|
|
52
52
|
const fetchOptions = {
|
|
53
53
|
// max size for issuer config related responses (in bytes, ~4 KiB)
|
|
@@ -57,6 +57,14 @@ export function fetchJSON({url, agent} = {}) {
|
|
|
57
57
|
agent
|
|
58
58
|
};
|
|
59
59
|
|
|
60
|
+
if(method === 'post') {
|
|
61
|
+
if(body !== undefined) {
|
|
62
|
+
fetchOptions.body = body;
|
|
63
|
+
} else if(json !== undefined) {
|
|
64
|
+
fetchOptions.json = json;
|
|
65
|
+
}
|
|
66
|
+
return httpClient.post(url, fetchOptions);
|
|
67
|
+
}
|
|
60
68
|
return httpClient.get(url, fetchOptions);
|
|
61
69
|
}
|
|
62
70
|
|