@bedrock/vc-delivery 4.7.0 → 5.0.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/helpers.js +28 -0
- package/lib/openId.js +20 -6
- package/lib/vcapi.js +15 -0
- package/lib/verify.js +41 -9
- package/package.json +23 -24
- package/schemas/bedrock-vc-workflow.js +154 -3
package/lib/helpers.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import * as bedrock from '@bedrock/core';
|
|
5
5
|
import {decodeId, generateId} from 'bnid';
|
|
6
|
+
import {decodeJwt} from 'jose';
|
|
6
7
|
import {Ed25519Signature2020} from '@digitalbazaar/ed25519-signature-2020';
|
|
7
8
|
import {httpsAgent} from '@bedrock/https-agent';
|
|
8
9
|
import jsonata from 'jsonata';
|
|
@@ -102,3 +103,30 @@ export function decodeLocalId({localId} = {}) {
|
|
|
102
103
|
expectedSize: 16
|
|
103
104
|
}));
|
|
104
105
|
}
|
|
106
|
+
|
|
107
|
+
export async function unenvelopeCredential({envelopedCredential} = {}) {
|
|
108
|
+
let credential;
|
|
109
|
+
const {id} = envelopedCredential;
|
|
110
|
+
if(id?.startsWith('data:application/jwt,')) {
|
|
111
|
+
const format = 'application/jwt';
|
|
112
|
+
const jwt = id.slice('data:application/jwt,'.length);
|
|
113
|
+
const claimset = decodeJwt(jwt);
|
|
114
|
+
// FIXME: perform various field mappings as needed
|
|
115
|
+
console.log('VC-JWT claimset', credential);
|
|
116
|
+
return {credential: claimset.vc, format};
|
|
117
|
+
}
|
|
118
|
+
throw new Error('Not implemented.');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export async function unenvelopePresentation({envelopedPresentation} = {}) {
|
|
122
|
+
const {id} = envelopedPresentation;
|
|
123
|
+
if(id?.startsWith('data:application/jwt,')) {
|
|
124
|
+
const format = 'application/jwt';
|
|
125
|
+
const jwt = id.slice('data:application/jwt,'.length);
|
|
126
|
+
const claimset = decodeJwt(jwt);
|
|
127
|
+
// FIXME: perform various field mappings as needed
|
|
128
|
+
console.log('VC-JWT claimset', claimset);
|
|
129
|
+
return {presentation: claimset.vp, format};
|
|
130
|
+
}
|
|
131
|
+
throw new Error('Not implemented.');
|
|
132
|
+
}
|
package/lib/openId.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import * as bedrock from '@bedrock/core';
|
|
5
5
|
import * as exchanges from './exchanges.js';
|
|
6
6
|
import {
|
|
7
|
-
compile,
|
|
7
|
+
compile, createValidateMiddleware as validate
|
|
8
8
|
} from '@bedrock/validation';
|
|
9
9
|
import {evaluateTemplate, getWorkflowIssuerInstances} from './helpers.js';
|
|
10
10
|
import {importJWK, SignJWT} from 'jose';
|
|
@@ -13,7 +13,8 @@ import {
|
|
|
13
13
|
openIdBatchCredentialBody,
|
|
14
14
|
openIdCredentialBody,
|
|
15
15
|
openIdTokenBody,
|
|
16
|
-
presentationSubmission as presentationSubmissionSchema
|
|
16
|
+
presentationSubmission as presentationSubmissionSchema,
|
|
17
|
+
verifiablePresentation as verifiablePresentationSchema
|
|
17
18
|
} from '../schemas/bedrock-vc-workflow.js';
|
|
18
19
|
import {verify, verifyDidProofJwt} from './verify.js';
|
|
19
20
|
import {asyncHandler} from '@bedrock/express';
|
|
@@ -84,7 +85,7 @@ export async function createRoutes({
|
|
|
84
85
|
|
|
85
86
|
// create validators for x-www-form-urlencoded parsed data
|
|
86
87
|
const validatePresentation = compile(
|
|
87
|
-
{schema:
|
|
88
|
+
{schema: verifiablePresentationSchema()});
|
|
88
89
|
const validatePresentationSubmission = compile(
|
|
89
90
|
{schema: presentationSubmissionSchema});
|
|
90
91
|
|
|
@@ -916,6 +917,22 @@ async function _processAuthorizationResponse({
|
|
|
916
917
|
const {authorizationRequest, step} = arRequest;
|
|
917
918
|
({exchange} = arRequest);
|
|
918
919
|
|
|
920
|
+
// FIXME: if the VP is enveloped, remove the envelope to validate or
|
|
921
|
+
// run validation code after verification if necessary
|
|
922
|
+
|
|
923
|
+
// FIXME: check the VP against the presentation submission if requested
|
|
924
|
+
// FIXME: check the VP against "trustedIssuer" in VPR, if provided
|
|
925
|
+
const {presentationSchema} = step;
|
|
926
|
+
if(presentationSchema) {
|
|
927
|
+
// validate the received VP
|
|
928
|
+
const {jsonSchema: schema} = presentationSchema;
|
|
929
|
+
const validate = compile({schema});
|
|
930
|
+
const {valid, error} = validate(presentation);
|
|
931
|
+
if(!valid) {
|
|
932
|
+
throw error;
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
|
|
919
936
|
// verify the received VP
|
|
920
937
|
const {verifiablePresentationRequest} = await oid4vp.toVpr(
|
|
921
938
|
{authorizationRequest});
|
|
@@ -928,9 +945,6 @@ async function _processAuthorizationResponse({
|
|
|
928
945
|
expectedChallenge: authorizationRequest.nonce
|
|
929
946
|
});
|
|
930
947
|
|
|
931
|
-
// FIXME: check the VP against the presentation submission if requested
|
|
932
|
-
// FIXME: check the VP against "trustedIssuer" in VPR, if provided
|
|
933
|
-
|
|
934
948
|
// store VP results in variables associated with current step
|
|
935
949
|
const currentStep = exchange.step;
|
|
936
950
|
if(!exchange.variables.results) {
|
package/lib/vcapi.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import * as bedrock from '@bedrock/core';
|
|
5
5
|
import * as exchanges from './exchanges.js';
|
|
6
6
|
import {createChallenge as _createChallenge, verify} from './verify.js';
|
|
7
|
+
import {compile} from '@bedrock/validation';
|
|
7
8
|
import {evaluateTemplate} from './helpers.js';
|
|
8
9
|
import {issue} from './issue.js';
|
|
9
10
|
import {klona} from 'klona';
|
|
@@ -95,6 +96,20 @@ export async function processExchange({req, res, workflow, exchange}) {
|
|
|
95
96
|
return;
|
|
96
97
|
}
|
|
97
98
|
|
|
99
|
+
// FIXME: if the VP is enveloped, remove the envelope to validate or
|
|
100
|
+
// run validation code after verification if necessary
|
|
101
|
+
|
|
102
|
+
const {presentationSchema} = step;
|
|
103
|
+
if(presentationSchema) {
|
|
104
|
+
// validate the received VP
|
|
105
|
+
const {jsonSchema: schema} = presentationSchema;
|
|
106
|
+
const validate = compile({schema});
|
|
107
|
+
const {valid, error} = validate(receivedPresentation);
|
|
108
|
+
if(!valid) {
|
|
109
|
+
throw error;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
98
113
|
// verify the received VP
|
|
99
114
|
const expectedChallenge = isInitialStep ? exchange.id : undefined;
|
|
100
115
|
const {allowUnprotectedPresentation = false} = step;
|
package/lib/verify.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Copyright (c) 2022-2024 Digital Bazaar, Inc. All rights reserved.
|
|
3
3
|
*/
|
|
4
4
|
import * as bedrock from '@bedrock/core';
|
|
5
|
+
import * as EcdsaMultikey from '@digitalbazaar/ecdsa-multikey';
|
|
5
6
|
import * as Ed25519Multikey from '@digitalbazaar/ed25519-multikey';
|
|
6
7
|
import {importJWK, jwtVerify} from 'jose';
|
|
7
8
|
import {didIo} from '@bedrock/did-io';
|
|
@@ -9,6 +10,10 @@ import {getZcapClient} from './helpers.js';
|
|
|
9
10
|
|
|
10
11
|
const {util: {BedrockError}} = bedrock;
|
|
11
12
|
|
|
13
|
+
// supported JWT algs
|
|
14
|
+
const ECDSA_ALGS = ['ES256', 'ES384'];
|
|
15
|
+
const EDDSA_ALGS = ['Ed25519', 'EdDSA'];
|
|
16
|
+
|
|
12
17
|
export async function createChallenge({workflow} = {}) {
|
|
13
18
|
// create zcap client for creating challenges
|
|
14
19
|
const {zcapClient, zcaps} = await getZcapClient({workflow});
|
|
@@ -134,23 +139,50 @@ export async function verifyDidProofJwt({workflow, exchange, jwt} = {}) {
|
|
|
134
139
|
const audience = exchangeId;
|
|
135
140
|
|
|
136
141
|
let issuer;
|
|
137
|
-
|
|
138
|
-
|
|
142
|
+
// `resolveKey` is passed `protectedHeader`
|
|
143
|
+
const resolveKey = async ({alg, kid}) => {
|
|
144
|
+
const isEcdsa = ECDSA_ALGS.includes(alg);
|
|
145
|
+
const isEddsa = !isEcdsa && EDDSA_ALGS.includes(alg);
|
|
146
|
+
if(!(isEcdsa || isEddsa)) {
|
|
147
|
+
throw new BedrockError(
|
|
148
|
+
`Unsupported JWT "alg": "${alg}".`, {
|
|
149
|
+
name: 'DataError',
|
|
150
|
+
details: {
|
|
151
|
+
httpStatusCode: 400,
|
|
152
|
+
public: true
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const vm = await didIo.get({url: kid});
|
|
139
158
|
// `vm.controller` must be the issuer of the DID JWT; also ensure that
|
|
140
159
|
// the specified controller authorized `vm` for the purpose of
|
|
141
160
|
// authentication
|
|
142
161
|
issuer = vm.controller;
|
|
143
162
|
const didDoc = await didIo.get({url: issuer});
|
|
144
|
-
|
|
163
|
+
let match = didDoc?.authentication?.find?.(
|
|
164
|
+
e => e === vm.id || e.id === vm.id);
|
|
165
|
+
if(typeof match === 'string') {
|
|
166
|
+
match = didDoc?.verificationMethod?.find?.(e => e.id === vm.id);
|
|
167
|
+
}
|
|
168
|
+
if(!(match && Array.isArray(match.controller) ?
|
|
169
|
+
match.controller.includes(vm.controller) :
|
|
170
|
+
match.controller === vm.controller)) {
|
|
145
171
|
throw new BedrockError(
|
|
146
172
|
`Verification method controller "${issuer}" did not authorize ` +
|
|
147
173
|
`verification method "${vm.id}" for the purpose of "authentication".`,
|
|
148
174
|
{name: 'NotAllowedError'});
|
|
149
175
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
176
|
+
let jwk;
|
|
177
|
+
if(isEcdsa) {
|
|
178
|
+
const keyPair = await EcdsaMultikey.from(vm);
|
|
179
|
+
jwk = await EcdsaMultikey.toJwk({keyPair});
|
|
180
|
+
jwk.alg = alg;
|
|
181
|
+
} else {
|
|
182
|
+
const keyPair = await Ed25519Multikey.from(vm);
|
|
183
|
+
jwk = await Ed25519Multikey.toJwk({keyPair});
|
|
184
|
+
jwk.alg = 'EdDSA';
|
|
185
|
+
}
|
|
154
186
|
return importJWK(jwk);
|
|
155
187
|
};
|
|
156
188
|
|
|
@@ -186,7 +218,7 @@ export async function verifyDidProofJwt({workflow, exchange, jwt} = {}) {
|
|
|
186
218
|
}
|
|
187
219
|
|
|
188
220
|
// check `iss` claim
|
|
189
|
-
if(!(verifyResult?.payload?.iss === issuer)) {
|
|
221
|
+
if(!(issuer && verifyResult?.payload?.iss === issuer)) {
|
|
190
222
|
throw new BedrockError('DID proof JWT validation failed.', {
|
|
191
223
|
name: 'NotAllowedError',
|
|
192
224
|
details: {
|
|
@@ -200,7 +232,7 @@ export async function verifyDidProofJwt({workflow, exchange, jwt} = {}) {
|
|
|
200
232
|
}
|
|
201
233
|
|
|
202
234
|
// check `nonce` claim
|
|
203
|
-
if(
|
|
235
|
+
if(verifyResult?.payload?.nonce !== exchange.id) {
|
|
204
236
|
throw new BedrockError('DID proof JWT validation failed.', {
|
|
205
237
|
name: 'NotAllowedError',
|
|
206
238
|
details: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bedrock/vc-delivery",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Bedrock Verifiable Credential Delivery",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"schemas/**/*.js"
|
|
10
10
|
],
|
|
11
11
|
"scripts": {
|
|
12
|
-
"lint": "eslint ."
|
|
12
|
+
"lint": "eslint --ext .cjs,.js ."
|
|
13
13
|
},
|
|
14
14
|
"repository": {
|
|
15
15
|
"type": "git",
|
|
@@ -35,41 +35,40 @@
|
|
|
35
35
|
},
|
|
36
36
|
"homepage": "https://github.com/digitalbazaar/bedrock-vc-delivery",
|
|
37
37
|
"dependencies": {
|
|
38
|
+
"@digitalbazaar/ecdsa-multikey": "^1.7.0",
|
|
38
39
|
"@digitalbazaar/ed25519-multikey": "^1.1.0",
|
|
39
|
-
"@digitalbazaar/ed25519-signature-2020": "^5.
|
|
40
|
-
"@digitalbazaar/ezcap": "^4.
|
|
41
|
-
"@digitalbazaar/oid4-client": "^3.1
|
|
42
|
-
"@digitalbazaar/vc": "^
|
|
40
|
+
"@digitalbazaar/ed25519-signature-2020": "^5.4.0",
|
|
41
|
+
"@digitalbazaar/ezcap": "^4.1.0",
|
|
42
|
+
"@digitalbazaar/oid4-client": "^3.4.1",
|
|
43
|
+
"@digitalbazaar/vc": "^7.0.0",
|
|
43
44
|
"assert-plus": "^1.0.0",
|
|
44
45
|
"bnid": "^3.0.0",
|
|
45
|
-
"body-parser": "^1.20.
|
|
46
|
+
"body-parser": "^1.20.2",
|
|
46
47
|
"cors": "^2.8.5",
|
|
47
|
-
"jose": "^
|
|
48
|
-
"jsonata": "^2.0.
|
|
49
|
-
"klona": "^2.0.
|
|
48
|
+
"jose": "^5.6.3",
|
|
49
|
+
"jsonata": "^2.0.5",
|
|
50
|
+
"klona": "^2.0.6"
|
|
50
51
|
},
|
|
51
52
|
"peerDependencies": {
|
|
52
53
|
"@bedrock/app-identity": "4.0.0",
|
|
53
|
-
"@bedrock/core": "^6.
|
|
54
|
-
"@bedrock/did-io": "^10.
|
|
55
|
-
"@bedrock/express": "^8.
|
|
56
|
-
"@bedrock/https-agent": "^4.
|
|
57
|
-
"@bedrock/mongodb": "^10.
|
|
58
|
-
"@bedrock/oauth2-verifier": "^2.
|
|
59
|
-
"@bedrock/service-agent": "^
|
|
60
|
-
"@bedrock/service-core": "^
|
|
54
|
+
"@bedrock/core": "^6.1.3",
|
|
55
|
+
"@bedrock/did-io": "^10.3.1",
|
|
56
|
+
"@bedrock/express": "^8.3.1",
|
|
57
|
+
"@bedrock/https-agent": "^4.1.0",
|
|
58
|
+
"@bedrock/mongodb": "^10.2.0",
|
|
59
|
+
"@bedrock/oauth2-verifier": "^2.1.0",
|
|
60
|
+
"@bedrock/service-agent": "^9.0.2",
|
|
61
|
+
"@bedrock/service-core": "^10.0.0",
|
|
61
62
|
"@bedrock/validation": "^7.1.0"
|
|
62
63
|
},
|
|
63
64
|
"directories": {
|
|
64
65
|
"lib": "./lib"
|
|
65
66
|
},
|
|
66
67
|
"devDependencies": {
|
|
67
|
-
"eslint": "^8.
|
|
68
|
-
"eslint-config-digitalbazaar": "^5.0
|
|
69
|
-
"eslint-plugin-jsdoc": "^
|
|
70
|
-
"eslint-plugin-unicorn": "^
|
|
71
|
-
"jsdoc": "^4.0.2",
|
|
72
|
-
"jsdoc-to-markdown": "^8.0.0"
|
|
68
|
+
"eslint": "^8.57.0",
|
|
69
|
+
"eslint-config-digitalbazaar": "^5.2.0",
|
|
70
|
+
"eslint-plugin-jsdoc": "^48.11.0",
|
|
71
|
+
"eslint-plugin-unicorn": "^55.0.0"
|
|
73
72
|
},
|
|
74
73
|
"engines": {
|
|
75
74
|
"node": ">=18"
|
|
@@ -4,6 +4,144 @@
|
|
|
4
4
|
import {MAX_ISSUER_INSTANCES} from '../lib/constants.js';
|
|
5
5
|
import {schemas} from '@bedrock/validation';
|
|
6
6
|
|
|
7
|
+
const VC_CONTEXT_1 = 'https://www.w3.org/2018/credentials/v1';
|
|
8
|
+
const VC_CONTEXT_2 = 'https://www.w3.org/ns/credentials/v2';
|
|
9
|
+
|
|
10
|
+
const vcContext = {
|
|
11
|
+
type: 'array',
|
|
12
|
+
minItems: 1,
|
|
13
|
+
// the first context must be the VC context
|
|
14
|
+
items: [{
|
|
15
|
+
oneOf: [{
|
|
16
|
+
const: VC_CONTEXT_1
|
|
17
|
+
}, {
|
|
18
|
+
const: VC_CONTEXT_2
|
|
19
|
+
}]
|
|
20
|
+
}],
|
|
21
|
+
// additional contexts maybe strings or objects
|
|
22
|
+
additionalItems: {
|
|
23
|
+
anyOf: [{type: 'string'}, {type: 'object'}]
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
function idOrObjectWithId() {
|
|
28
|
+
return {
|
|
29
|
+
title: 'identifier or an object with an id',
|
|
30
|
+
anyOf: [
|
|
31
|
+
schemas.identifier(),
|
|
32
|
+
{
|
|
33
|
+
type: 'object',
|
|
34
|
+
required: ['id'],
|
|
35
|
+
additionalProperties: true,
|
|
36
|
+
properties: {id: schemas.identifier()}
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function verifiableCredential() {
|
|
43
|
+
return {
|
|
44
|
+
title: 'Verifiable Credential',
|
|
45
|
+
type: 'object',
|
|
46
|
+
required: [
|
|
47
|
+
'@context',
|
|
48
|
+
'credentialSubject',
|
|
49
|
+
'issuer',
|
|
50
|
+
'type'
|
|
51
|
+
],
|
|
52
|
+
additionalProperties: true,
|
|
53
|
+
properties: {
|
|
54
|
+
'@context': vcContext,
|
|
55
|
+
credentialSubject: {
|
|
56
|
+
anyOf: [
|
|
57
|
+
{type: 'object'},
|
|
58
|
+
{type: 'array', minItems: 1, items: {type: 'object'}}
|
|
59
|
+
]
|
|
60
|
+
},
|
|
61
|
+
id: {
|
|
62
|
+
type: 'string'
|
|
63
|
+
},
|
|
64
|
+
issuer: idOrObjectWithId(),
|
|
65
|
+
type: {
|
|
66
|
+
type: 'array',
|
|
67
|
+
minItems: 1,
|
|
68
|
+
// this first type must be VerifiableCredential
|
|
69
|
+
items: [
|
|
70
|
+
{const: 'VerifiableCredential'},
|
|
71
|
+
],
|
|
72
|
+
// additional types must be strings
|
|
73
|
+
additionalItems: {
|
|
74
|
+
type: 'string'
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
proof: schemas.proof()
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const envelopedVerifiableCredential = {
|
|
83
|
+
title: 'Enveloped Verifiable Credential',
|
|
84
|
+
type: 'object',
|
|
85
|
+
additionalProperties: true,
|
|
86
|
+
properties: {
|
|
87
|
+
'@context': {
|
|
88
|
+
const: VC_CONTEXT_2
|
|
89
|
+
},
|
|
90
|
+
id: {
|
|
91
|
+
type: 'string'
|
|
92
|
+
},
|
|
93
|
+
type: {
|
|
94
|
+
const: 'EnvelopedVerifiableCredential'
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
required: [
|
|
98
|
+
'@context',
|
|
99
|
+
'id',
|
|
100
|
+
'type'
|
|
101
|
+
]
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
export function verifiablePresentation() {
|
|
105
|
+
return {
|
|
106
|
+
title: 'Verifiable Presentation',
|
|
107
|
+
type: 'object',
|
|
108
|
+
required: ['@context', 'type'],
|
|
109
|
+
additionalProperties: true,
|
|
110
|
+
properties: {
|
|
111
|
+
'@context': vcContext,
|
|
112
|
+
id: {
|
|
113
|
+
type: 'string'
|
|
114
|
+
},
|
|
115
|
+
type: {
|
|
116
|
+
type: 'array',
|
|
117
|
+
minItems: 1,
|
|
118
|
+
// this first type must be VerifiablePresentation
|
|
119
|
+
items: [
|
|
120
|
+
{const: 'VerifiablePresentation'},
|
|
121
|
+
],
|
|
122
|
+
// additional types must be strings
|
|
123
|
+
additionalItems: {
|
|
124
|
+
type: 'string'
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
verifiableCredential: {
|
|
128
|
+
anyOf: [
|
|
129
|
+
verifiableCredential(),
|
|
130
|
+
envelopedVerifiableCredential, {
|
|
131
|
+
type: 'array',
|
|
132
|
+
minItems: 1,
|
|
133
|
+
items: {
|
|
134
|
+
anyOf: [verifiableCredential(), envelopedVerifiableCredential]
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
]
|
|
138
|
+
},
|
|
139
|
+
holder: idOrObjectWithId(),
|
|
140
|
+
proof: schemas.proof()
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
7
145
|
const credentialDefinition = {
|
|
8
146
|
title: 'OID4VCI Verifiable Credential Definition',
|
|
9
147
|
type: 'object',
|
|
@@ -19,7 +157,7 @@ const credentialDefinition = {
|
|
|
19
157
|
},
|
|
20
158
|
type: {
|
|
21
159
|
type: 'array',
|
|
22
|
-
minItems:
|
|
160
|
+
minItems: 1,
|
|
23
161
|
item: {
|
|
24
162
|
type: 'string'
|
|
25
163
|
}
|
|
@@ -27,7 +165,7 @@ const credentialDefinition = {
|
|
|
27
165
|
// allow `types` to be flexible for OID4VCI draft 20 implementers
|
|
28
166
|
types: {
|
|
29
167
|
type: 'array',
|
|
30
|
-
minItems:
|
|
168
|
+
minItems: 1,
|
|
31
169
|
item: {
|
|
32
170
|
type: 'string'
|
|
33
171
|
}
|
|
@@ -228,6 +366,19 @@ const step = {
|
|
|
228
366
|
verifiablePresentationRequest: {
|
|
229
367
|
type: 'object'
|
|
230
368
|
},
|
|
369
|
+
presentationSchema: {
|
|
370
|
+
type: 'object',
|
|
371
|
+
required: ['type', 'jsonSchema'],
|
|
372
|
+
additionalProperties: false,
|
|
373
|
+
properties: {
|
|
374
|
+
type: {
|
|
375
|
+
type: 'string'
|
|
376
|
+
},
|
|
377
|
+
jsonSchema: {
|
|
378
|
+
type: 'object'
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
},
|
|
231
382
|
jwtDidProofRequest: {
|
|
232
383
|
type: 'object',
|
|
233
384
|
additionalProperties: false,
|
|
@@ -314,7 +465,7 @@ export function useExchangeBody() {
|
|
|
314
465
|
type: 'object',
|
|
315
466
|
additionalProperties: false,
|
|
316
467
|
properties: {
|
|
317
|
-
verifiablePresentation:
|
|
468
|
+
verifiablePresentation: verifiablePresentation()
|
|
318
469
|
}
|
|
319
470
|
};
|
|
320
471
|
}
|