@sphereon/ssi-sdk.siopv2-oid4vp-op-auth 0.32.1-next.54 → 0.33.1-feature.vcdm2.4
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/dist/agent/DidAuthSiopOpAuthenticator.d.ts +6 -1
- package/dist/agent/DidAuthSiopOpAuthenticator.d.ts.map +1 -1
- package/dist/agent/DidAuthSiopOpAuthenticator.js +325 -277
- package/dist/agent/DidAuthSiopOpAuthenticator.js.map +1 -1
- package/dist/index.js +7 -27
- package/dist/index.js.map +1 -1
- package/dist/link-handler/index.js +35 -47
- package/dist/link-handler/index.js.map +1 -1
- package/dist/localization/Localization.js +38 -43
- package/dist/localization/Localization.js.map +1 -1
- package/dist/machine/CallbackStateListener.js +9 -22
- package/dist/machine/CallbackStateListener.js.map +1 -1
- package/dist/machine/Siopv2Machine.js +129 -131
- package/dist/machine/Siopv2Machine.js.map +1 -1
- package/dist/services/IdentifierService.js +11 -24
- package/dist/services/IdentifierService.js.map +1 -1
- package/dist/services/Siopv2MachineService.d.ts +4 -2
- package/dist/services/Siopv2MachineService.d.ts.map +1 -1
- package/dist/services/Siopv2MachineService.js +193 -98
- package/dist/services/Siopv2MachineService.js.map +1 -1
- package/dist/session/OID4VP.d.ts +4 -4
- package/dist/session/OID4VP.d.ts.map +1 -1
- package/dist/session/OID4VP.js +184 -194
- package/dist/session/OID4VP.js.map +1 -1
- package/dist/session/OpSession.d.ts.map +1 -1
- package/dist/session/OpSession.js +252 -288
- package/dist/session/OpSession.js.map +1 -1
- package/dist/session/functions.js +95 -111
- package/dist/session/functions.js.map +1 -1
- package/dist/session/index.js +3 -19
- package/dist/session/index.js.map +1 -1
- package/dist/types/IDidAuthSiopOpAuthenticator.d.ts +11 -7
- package/dist/types/IDidAuthSiopOpAuthenticator.d.ts.map +1 -1
- package/dist/types/IDidAuthSiopOpAuthenticator.js +4 -7
- package/dist/types/IDidAuthSiopOpAuthenticator.js.map +1 -1
- package/dist/types/error/index.js +1 -2
- package/dist/types/identifier/index.js +1 -4
- package/dist/types/identifier/index.js.map +1 -1
- package/dist/types/index.js +5 -21
- package/dist/types/index.js.map +1 -1
- package/dist/types/machine/index.js +10 -13
- package/dist/types/machine/index.js.map +1 -1
- package/dist/types/siop-service/index.d.ts +4 -2
- package/dist/types/siop-service/index.d.ts.map +1 -1
- package/dist/types/siop-service/index.js +4 -7
- package/dist/types/siop-service/index.js.map +1 -1
- package/dist/utils/CredentialUtils.d.ts +23 -0
- package/dist/utils/CredentialUtils.d.ts.map +1 -0
- package/dist/utils/CredentialUtils.js +55 -0
- package/dist/utils/CredentialUtils.js.map +1 -0
- package/dist/utils/dcql.d.ts +5 -0
- package/dist/utils/dcql.d.ts.map +1 -0
- package/dist/utils/dcql.js +34 -0
- package/dist/utils/dcql.js.map +1 -0
- package/package.json +26 -23
- package/src/agent/DidAuthSiopOpAuthenticator.ts +122 -42
- package/src/services/Siopv2MachineService.ts +130 -20
- package/src/session/OID4VP.ts +8 -8
- package/src/session/OpSession.ts +5 -4
- package/src/types/IDidAuthSiopOpAuthenticator.ts +20 -7
- package/src/types/siop-service/index.ts +9 -6
- package/src/utils/CredentialUtils.ts +71 -0
- package/src/utils/dcql.ts +36 -0
|
@@ -1,59 +1,46 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const uuid_1 = require("uuid");
|
|
22
|
-
const functions_1 = require("./functions");
|
|
23
|
-
const OID4VP_1 = require("./OID4VP");
|
|
24
|
-
const pex_1 = require("@sphereon/pex");
|
|
25
|
-
const debug = (0, debug_1.default)(`sphereon:sdk:siop:op-session`);
|
|
26
|
-
class OpSession {
|
|
1
|
+
import { OP, URI, } from '@sphereon/did-auth-siop';
|
|
2
|
+
import { getAgentDIDMethods, getAgentResolver } from '@sphereon/ssi-sdk-ext.did-utils';
|
|
3
|
+
import { encodeBase64url } from '@sphereon/ssi-sdk.core';
|
|
4
|
+
import { CredentialMapper, parseDid, } from '@sphereon/ssi-types';
|
|
5
|
+
import Debug from 'debug';
|
|
6
|
+
import { v4 } from 'uuid';
|
|
7
|
+
import { createOP } from './functions';
|
|
8
|
+
import { OID4VP } from './OID4VP';
|
|
9
|
+
import { PEX } from '@sphereon/pex';
|
|
10
|
+
const debug = Debug(`sphereon:sdk:siop:op-session`);
|
|
11
|
+
export class OpSession {
|
|
12
|
+
ts = new Date().getDate();
|
|
13
|
+
id;
|
|
14
|
+
options;
|
|
15
|
+
context;
|
|
16
|
+
requestJwtOrUri;
|
|
17
|
+
verifiedAuthorizationRequest;
|
|
18
|
+
_nonce;
|
|
19
|
+
_state;
|
|
20
|
+
_providedPresentationDefinitions;
|
|
27
21
|
constructor(options) {
|
|
28
|
-
this.ts = new Date().getDate();
|
|
29
22
|
this.id = options.sessionId;
|
|
30
23
|
this.options = options.op;
|
|
31
24
|
this.context = options.context;
|
|
32
25
|
this.requestJwtOrUri = options.requestJwtOrUri;
|
|
33
26
|
this._providedPresentationDefinitions = options.providedPresentationDefinitions;
|
|
34
27
|
}
|
|
35
|
-
static init(options) {
|
|
36
|
-
return
|
|
37
|
-
return new OpSession(options);
|
|
38
|
-
});
|
|
28
|
+
static async init(options) {
|
|
29
|
+
return new OpSession(options);
|
|
39
30
|
}
|
|
40
|
-
getAuthorizationRequest() {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
return this.verifiedAuthorizationRequest;
|
|
51
|
-
});
|
|
31
|
+
async getAuthorizationRequest() {
|
|
32
|
+
if (!this.verifiedAuthorizationRequest) {
|
|
33
|
+
const op = await createOP({ opOptions: this.options, context: this.context });
|
|
34
|
+
this.verifiedAuthorizationRequest = await op.verifyAuthorizationRequest(this.requestJwtOrUri);
|
|
35
|
+
this._nonce = await this.verifiedAuthorizationRequest.authorizationRequest.getMergedProperty('nonce');
|
|
36
|
+
this._state = await this.verifiedAuthorizationRequest.authorizationRequest.getMergedProperty('state');
|
|
37
|
+
// only used to ensure that we have DID methods supported
|
|
38
|
+
await this.getSupportedDIDMethods();
|
|
39
|
+
}
|
|
40
|
+
return this.verifiedAuthorizationRequest;
|
|
52
41
|
}
|
|
53
|
-
getAuthorizationRequestURI() {
|
|
54
|
-
return
|
|
55
|
-
return yield did_auth_siop_1.URI.fromAuthorizationRequest((yield this.getAuthorizationRequest()).authorizationRequest);
|
|
56
|
-
});
|
|
42
|
+
async getAuthorizationRequestURI() {
|
|
43
|
+
return await URI.fromAuthorizationRequest((await this.getAuthorizationRequest()).authorizationRequest);
|
|
57
44
|
}
|
|
58
45
|
get nonce() {
|
|
59
46
|
if (!this._nonce) {
|
|
@@ -73,289 +60,266 @@ class OpSession {
|
|
|
73
60
|
this.verifiedAuthorizationRequest = undefined;
|
|
74
61
|
return this;
|
|
75
62
|
}
|
|
76
|
-
getSupportedDIDMethods(didPrefix) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
debug(`RP
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
return intersection.map((value) => convertDidMethod(value, didPrefix));
|
|
103
|
-
});
|
|
63
|
+
async getSupportedDIDMethods(didPrefix) {
|
|
64
|
+
const agentMethods = this.getAgentDIDMethodsSupported({ didPrefix });
|
|
65
|
+
let rpMethods = await this.getRPDIDMethodsSupported({ didPrefix, agentMethods });
|
|
66
|
+
debug(`RP supports subject syntax types: ${JSON.stringify(this.getSubjectSyntaxTypesSupported())}`);
|
|
67
|
+
if (rpMethods.dids.length === 0) {
|
|
68
|
+
debug(`RP does not support DIDs. Supported: ${JSON.stringify(this.getSubjectSyntaxTypesSupported())}`);
|
|
69
|
+
return [];
|
|
70
|
+
}
|
|
71
|
+
let intersection;
|
|
72
|
+
if (rpMethods.dids.includes('did')) {
|
|
73
|
+
intersection =
|
|
74
|
+
agentMethods && agentMethods.length > 0
|
|
75
|
+
? agentMethods
|
|
76
|
+
: (await getAgentDIDMethods(this.context)).map((method) => convertDidMethod(method, didPrefix)); // fallback to the agent in case the agent methods are undefined
|
|
77
|
+
}
|
|
78
|
+
else if (!agentMethods || agentMethods.length === 0) {
|
|
79
|
+
intersection = rpMethods.dids?.map((method) => convertDidMethod(method, didPrefix));
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
intersection = agentMethods.filter((value) => rpMethods.dids.includes(value));
|
|
83
|
+
}
|
|
84
|
+
if (intersection.length === 0) {
|
|
85
|
+
throw Error('No matching DID methods between agent and relying party');
|
|
86
|
+
}
|
|
87
|
+
return intersection.map((value) => convertDidMethod(value, didPrefix));
|
|
104
88
|
}
|
|
105
89
|
getAgentDIDMethodsSupported(opts) {
|
|
106
|
-
|
|
107
|
-
const agentMethods = (_a = this.options.supportedDIDMethods) === null || _a === void 0 ? void 0 : _a.map((method) => convertDidMethod(method, opts.didPrefix));
|
|
90
|
+
const agentMethods = this.options.supportedDIDMethods?.map((method) => convertDidMethod(method, opts.didPrefix));
|
|
108
91
|
debug(`agent methods: ${JSON.stringify(agentMethods)}`);
|
|
109
92
|
return agentMethods;
|
|
110
93
|
}
|
|
111
|
-
getSubjectSyntaxTypesSupported() {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
const subjectSyntaxTypesSupported = (_a = authReq.registrationMetadataPayload) === null || _a === void 0 ? void 0 : _a.subject_syntax_types_supported;
|
|
116
|
-
return subjectSyntaxTypesSupported !== null && subjectSyntaxTypesSupported !== void 0 ? subjectSyntaxTypesSupported : [];
|
|
117
|
-
});
|
|
94
|
+
async getSubjectSyntaxTypesSupported() {
|
|
95
|
+
const authReq = await this.getAuthorizationRequest();
|
|
96
|
+
const subjectSyntaxTypesSupported = authReq.registrationMetadataPayload?.subject_syntax_types_supported;
|
|
97
|
+
return subjectSyntaxTypesSupported ?? [];
|
|
118
98
|
}
|
|
119
|
-
getRPDIDMethodsSupported(opts) {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
}
|
|
141
|
-
rpMethods = [didMethod];
|
|
99
|
+
async getRPDIDMethodsSupported(opts) {
|
|
100
|
+
let keyType;
|
|
101
|
+
const agentMethods = (opts.agentMethods ?? this.getAgentDIDMethodsSupported(opts))?.map((method) => convertDidMethod(method, opts.didPrefix)) ?? [];
|
|
102
|
+
debug(`agent methods supported: ${JSON.stringify(agentMethods)}`);
|
|
103
|
+
const authReq = await this.getAuthorizationRequest();
|
|
104
|
+
const subjectSyntaxTypesSupported = authReq.registrationMetadataPayload?.subject_syntax_types_supported
|
|
105
|
+
?.map((method) => convertDidMethod(method, opts.didPrefix))
|
|
106
|
+
.filter((val) => !val.startsWith('did'));
|
|
107
|
+
debug(`subject syntax types supported in rp method supported: ${JSON.stringify(subjectSyntaxTypesSupported)}`);
|
|
108
|
+
const aud = await authReq.authorizationRequest.getMergedProperty('aud');
|
|
109
|
+
let rpMethods = [];
|
|
110
|
+
if (aud && aud.startsWith('did:')) {
|
|
111
|
+
const didMethod = convertDidMethod(parseDid(aud).method, opts.didPrefix);
|
|
112
|
+
debug(`aud did method: ${didMethod}`);
|
|
113
|
+
// The RP knows our DID, so we can use it to determine the supported DID methods
|
|
114
|
+
// If the aud did:method is not in the supported types, there still is something wrong, unless the RP signals to support all did methods
|
|
115
|
+
if (subjectSyntaxTypesSupported &&
|
|
116
|
+
subjectSyntaxTypesSupported.length > 0 &&
|
|
117
|
+
!subjectSyntaxTypesSupported.includes('did') &&
|
|
118
|
+
!subjectSyntaxTypesSupported.includes(didMethod)) {
|
|
119
|
+
throw Error(`The aud DID method ${didMethod} is not in the supported types ${subjectSyntaxTypesSupported}`);
|
|
142
120
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
keyType = 'Secp256r1';
|
|
157
|
-
codecName = 'jwk_jcs-pub';
|
|
121
|
+
rpMethods = [didMethod];
|
|
122
|
+
}
|
|
123
|
+
else if (subjectSyntaxTypesSupported) {
|
|
124
|
+
rpMethods = (Array.isArray(subjectSyntaxTypesSupported) ? subjectSyntaxTypesSupported : [subjectSyntaxTypesSupported]).map((method) => convertDidMethod(method, opts.didPrefix));
|
|
125
|
+
}
|
|
126
|
+
const isEBSI = rpMethods.length === 0 &&
|
|
127
|
+
(authReq.issuer?.includes('.ebsi.eu') || (await authReq.authorizationRequest.getMergedProperty('client_id'))?.includes('.ebsi.eu'));
|
|
128
|
+
let codecName = undefined;
|
|
129
|
+
if (isEBSI && (!aud || !aud.startsWith('http'))) {
|
|
130
|
+
debug(`EBSI detected, adding did:key to supported DID methods for RP`);
|
|
131
|
+
const didKeyMethod = convertDidMethod('did:key', opts.didPrefix);
|
|
132
|
+
if (!agentMethods?.includes(didKeyMethod)) {
|
|
133
|
+
throw Error(`EBSI detected, but agent did not support did:key. Please reconfigure agent`);
|
|
158
134
|
}
|
|
159
|
-
|
|
160
|
-
|
|
135
|
+
rpMethods = [didKeyMethod];
|
|
136
|
+
keyType = 'Secp256r1';
|
|
137
|
+
codecName = 'jwk_jcs-pub';
|
|
138
|
+
}
|
|
139
|
+
return { dids: rpMethods, codecName, keyType };
|
|
161
140
|
}
|
|
162
|
-
getSupportedIdentifiers(opts) {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
identifiers.push(identifier);
|
|
186
|
-
}
|
|
141
|
+
async getSupportedIdentifiers(opts) {
|
|
142
|
+
// todo: we also need to check signature algo
|
|
143
|
+
const methods = await this.getSupportedDIDMethods(true);
|
|
144
|
+
debug(`supported DID methods (did: prefix = true): ${JSON.stringify(methods)}`);
|
|
145
|
+
if (methods.length === 0) {
|
|
146
|
+
throw Error(`No DID methods are supported`);
|
|
147
|
+
}
|
|
148
|
+
const identifiers = await this.context.agent
|
|
149
|
+
.didManagerFind()
|
|
150
|
+
.then((ids) => ids.filter((id) => methods.includes(id.provider)));
|
|
151
|
+
if (identifiers.length === 0) {
|
|
152
|
+
debug(`No identifiers available in agent supporting methods ${JSON.stringify(methods)}`);
|
|
153
|
+
if (opts?.createInCaseNoDIDFound !== false) {
|
|
154
|
+
const { codecName, keyType } = await this.getRPDIDMethodsSupported({
|
|
155
|
+
didPrefix: true,
|
|
156
|
+
agentMethods: methods,
|
|
157
|
+
});
|
|
158
|
+
const identifier = await this.context.agent.didManagerCreate({
|
|
159
|
+
provider: methods[0],
|
|
160
|
+
options: { codecName, keyType, type: keyType }, // both keyType and type, because not every did provider has the same param
|
|
161
|
+
});
|
|
162
|
+
debug(`Created a new identifier for the SIOP interaction: ${identifier.did}`);
|
|
163
|
+
identifiers.push(identifier);
|
|
187
164
|
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
165
|
+
}
|
|
166
|
+
debug(`supported identifiers: ${JSON.stringify(identifiers.map((id) => id.did))}`);
|
|
167
|
+
return identifiers;
|
|
191
168
|
}
|
|
192
|
-
getSupportedDIDs() {
|
|
193
|
-
return
|
|
194
|
-
return (yield this.getSupportedIdentifiers()).map((id) => id.did);
|
|
195
|
-
});
|
|
169
|
+
async getSupportedDIDs() {
|
|
170
|
+
return (await this.getSupportedIdentifiers()).map((id) => id.did);
|
|
196
171
|
}
|
|
197
|
-
getRedirectUri() {
|
|
198
|
-
return
|
|
199
|
-
return Promise.resolve(this.verifiedAuthorizationRequest.responseURI);
|
|
200
|
-
});
|
|
172
|
+
async getRedirectUri() {
|
|
173
|
+
return Promise.resolve(this.verifiedAuthorizationRequest.responseURI);
|
|
201
174
|
}
|
|
202
|
-
hasPresentationDefinitions() {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
const defs = (_a = this._providedPresentationDefinitions) !== null && _a !== void 0 ? _a : (yield this.getAuthorizationRequest()).presentationDefinitions;
|
|
206
|
-
return defs !== undefined && defs.length > 0;
|
|
207
|
-
});
|
|
175
|
+
async hasPresentationDefinitions() {
|
|
176
|
+
const defs = this._providedPresentationDefinitions ?? (await this.getAuthorizationRequest()).presentationDefinitions;
|
|
177
|
+
return defs !== undefined && defs.length > 0;
|
|
208
178
|
}
|
|
209
|
-
getPresentationDefinitions() {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
}
|
|
215
|
-
return (_a = this._providedPresentationDefinitions) !== null && _a !== void 0 ? _a : (yield this.getAuthorizationRequest()).presentationDefinitions;
|
|
216
|
-
});
|
|
179
|
+
async getPresentationDefinitions() {
|
|
180
|
+
if (!(await this.hasPresentationDefinitions())) {
|
|
181
|
+
throw Error(`No presentation definitions found`);
|
|
182
|
+
}
|
|
183
|
+
return this._providedPresentationDefinitions ?? (await this.getAuthorizationRequest()).presentationDefinitions;
|
|
217
184
|
}
|
|
218
|
-
getOID4VP(args) {
|
|
219
|
-
return
|
|
220
|
-
var _a;
|
|
221
|
-
return yield OID4VP_1.OID4VP.init(this, (_a = args.allIdentifiers) !== null && _a !== void 0 ? _a : [], args.hasher);
|
|
222
|
-
});
|
|
185
|
+
async getOID4VP(args) {
|
|
186
|
+
return await OID4VP.init(this, args.allIdentifiers ?? [], args.hasher);
|
|
223
187
|
}
|
|
224
188
|
createPresentationVerificationCallback(context) {
|
|
225
|
-
function presentationVerificationCallback(args, presentationSubmission) {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
};
|
|
235
|
-
}
|
|
236
|
-
catch (error) {
|
|
237
|
-
result = {
|
|
238
|
-
verified: false,
|
|
239
|
-
error: { message: error.message },
|
|
240
|
-
};
|
|
241
|
-
}
|
|
189
|
+
async function presentationVerificationCallback(args, presentationSubmission) {
|
|
190
|
+
let result;
|
|
191
|
+
if (CredentialMapper.isSdJwtEncoded(args)) {
|
|
192
|
+
try {
|
|
193
|
+
const sdJwtResult = await context.agent.verifySdJwtPresentation({ presentation: args });
|
|
194
|
+
result = {
|
|
195
|
+
verified: 'header' in sdJwtResult,
|
|
196
|
+
error: 'header' in sdJwtResult ? undefined : { message: 'could not verify SD JWT presentation' },
|
|
197
|
+
};
|
|
242
198
|
}
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
199
|
+
catch (error) {
|
|
200
|
+
result = {
|
|
201
|
+
verified: false,
|
|
202
|
+
error: { message: error.message },
|
|
203
|
+
};
|
|
246
204
|
}
|
|
247
|
-
|
|
248
|
-
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
// @ts-ignore TODO IVerifiablePresentation has too many union types for Veramo
|
|
208
|
+
result = await context.agent.verifyPresentation({ presentation: args });
|
|
209
|
+
}
|
|
210
|
+
return result;
|
|
249
211
|
}
|
|
250
212
|
return presentationVerificationCallback;
|
|
251
213
|
}
|
|
252
|
-
createJarmResponseCallback(
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
return { response: result.jwt };
|
|
276
|
-
});
|
|
277
|
-
});
|
|
278
|
-
};
|
|
279
|
-
});
|
|
214
|
+
async createJarmResponseCallback({ responseOpts, }) {
|
|
215
|
+
const agent = this.context.agent;
|
|
216
|
+
return async function jarmResponse(opts) {
|
|
217
|
+
const { clientMetadata, requestObjectPayload, authorizationResponsePayload: authResponse } = opts;
|
|
218
|
+
const jwk = await OP.extractEncJwksFromClientMetadata(clientMetadata);
|
|
219
|
+
// @ts-ignore // FIXME: Fix jwk inference
|
|
220
|
+
const recipientKey = await agent.identifierExternalResolveByJwk({ identifier: jwk });
|
|
221
|
+
return await agent
|
|
222
|
+
.jwtEncryptJweCompactJwt({
|
|
223
|
+
recipientKey,
|
|
224
|
+
protectedHeader: {},
|
|
225
|
+
alg: requestObjectPayload.client_metadata.authorization_encrypted_response_alg ?? 'ECDH-ES',
|
|
226
|
+
enc: requestObjectPayload.client_metadata.authorization_encrypted_response_enc ?? 'A256GCM',
|
|
227
|
+
apv: encodeBase64url(opts.requestObjectPayload.nonce),
|
|
228
|
+
apu: encodeBase64url(v4()),
|
|
229
|
+
payload: authResponse,
|
|
230
|
+
issuer: responseOpts.issuer,
|
|
231
|
+
audience: responseOpts.audience,
|
|
232
|
+
})
|
|
233
|
+
.then((result) => {
|
|
234
|
+
return { response: result.jwt };
|
|
235
|
+
});
|
|
236
|
+
};
|
|
280
237
|
}
|
|
281
|
-
sendAuthorizationResponse(args) {
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
238
|
+
async sendAuthorizationResponse(args) {
|
|
239
|
+
const resolveOpts = this.options.resolveOpts ?? {
|
|
240
|
+
resolver: getAgentResolver(this.context, {
|
|
241
|
+
uniresolverResolution: true,
|
|
242
|
+
localResolution: true,
|
|
243
|
+
resolverResolution: true,
|
|
244
|
+
}),
|
|
245
|
+
};
|
|
246
|
+
if (!resolveOpts.subjectSyntaxTypesSupported || resolveOpts.subjectSyntaxTypesSupported.length === 0) {
|
|
247
|
+
resolveOpts.subjectSyntaxTypesSupported = await this.getSupportedDIDMethods(true);
|
|
248
|
+
}
|
|
249
|
+
//todo: populate with the right verification params. In did-auth-siop we don't have any test that actually passes this parameter
|
|
250
|
+
const verification = {
|
|
251
|
+
presentationVerificationCallback: this.createPresentationVerificationCallback(this.context),
|
|
252
|
+
};
|
|
253
|
+
const request = await this.getAuthorizationRequest();
|
|
254
|
+
const hasDefinitions = await this.hasPresentationDefinitions();
|
|
255
|
+
if (hasDefinitions) {
|
|
256
|
+
const totalInputDescriptors = request.presentationDefinitions?.reduce((sum, pd) => {
|
|
257
|
+
return sum + pd.definition.input_descriptors.length;
|
|
258
|
+
}, 0);
|
|
259
|
+
const totalVCs = args.verifiablePresentations ? this.countVCsInAllVPs(args.verifiablePresentations, args.hasher) : 0;
|
|
260
|
+
if (!request.presentationDefinitions || !args.verifiablePresentations || totalVCs !== totalInputDescriptors) {
|
|
261
|
+
throw Error(`Amount of presentations ${args.verifiablePresentations?.length}, doesn't match expected ${request.presentationDefinitions?.length}`);
|
|
293
262
|
}
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
presentationVerificationCallback: this.createPresentationVerificationCallback(this.context),
|
|
297
|
-
};
|
|
298
|
-
const request = yield this.getAuthorizationRequest();
|
|
299
|
-
const hasDefinitions = yield this.hasPresentationDefinitions();
|
|
300
|
-
if (hasDefinitions) {
|
|
301
|
-
const totalInputDescriptors = (_b = request.presentationDefinitions) === null || _b === void 0 ? void 0 : _b.reduce((sum, pd) => {
|
|
302
|
-
return sum + pd.definition.input_descriptors.length;
|
|
303
|
-
}, 0);
|
|
304
|
-
const totalVCs = args.verifiablePresentations ? this.countVCsInAllVPs(args.verifiablePresentations, args.hasher) : 0;
|
|
305
|
-
if (!request.presentationDefinitions || !args.verifiablePresentations || totalVCs !== totalInputDescriptors) {
|
|
306
|
-
throw Error(`Amount of presentations ${(_c = args.verifiablePresentations) === null || _c === void 0 ? void 0 : _c.length}, doesn't match expected ${(_d = request.presentationDefinitions) === null || _d === void 0 ? void 0 : _d.length}`);
|
|
307
|
-
}
|
|
308
|
-
else if (!args.presentationSubmission) {
|
|
309
|
-
throw Error(`Presentation submission is required when verifiable presentations are required`);
|
|
310
|
-
}
|
|
263
|
+
else if (!args.presentationSubmission) {
|
|
264
|
+
throw Error(`Presentation submission is required when verifiable presentations are required`);
|
|
311
265
|
}
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
266
|
+
}
|
|
267
|
+
const verifiablePresentations = args.verifiablePresentations
|
|
268
|
+
? args.verifiablePresentations.map((vp) => CredentialMapper.storedPresentationToOriginalFormat(vp))
|
|
269
|
+
: [];
|
|
270
|
+
const op = await createOP({
|
|
271
|
+
opOptions: {
|
|
272
|
+
...this.options,
|
|
273
|
+
resolveOpts: { ...this.options.resolveOpts },
|
|
274
|
+
eventEmitter: this.options.eventEmitter,
|
|
275
|
+
presentationSignCallback: this.options.presentationSignCallback,
|
|
276
|
+
wellknownDIDVerifyCallback: this.options.wellknownDIDVerifyCallback,
|
|
277
|
+
supportedVersions: request.versions,
|
|
278
|
+
},
|
|
279
|
+
idOpts: args.responseSignerOpts,
|
|
280
|
+
context: this.context,
|
|
281
|
+
});
|
|
282
|
+
//TODO change this to use the new functionalities by identifier-resolver and get the jwkIssuer for the responseOpts
|
|
283
|
+
let issuer = args.responseSignerOpts.issuer;
|
|
284
|
+
const responseOpts = {
|
|
285
|
+
verification,
|
|
286
|
+
issuer,
|
|
287
|
+
...(args.isFirstParty && { isFirstParty: args.isFirstParty }),
|
|
288
|
+
...(args.verifiablePresentations && {
|
|
324
289
|
presentationExchange: {
|
|
325
290
|
verifiablePresentations,
|
|
326
291
|
presentationSubmission: args.presentationSubmission,
|
|
327
292
|
},
|
|
328
|
-
})
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
293
|
+
}),
|
|
294
|
+
dcqlQuery: args.dcqlResponse,
|
|
295
|
+
};
|
|
296
|
+
const authResponse = await op.createAuthorizationResponse(request, responseOpts);
|
|
297
|
+
const response = await op.submitAuthorizationResponse(authResponse, await this.createJarmResponseCallback({ responseOpts }));
|
|
298
|
+
if (response.status >= 400) {
|
|
299
|
+
throw Error(`Error ${response.status}: ${response.statusText || (await response.text())}`);
|
|
300
|
+
}
|
|
301
|
+
else {
|
|
302
|
+
return response;
|
|
303
|
+
}
|
|
338
304
|
}
|
|
339
305
|
countVCsInAllVPs(verifiablePresentations, hasher) {
|
|
340
306
|
return verifiablePresentations.reduce((sum, vp) => {
|
|
341
|
-
|
|
342
|
-
if (ssi_types_1.CredentialMapper.isMsoMdocDecodedPresentation(vp) || ssi_types_1.CredentialMapper.isMsoMdocOid4VPEncoded(vp)) {
|
|
307
|
+
if (CredentialMapper.isMsoMdocDecodedPresentation(vp) || CredentialMapper.isMsoMdocOid4VPEncoded(vp)) {
|
|
343
308
|
return sum + 1;
|
|
344
309
|
}
|
|
345
|
-
const uvp =
|
|
346
|
-
if (
|
|
347
|
-
return sum +
|
|
310
|
+
const uvp = CredentialMapper.toUniformPresentation(vp, { hasher: hasher ?? this.options.hasher });
|
|
311
|
+
if (uvp.verifiableCredential?.length) {
|
|
312
|
+
return sum + uvp.verifiableCredential?.length;
|
|
348
313
|
}
|
|
349
|
-
const isSdJWT =
|
|
314
|
+
const isSdJWT = CredentialMapper.isSdJwtDecodedCredential(uvp);
|
|
350
315
|
if (isSdJWT ||
|
|
351
|
-
(uvp.verifiableCredential && !
|
|
316
|
+
(uvp.verifiableCredential && !PEX.allowMultipleVCsPerPresentation(uvp.verifiableCredential))) {
|
|
352
317
|
return sum + 1;
|
|
353
318
|
}
|
|
354
319
|
return sum;
|
|
355
320
|
}, 0);
|
|
356
321
|
}
|
|
357
322
|
}
|
|
358
|
-
exports.OpSession = OpSession;
|
|
359
323
|
function convertDidMethod(didMethod, didPrefix) {
|
|
360
324
|
if (didPrefix === false) {
|
|
361
325
|
return didMethod.startsWith('did:') ? didMethod.toLowerCase().replace('did:', '') : didMethod.toLowerCase();
|