@digitalbazaar/oid4-client 5.8.0 → 5.9.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.
@@ -139,8 +139,10 @@ export function toVpr({authorizationRequest, strict = false} = {}) {
139
139
  client_id,
140
140
  client_metadata,
141
141
  dcql_query,
142
+ expected_origins,
142
143
  nonce,
143
144
  presentation_definition,
145
+ response_mode,
144
146
  response_uri
145
147
  } = authorizationRequest;
146
148
 
@@ -186,9 +188,14 @@ export function toVpr({authorizationRequest, strict = false} = {}) {
186
188
  verifiablePresentationRequest.query = [didAuthnQuery];
187
189
  }
188
190
 
189
- // map `response_uri` or `client_id` to `domain`
191
+ // map `expected_origins` or `response_uri` to `domain`
190
192
  if(response_uri !== undefined || client_id !== undefined) {
191
- verifiablePresentationRequest.domain = response_uri ?? client_id;
193
+ if(response_mode?.startsWith('dc_api') && !response_uri &&
194
+ expected_origins?.length > 0) {
195
+ verifiablePresentationRequest.domain = expected_origins[0];
196
+ } else {
197
+ verifiablePresentationRequest.domain = response_uri;
198
+ }
192
199
  }
193
200
 
194
201
  // map `nonce` to `challenge`
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Copyright (c) 2023-2025 Digital Bazaar, Inc. All rights reserved.
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 _fetch({
64
- requestUrl, getTrustedCertificates, getVerificationKey, agent
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.startsWith(`${clientIdScheme}:`) ?
272
- clientId.slice(clientIdScheme.length + 2) : clientId;
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 _fetch({
328
- requestUrl, getTrustedCertificates, getVerificationKey, agent
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 response = await fetchJSON({url: requestUrl, agent});
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
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@digitalbazaar/oid4-client",
3
- "version": "5.8.0",
3
+ "version": "5.9.0",
4
4
  "description": "An OID4 (VC + VP) client",
5
5
  "homepage": "https://github.com/digitalbazaar/oid4-client",
6
6
  "author": {