@bedrock/vc-delivery 7.12.0 → 7.13.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.
- package/lib/ExchangeProcessor.js +1 -1
- package/lib/helpers.js +1 -7
- package/lib/oid4/authorizationRequest.js +31 -9
- package/lib/oid4/http.js +21 -2
- package/lib/oid4/oid4vp.js +85 -16
- package/lib/storage/exchanges.js +1 -0
- package/package.json +2 -2
- package/schemas/bedrock-vc-workflow.js +8 -0
package/lib/ExchangeProcessor.js
CHANGED
|
@@ -479,7 +479,6 @@ export class ExchangeProcessor {
|
|
|
479
479
|
|
|
480
480
|
async function _getStep({workflow, exchange}) {
|
|
481
481
|
const currentStep = exchange.step;
|
|
482
|
-
|
|
483
482
|
if(!currentStep) {
|
|
484
483
|
// return default empty step and set dummy stepname for exchange
|
|
485
484
|
exchange.step = 'initial';
|
|
@@ -562,6 +561,7 @@ function _isInitialStep({workflow, exchange}) {
|
|
|
562
561
|
|
|
563
562
|
async function _updateExchange({workflow, exchange, meta, step}) {
|
|
564
563
|
try {
|
|
564
|
+
exchange.referenceId = globalThis.crypto.randomUUID();
|
|
565
565
|
exchange.sequence++;
|
|
566
566
|
if(exchange.state === 'complete') {
|
|
567
567
|
await exchanges.complete({workflowId: workflow.id, exchange});
|
package/lib/helpers.js
CHANGED
|
@@ -115,7 +115,7 @@ export async function evaluateTemplate({
|
|
|
115
115
|
export async function evaluateExchangeStep({
|
|
116
116
|
workflow, exchange, stepName = exchange.step
|
|
117
117
|
}) {
|
|
118
|
-
let step = workflow.steps[stepName];
|
|
118
|
+
let step = workflow.steps[stepName] ?? {};
|
|
119
119
|
if(step.stepTemplate) {
|
|
120
120
|
step = await evaluateTemplate({
|
|
121
121
|
workflow, exchange, typedTemplate: step.stepTemplate
|
|
@@ -349,12 +349,6 @@ export function stripStacktrace(error) {
|
|
|
349
349
|
|
|
350
350
|
export async function validateStep({step} = {}) {
|
|
351
351
|
// FIXME: use `ajv` and do JSON schema check
|
|
352
|
-
if(Object.keys(step).length === 0) {
|
|
353
|
-
throw new BedrockError('Empty exchange step detected.', {
|
|
354
|
-
name: 'DataError',
|
|
355
|
-
details: {httpStatusCode: 500, public: true}
|
|
356
|
-
});
|
|
357
|
-
}
|
|
358
352
|
if(step.issueRequests !== undefined && !Array.isArray(step.issueRequests)) {
|
|
359
353
|
throw new BedrockError(
|
|
360
354
|
'Invalid "issueRequests" in step.', {
|
|
@@ -16,6 +16,10 @@ const ENCRYPTED_RESPONSE_MODES = new Set([
|
|
|
16
16
|
'direct_post.jwt', 'dc_api.jwt', 'dc_api'
|
|
17
17
|
]);
|
|
18
18
|
const OID4VP_JWT_TYP = 'oauth-authz-req+jwt';
|
|
19
|
+
const SUPPORTED_CLIENT_ID_SCHEMES = new Set([
|
|
20
|
+
'redirect_uri', 'x509_san_dns', 'x509_hash', 'decentralized_identifier'
|
|
21
|
+
]);
|
|
22
|
+
|
|
19
23
|
const TEXT_ENCODER = new TextEncoder();
|
|
20
24
|
|
|
21
25
|
export async function create({
|
|
@@ -30,11 +34,14 @@ export async function create({
|
|
|
30
34
|
|
|
31
35
|
// get params from step OID4VP client profile to apply to the AR
|
|
32
36
|
const {
|
|
33
|
-
client_id,
|
|
37
|
+
client_id,
|
|
38
|
+
client_id_scheme,
|
|
34
39
|
dcql_query,
|
|
40
|
+
expected_origins,
|
|
35
41
|
nonce,
|
|
36
42
|
presentation_definition,
|
|
37
|
-
response_mode,
|
|
43
|
+
response_mode,
|
|
44
|
+
response_uri
|
|
38
45
|
} = clientProfile;
|
|
39
46
|
const clientBaseUrl = getClientBaseUrl({workflow, exchange, clientProfileId});
|
|
40
47
|
|
|
@@ -57,10 +64,13 @@ export async function create({
|
|
|
57
64
|
`${clientBaseUrl}/authorization/response`;
|
|
58
65
|
|
|
59
66
|
// client_id (defaults to `response_uri`)
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
authorizationRequest.
|
|
63
|
-
|
|
67
|
+
if(client_id) {
|
|
68
|
+
authorizationRequest.client_id = client_id;
|
|
69
|
+
} else if(authorizationRequest.client_id_scheme === 'redirect_uri') {
|
|
70
|
+
// use prefix; this is compatible with both draft 18 and 1.0+
|
|
71
|
+
authorizationRequest.client_id =
|
|
72
|
+
`redirect_uri:${authorizationRequest.response_uri}`;
|
|
73
|
+
}
|
|
64
74
|
|
|
65
75
|
// `x509_san_dns` requires the `direct_post.jwt` response mode when using
|
|
66
76
|
// `direct_post`
|
|
@@ -71,6 +81,10 @@ export async function create({
|
|
|
71
81
|
authorizationRequest.response_mode += '.jwt';
|
|
72
82
|
}
|
|
73
83
|
|
|
84
|
+
// expected origins; safe to always include
|
|
85
|
+
authorizationRequest.expected_origins = expected_origins ??
|
|
86
|
+
[new URL(authorizationRequest.response_uri).origin];
|
|
87
|
+
|
|
74
88
|
// nonce
|
|
75
89
|
if(nonce) {
|
|
76
90
|
authorizationRequest.nonce = nonce;
|
|
@@ -117,6 +131,16 @@ export async function encode({
|
|
|
117
131
|
return jwt;
|
|
118
132
|
}
|
|
119
133
|
|
|
134
|
+
export function removeClientIdPrefix({clientId} = {}) {
|
|
135
|
+
for(const idScheme of SUPPORTED_CLIENT_ID_SCHEMES) {
|
|
136
|
+
const prefix = `${idScheme}:`;
|
|
137
|
+
if(clientId.startsWith(prefix)) {
|
|
138
|
+
return clientId.slice(prefix.length);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return clientId;
|
|
142
|
+
}
|
|
143
|
+
|
|
120
144
|
async function _createClientMetaData({
|
|
121
145
|
authorizationRequest, clientProfile
|
|
122
146
|
} = {}) {
|
|
@@ -247,9 +271,7 @@ async function _createJwt({workflow, clientProfile, authorizationRequest}) {
|
|
|
247
271
|
const kid = keyDescription.id;
|
|
248
272
|
|
|
249
273
|
// create the JWT payload and header to be signed
|
|
250
|
-
const payload = {
|
|
251
|
-
...authorizationRequest
|
|
252
|
-
};
|
|
274
|
+
const payload = {...authorizationRequest};
|
|
253
275
|
const protectedHeader = {typ: OID4VP_JWT_TYP, alg: 'ES256', kid, x5c};
|
|
254
276
|
|
|
255
277
|
// create the JWT
|
package/lib/oid4/http.js
CHANGED
|
@@ -328,21 +328,37 @@ export async function createRoutes({
|
|
|
328
328
|
}));
|
|
329
329
|
|
|
330
330
|
// an OID4VP verifier endpoint
|
|
331
|
-
// serves the authorization request
|
|
331
|
+
// serves the authorization request
|
|
332
332
|
// associated with the current step in the exchange
|
|
333
|
+
app.options(routes.authorizationRequest, cors());
|
|
333
334
|
app.get(
|
|
334
335
|
routes.authorizationRequest,
|
|
335
336
|
cors(),
|
|
336
337
|
getConfigMiddleware,
|
|
337
338
|
getExchange,
|
|
338
339
|
asyncHandler(_handleOid4vpAuthzRequest));
|
|
340
|
+
// same as above but allows wallet to submit metadata
|
|
341
|
+
app.post(
|
|
342
|
+
routes.authorizationRequest,
|
|
343
|
+
cors(),
|
|
344
|
+
getConfigMiddleware,
|
|
345
|
+
getExchange,
|
|
346
|
+
asyncHandler(_handleOid4vpAuthzRequest));
|
|
339
347
|
// same as above but handling is based on specific client profile
|
|
348
|
+
app.options(routes.profiledAuthorizationRequest, cors());
|
|
340
349
|
app.get(
|
|
341
350
|
routes.profiledAuthorizationRequest,
|
|
342
351
|
cors(),
|
|
343
352
|
getConfigMiddleware,
|
|
344
353
|
getExchange,
|
|
345
354
|
asyncHandler(_handleOid4vpAuthzRequest));
|
|
355
|
+
// same as above but allows wallet to submit metadata
|
|
356
|
+
app.post(
|
|
357
|
+
routes.profiledAuthorizationRequest,
|
|
358
|
+
cors(),
|
|
359
|
+
getConfigMiddleware,
|
|
360
|
+
getExchange,
|
|
361
|
+
asyncHandler(_handleOid4vpAuthzRequest));
|
|
346
362
|
|
|
347
363
|
// an OID4VP verifier endpoint
|
|
348
364
|
// receives an authorization response with vp_token
|
|
@@ -375,13 +391,16 @@ async function _handleOid4vpAuthzRequest(req, res) {
|
|
|
375
391
|
const {clientProfileId} = req.params;
|
|
376
392
|
let result;
|
|
377
393
|
try {
|
|
394
|
+
// FIXME: consider passing `body` to modulate authz request that is
|
|
395
|
+
// returned in response; presently any wallet metadata is ignored
|
|
378
396
|
const {
|
|
379
397
|
authorizationRequest,
|
|
380
398
|
clientProfile
|
|
381
399
|
} = await oid4vp.getAuthorizationRequest({req, clientProfileId});
|
|
382
400
|
const {config: workflow} = req.serviceObject;
|
|
383
401
|
result = await oid4vp.encodeAuthorizationRequest({
|
|
384
|
-
workflow, clientProfile, authorizationRequest
|
|
402
|
+
workflow, clientProfile, authorizationRequest,
|
|
403
|
+
requestMethod: req.method.toLowerCase()
|
|
385
404
|
});
|
|
386
405
|
res.set('content-type', 'application/oauth-authz-req+jwt');
|
|
387
406
|
} catch(error) {
|
package/lib/oid4/oid4vp.js
CHANGED
|
@@ -2,13 +2,16 @@
|
|
|
2
2
|
* Copyright (c) 2022-2026 Digital Bazaar, Inc. All rights reserved.
|
|
3
3
|
*/
|
|
4
4
|
import * as bedrock from '@bedrock/core';
|
|
5
|
+
import {
|
|
6
|
+
create as createAuthorizationRequest,
|
|
7
|
+
removeClientIdPrefix
|
|
8
|
+
} from './authorizationRequest.js';
|
|
5
9
|
import {
|
|
6
10
|
evaluateExchangeStep,
|
|
7
11
|
resolveVariableName,
|
|
8
12
|
setVariable
|
|
9
13
|
} from '../helpers.js';
|
|
10
14
|
import {getClientBaseUrl, getClientProfile} from './clientProfiles.js';
|
|
11
|
-
import {create as createAuthorizationRequest} from './authorizationRequest.js';
|
|
12
15
|
import {verify as defaultVerify} from '../verify.js';
|
|
13
16
|
import {ExchangeProcessor} from '../ExchangeProcessor.js';
|
|
14
17
|
import {oid4vp} from '@digitalbazaar/oid4-client';
|
|
@@ -92,27 +95,26 @@ export async function getOID4VPProtocols({workflow, exchange, step}) {
|
|
|
92
95
|
// profile name
|
|
93
96
|
const protocols = {};
|
|
94
97
|
for(const [clientProfileId, clientProfile] of clientProfiles) {
|
|
95
|
-
//
|
|
96
|
-
const {
|
|
97
|
-
protocolUrlParameters: {
|
|
98
|
-
name = 'OID4VP',
|
|
99
|
-
scheme = 'openid4vp'
|
|
100
|
-
} = {}
|
|
101
|
-
} = clientProfile;
|
|
98
|
+
// get supported protocol URL parameters
|
|
99
|
+
const {name, scheme, version} = _getProtocolUrlParameters({clientProfile});
|
|
102
100
|
|
|
103
101
|
// generate default OID4VP protocol URL
|
|
104
102
|
const clientBaseUrl = getClientBaseUrl({
|
|
105
103
|
workflow, exchange, clientProfileId
|
|
106
104
|
});
|
|
107
105
|
const {
|
|
108
|
-
authorizationRequest
|
|
106
|
+
authorizationRequest
|
|
109
107
|
} = await _getOrCreateStepAuthorizationRequest({
|
|
110
108
|
workflow, exchange, clientProfileId, clientProfile, step
|
|
111
109
|
});
|
|
110
|
+
const {client_id, request_uri_method} = authorizationRequest;
|
|
112
111
|
const searchParams = new URLSearchParams({
|
|
113
112
|
client_id,
|
|
114
113
|
request_uri: `${clientBaseUrl}/authorization/request`
|
|
115
114
|
});
|
|
115
|
+
if(request_uri_method && version !== 'OID4VP-draft18') {
|
|
116
|
+
searchParams.set('request_uri_method', request_uri_method);
|
|
117
|
+
}
|
|
116
118
|
protocols[name] = `${scheme}://?${searchParams}`;
|
|
117
119
|
}
|
|
118
120
|
return protocols;
|
|
@@ -191,8 +193,6 @@ export async function processAuthorizationResponse({req, clientProfileId}) {
|
|
|
191
193
|
verifyPresentationOptions.challenge = authorizationRequest.nonce;
|
|
192
194
|
verifyPresentationOptions.domain = authorizationRequest.response_uri;
|
|
193
195
|
|
|
194
|
-
// FIXME: OID4VP 1.0+ does not have a presentation submission
|
|
195
|
-
// handle mDL submission
|
|
196
196
|
const {envelope} = parseResponseResult;
|
|
197
197
|
if(envelope?.mediaType === 'application/mdl-vp-token') {
|
|
198
198
|
// generate `handover` for mDL verification
|
|
@@ -205,8 +205,7 @@ export async function processAuthorizationResponse({req, clientProfileId}) {
|
|
|
205
205
|
|
|
206
206
|
// `direct_post.jwt` => ISO18013-7 Annex B
|
|
207
207
|
// FIXME: same response mode is also used for OID4VP 1.0 with
|
|
208
|
-
// `OpenID4VPHandover`
|
|
209
|
-
// this is not yet supported
|
|
208
|
+
// `OpenID4VPHandover` for non-Annex-B; this is not yet supported
|
|
210
209
|
// https://openid.net/specs/openid-4-verifiable-presentations-1_0.html#name-invocation-via-redirects
|
|
211
210
|
const {responseMode} = parseResponseResult;
|
|
212
211
|
if(responseMode === 'direct_post.jwt') {
|
|
@@ -270,8 +269,6 @@ export async function processAuthorizationResponse({req, clientProfileId}) {
|
|
|
270
269
|
presentationSubmission
|
|
271
270
|
}
|
|
272
271
|
};
|
|
273
|
-
// FIXME: do w/o `parseResponseResult.envelope` to eliminate envelope
|
|
274
|
-
// parsing (let verifier do it)
|
|
275
272
|
if(parseResponseResult.envelope) {
|
|
276
273
|
// include enveloped VP in step result
|
|
277
274
|
exchange.variables.results[exchange.step]
|
|
@@ -296,6 +293,21 @@ export async function supportsOID4VP({workflow, exchange, step}) {
|
|
|
296
293
|
return step.openId !== undefined;
|
|
297
294
|
}
|
|
298
295
|
|
|
296
|
+
function _getProtocolUrlParameters({clientProfile}) {
|
|
297
|
+
const protocolUrlParameters = {
|
|
298
|
+
name: 'OID4VP',
|
|
299
|
+
scheme: 'openid4vp',
|
|
300
|
+
version: undefined,
|
|
301
|
+
...clientProfile.protocolUrlParameters
|
|
302
|
+
};
|
|
303
|
+
if(protocolUrlParameters.version === undefined) {
|
|
304
|
+
protocolUrlParameters.version =
|
|
305
|
+
protocolUrlParameters.scheme === 'mdoc-openid4vp' ?
|
|
306
|
+
'OID4VP-draft18' : 'OID4VP-1.0';
|
|
307
|
+
}
|
|
308
|
+
return protocolUrlParameters;
|
|
309
|
+
}
|
|
310
|
+
|
|
299
311
|
async function _getOrCreateStepAuthorizationRequest({
|
|
300
312
|
workflow, exchange, clientProfileId, clientProfile, step
|
|
301
313
|
}) {
|
|
@@ -304,6 +316,9 @@ async function _getOrCreateStepAuthorizationRequest({
|
|
|
304
316
|
// get authorization request
|
|
305
317
|
authorizationRequest = clientProfile.authorizationRequest;
|
|
306
318
|
if(authorizationRequest) {
|
|
319
|
+
authorizationRequest = _normalizeAuthorizationRequest({
|
|
320
|
+
authorizationRequest, exchange, clientProfile
|
|
321
|
+
});
|
|
307
322
|
return {authorizationRequest, exchangeChanged: false};
|
|
308
323
|
}
|
|
309
324
|
|
|
@@ -328,6 +343,9 @@ async function _getOrCreateStepAuthorizationRequest({
|
|
|
328
343
|
variables: exchange.variables, name: authzReqVarName
|
|
329
344
|
});
|
|
330
345
|
if(authorizationRequest) {
|
|
346
|
+
authorizationRequest = _normalizeAuthorizationRequest({
|
|
347
|
+
authorizationRequest, exchange, clientProfile
|
|
348
|
+
});
|
|
331
349
|
return {authorizationRequest, exchangeChanged: false};
|
|
332
350
|
}
|
|
333
351
|
|
|
@@ -338,7 +356,9 @@ async function _getOrCreateStepAuthorizationRequest({
|
|
|
338
356
|
clientProfile, clientProfileId,
|
|
339
357
|
verifiablePresentationRequest
|
|
340
358
|
});
|
|
341
|
-
authorizationRequest =
|
|
359
|
+
authorizationRequest = _normalizeAuthorizationRequest({
|
|
360
|
+
authorizationRequest: result.authorizationRequest, exchange, clientProfile
|
|
361
|
+
});
|
|
342
362
|
|
|
343
363
|
// merge any newly created exchange secrets
|
|
344
364
|
exchange.secrets = {
|
|
@@ -365,6 +385,55 @@ async function _getOrCreateStepAuthorizationRequest({
|
|
|
365
385
|
return {authorizationRequest, exchangeChanged: true};
|
|
366
386
|
}
|
|
367
387
|
|
|
388
|
+
function _normalizeAuthorizationRequest({
|
|
389
|
+
authorizationRequest, exchange, clientProfile
|
|
390
|
+
}) {
|
|
391
|
+
const {
|
|
392
|
+
client_id, client_id_scheme, request_uri_method, state
|
|
393
|
+
} = authorizationRequest;
|
|
394
|
+
authorizationRequest = {...authorizationRequest};
|
|
395
|
+
|
|
396
|
+
// get any explicit version to be used with client profile
|
|
397
|
+
const {version} = _getProtocolUrlParameters({clientProfile});
|
|
398
|
+
|
|
399
|
+
// if `version` is OID4VP draft 18, remove any `client_id_scheme` prefix
|
|
400
|
+
// from the `client_id`; otherwise add it
|
|
401
|
+
if(version === 'OID4VP-draft18') {
|
|
402
|
+
authorizationRequest.client_id = removeClientIdPrefix({
|
|
403
|
+
clientId: client_id
|
|
404
|
+
});
|
|
405
|
+
return authorizationRequest;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// version is OID4VP 1.0+ or that + compatibility w/Draft18...
|
|
409
|
+
if(client_id_scheme && client_id && !client_id.startsWith(client_id_scheme)) {
|
|
410
|
+
// note: for `redirect_uri` `client_id_scheme`, it is ok to always include
|
|
411
|
+
// `redirect_uri:` prefix in the client ID, even for versions that support
|
|
412
|
+
// Draft 18 compatibility along with other versions, as the client ID
|
|
413
|
+
// should be treated as opaque when using `response_mode=direct*` and
|
|
414
|
+
// omitting the `redirect_uri` parameter; which is the only supported
|
|
415
|
+
// configuration in this implementation for Draft 18 clients
|
|
416
|
+
authorizationRequest.client_id = `${client_id_scheme}:${client_id}`;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// OID4VP 1.0+ requires `state` to be included for authz requests that do
|
|
420
|
+
// not require "holder binding", but always including it does not cause any
|
|
421
|
+
// known issues, so just include `state` using `referenceId` (if set) or
|
|
422
|
+
// `localExchangeId`
|
|
423
|
+
if(!state && oid4vp.authzRequest.usesClientIdScheme({
|
|
424
|
+
authorizationRequest, scheme: 'redirect_uri'
|
|
425
|
+
})) {
|
|
426
|
+
authorizationRequest.state = exchange.referenceId ?? exchange.id;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
// default to `request_uri_method=post` in OID4VP 1.0+
|
|
430
|
+
if(!request_uri_method) {
|
|
431
|
+
authorizationRequest.request_uri_method = 'post';
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
return authorizationRequest;
|
|
435
|
+
}
|
|
436
|
+
|
|
368
437
|
function _throwUnsupportedProtocol() {
|
|
369
438
|
throw new BedrockError('OID4VP is not supported by this exchange.', {
|
|
370
439
|
name: 'NotSupportedError',
|
package/lib/storage/exchanges.js
CHANGED
|
@@ -568,6 +568,7 @@ function _buildUpdate({exchange}) {
|
|
|
568
568
|
const update = {
|
|
569
569
|
$inc: {'exchange.sequence': 1},
|
|
570
570
|
$set: {
|
|
571
|
+
'exchange.referenceId': exchange.referenceId ?? exchange.id,
|
|
571
572
|
'exchange.state': exchange.state,
|
|
572
573
|
'exchange.secrets': exchange.secrets,
|
|
573
574
|
'exchange.variables': exchange.variables,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bedrock/vc-delivery",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.13.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Bedrock Verifiable Credential Delivery",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"@digitalbazaar/ed25519-signature-2020": "^5.4.0",
|
|
41
41
|
"@digitalbazaar/ezcap": "^4.1.0",
|
|
42
42
|
"@digitalbazaar/http-client": "^4.2.0",
|
|
43
|
-
"@digitalbazaar/oid4-client": "^5.
|
|
43
|
+
"@digitalbazaar/oid4-client": "^5.9.0",
|
|
44
44
|
"@digitalbazaar/vc": "^7.2.0",
|
|
45
45
|
"@digitalbazaar/webkms-client": "^14.2.0",
|
|
46
46
|
"assert-plus": "^1.0.0",
|
|
@@ -472,6 +472,10 @@ const oid4vpClientProfile = {
|
|
|
472
472
|
presentation_definition: {type: 'object'},
|
|
473
473
|
response_mode: {type: 'string'},
|
|
474
474
|
response_uri: {type: 'string'},
|
|
475
|
+
response_uri_method: {
|
|
476
|
+
type: 'string',
|
|
477
|
+
enum: ['get', 'post']
|
|
478
|
+
},
|
|
475
479
|
// optional parameters for signing authorization requests
|
|
476
480
|
authorizationRequestSigningParameters: {
|
|
477
481
|
type: 'object',
|
|
@@ -498,6 +502,10 @@ const oid4vpClientProfile = {
|
|
|
498
502
|
},
|
|
499
503
|
scheme: {
|
|
500
504
|
type: 'string'
|
|
505
|
+
},
|
|
506
|
+
version: {
|
|
507
|
+
type: 'string',
|
|
508
|
+
enum: ['OID4VP-draft18', 'OID4VP-1.0']
|
|
501
509
|
}
|
|
502
510
|
}
|
|
503
511
|
},
|