|
1 | 1 | /*! |
2 | | - * Copyright (c) 2023-2026 Digital Bazaar, Inc. All rights reserved. |
| 2 | + * Copyright (c) 2023-2026 Digital Bazaar, Inc. |
3 | 3 | */ |
4 | 4 | import * as base64url from 'base64url-universal'; |
5 | 5 | import {createNamedError, parseJSON} from '../util.js'; |
6 | 6 | import {calculateJwkThumbprint} from 'jose'; |
7 | 7 | import {decryptAnnexCResponse} from './mdl.js'; |
| 8 | +import {isObject} from '../query/util.js'; |
8 | 9 | import {decrypt as jwtDecrypt} from './jwt.js'; |
9 | 10 |
|
10 | 11 | // start of JSON object, array, or string |
@@ -68,33 +69,48 @@ export async function parseAuthorizationResponse({ |
68 | 69 |
|
69 | 70 | // if payload is set but not a Uint8Array (ISO 18013-7 Annex C case)... |
70 | 71 | 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: |
72 | 89 | // 1. a JSON object (a VP) |
73 | 90 | // 2. a JSON array (of something; unknown media type) |
74 | 91 | // 3. a JSON string (a quoted JWT: "<JWT>") |
75 | 92 | // 4. a JWT (starts with 'ey'...) |
76 | 93 | // 5. a base64url-encoded mDL device response |
77 | 94 | // 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])) { |
81 | 97 | // cases: 1-3 - JSON |
82 | | - parsed.vpToken = parseJSON(vp_token, 'vp_token'); |
| 98 | + parsed.vpToken = parseJSON(vpToken, 'vp_token'); |
83 | 99 | if(typeof parsed.vpToken === 'string') { |
84 | 100 | vpTokenMediaType = 'application/jwt'; |
85 | 101 | } else if(!Array.isArray(parsed.vpToken)) { |
86 | 102 | vpTokenMediaType = 'application/vp'; |
87 | 103 | } |
88 | 104 | } else { |
89 | 105 | // cases 4-5: JWT or mDL device response |
90 | | - parsed.vpToken = vp_token; |
| 106 | + parsed.vpToken = vpToken; |
91 | 107 | // if does not look like a JWT, assume mDL device response |
92 | | - vpTokenMediaType = vp_token.startsWith('ey') ? |
| 108 | + vpTokenMediaType = vpToken.startsWith('ey') ? |
93 | 109 | 'application/jwt' : 'application/mdl-vp-token'; |
94 | 110 | } |
95 | 111 | } else { |
96 | 112 | // unknown case |
97 | | - parsed.vpToken = vp_token; |
| 113 | + parsed.vpToken = vpToken; |
98 | 114 | } |
99 | 115 | } |
100 | 116 |
|
|
0 commit comments