Skip to content

Commit 0590856

Browse files
committed
Support vp_token values that are credential response objects.
1 parent 43a0762 commit 0590856

2 files changed

Lines changed: 31 additions & 9 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# @digitalbazaar/oid4-client Changelog
22

3+
## 5.11.0 - 2026-mm-dd
4+
5+
### Added
6+
- Support parsing `vp_token` values that are DCQL credential response
7+
wrappers.
8+
39
## 5.10.0 - 2026-03-30
410

511
### Added

lib/oid4vp/verifier.js

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
/*!
2-
* Copyright (c) 2023-2026 Digital Bazaar, Inc. All rights reserved.
2+
* Copyright (c) 2023-2026 Digital Bazaar, Inc.
33
*/
44
import * as base64url from 'base64url-universal';
55
import {createNamedError, parseJSON} from '../util.js';
66
import {calculateJwkThumbprint} from 'jose';
77
import {decryptAnnexCResponse} from './mdl.js';
8+
import {isObject} from '../query/util.js';
89
import {decrypt as jwtDecrypt} from './jwt.js';
910

1011
// start of JSON object, array, or string
@@ -68,33 +69,48 @@ export async function parseAuthorizationResponse({
6869

6970
// if payload is set but not a Uint8Array (ISO 18013-7 Annex C case)...
7071
if(payload && !(payload instanceof Uint8Array)) {
71-
// `vp_token` is either:
72+
// `vp_token` may be an already parsed object with keys that identify
73+
// credential response query IDs and values that are arrays with one
74+
// or more corresponding presentations; in this case we remove this wrapper
75+
// and we presently assume a single query was responded to with a single
76+
// presentation
77+
const {vp_token} = payload;
78+
let vpToken;
79+
if(isObject(vp_token)) {
80+
const keys = Object.keys(vp_token);
81+
if(keys.length > 0) {
82+
vpToken = vp_token[keys[0]]?.[0];
83+
}
84+
} else {
85+
vpToken = vp_token;
86+
}
87+
88+
// `vpToken` is either:
7289
// 1. a JSON object (a VP)
7390
// 2. a JSON array (of something; unknown media type)
7491
// 3. a JSON string (a quoted JWT: "<JWT>")
7592
// 4. a JWT (starts with 'ey'...)
7693
// 5. a base64url-encoded mDL device response
7794
// 6. unknown
78-
const {vp_token} = payload;
79-
if(typeof vp_token === 'string') {
80-
if(VP_TOKEN_JSON_PREFIXES.has(vp_token[0])) {
95+
if(typeof vpToken === 'string') {
96+
if(VP_TOKEN_JSON_PREFIXES.has(vpToken[0])) {
8197
// cases: 1-3 - JSON
82-
parsed.vpToken = parseJSON(vp_token, 'vp_token');
98+
parsed.vpToken = parseJSON(vpToken, 'vp_token');
8399
if(typeof parsed.vpToken === 'string') {
84100
vpTokenMediaType = 'application/jwt';
85101
} else if(!Array.isArray(parsed.vpToken)) {
86102
vpTokenMediaType = 'application/vp';
87103
}
88104
} else {
89105
// cases 4-5: JWT or mDL device response
90-
parsed.vpToken = vp_token;
106+
parsed.vpToken = vpToken;
91107
// if does not look like a JWT, assume mDL device response
92-
vpTokenMediaType = vp_token.startsWith('ey') ?
108+
vpTokenMediaType = vpToken.startsWith('ey') ?
93109
'application/jwt' : 'application/mdl-vp-token';
94110
}
95111
} else {
96112
// unknown case
97-
parsed.vpToken = vp_token;
113+
parsed.vpToken = vpToken;
98114
}
99115
}
100116

0 commit comments

Comments
 (0)