@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.
Files changed (63) hide show
  1. package/dist/agent/DidAuthSiopOpAuthenticator.d.ts +6 -1
  2. package/dist/agent/DidAuthSiopOpAuthenticator.d.ts.map +1 -1
  3. package/dist/agent/DidAuthSiopOpAuthenticator.js +325 -277
  4. package/dist/agent/DidAuthSiopOpAuthenticator.js.map +1 -1
  5. package/dist/index.js +7 -27
  6. package/dist/index.js.map +1 -1
  7. package/dist/link-handler/index.js +35 -47
  8. package/dist/link-handler/index.js.map +1 -1
  9. package/dist/localization/Localization.js +38 -43
  10. package/dist/localization/Localization.js.map +1 -1
  11. package/dist/machine/CallbackStateListener.js +9 -22
  12. package/dist/machine/CallbackStateListener.js.map +1 -1
  13. package/dist/machine/Siopv2Machine.js +129 -131
  14. package/dist/machine/Siopv2Machine.js.map +1 -1
  15. package/dist/services/IdentifierService.js +11 -24
  16. package/dist/services/IdentifierService.js.map +1 -1
  17. package/dist/services/Siopv2MachineService.d.ts +4 -2
  18. package/dist/services/Siopv2MachineService.d.ts.map +1 -1
  19. package/dist/services/Siopv2MachineService.js +193 -98
  20. package/dist/services/Siopv2MachineService.js.map +1 -1
  21. package/dist/session/OID4VP.d.ts +4 -4
  22. package/dist/session/OID4VP.d.ts.map +1 -1
  23. package/dist/session/OID4VP.js +184 -194
  24. package/dist/session/OID4VP.js.map +1 -1
  25. package/dist/session/OpSession.d.ts.map +1 -1
  26. package/dist/session/OpSession.js +252 -288
  27. package/dist/session/OpSession.js.map +1 -1
  28. package/dist/session/functions.js +95 -111
  29. package/dist/session/functions.js.map +1 -1
  30. package/dist/session/index.js +3 -19
  31. package/dist/session/index.js.map +1 -1
  32. package/dist/types/IDidAuthSiopOpAuthenticator.d.ts +11 -7
  33. package/dist/types/IDidAuthSiopOpAuthenticator.d.ts.map +1 -1
  34. package/dist/types/IDidAuthSiopOpAuthenticator.js +4 -7
  35. package/dist/types/IDidAuthSiopOpAuthenticator.js.map +1 -1
  36. package/dist/types/error/index.js +1 -2
  37. package/dist/types/identifier/index.js +1 -4
  38. package/dist/types/identifier/index.js.map +1 -1
  39. package/dist/types/index.js +5 -21
  40. package/dist/types/index.js.map +1 -1
  41. package/dist/types/machine/index.js +10 -13
  42. package/dist/types/machine/index.js.map +1 -1
  43. package/dist/types/siop-service/index.d.ts +4 -2
  44. package/dist/types/siop-service/index.d.ts.map +1 -1
  45. package/dist/types/siop-service/index.js +4 -7
  46. package/dist/types/siop-service/index.js.map +1 -1
  47. package/dist/utils/CredentialUtils.d.ts +23 -0
  48. package/dist/utils/CredentialUtils.d.ts.map +1 -0
  49. package/dist/utils/CredentialUtils.js +55 -0
  50. package/dist/utils/CredentialUtils.js.map +1 -0
  51. package/dist/utils/dcql.d.ts +5 -0
  52. package/dist/utils/dcql.d.ts.map +1 -0
  53. package/dist/utils/dcql.js +34 -0
  54. package/dist/utils/dcql.js.map +1 -0
  55. package/package.json +26 -23
  56. package/src/agent/DidAuthSiopOpAuthenticator.ts +122 -42
  57. package/src/services/Siopv2MachineService.ts +130 -20
  58. package/src/session/OID4VP.ts +8 -8
  59. package/src/session/OpSession.ts +5 -4
  60. package/src/types/IDidAuthSiopOpAuthenticator.ts +20 -7
  61. package/src/types/siop-service/index.ts +9 -6
  62. package/src/utils/CredentialUtils.ts +71 -0
  63. package/src/utils/dcql.ts +36 -0
@@ -1,29 +1,18 @@
1
- "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.DidAuthSiopOpAuthenticator = exports.didAuthSiopOpAuthenticatorMethods = void 0;
13
- const did_auth_siop_1 = require("@sphereon/did-auth-siop");
14
- const ssi_sdk_data_store_1 = require("@sphereon/ssi-sdk.data-store");
15
- const ssi_types_1 = require("@sphereon/ssi-types");
16
- const uuid_1 = require("uuid");
17
- const index_1 = require("../index");
18
- const Siopv2Machine_1 = require("../machine/Siopv2Machine");
19
- const Siopv2MachineService_1 = require("../services/Siopv2MachineService");
20
- const session_1 = require("../session");
21
- const pex_1 = require("@sphereon/pex");
22
- const utils_1 = require("@veramo/utils");
23
- const types_1 = require("../types");
24
- const logger = ssi_types_1.Loggers.DEFAULT.options(index_1.LOGGER_NAMESPACE, {}).get(index_1.LOGGER_NAMESPACE);
1
+ import { decodeUriAsJson, SupportedVersion } from '@sphereon/did-auth-siop';
2
+ import { ConnectionType, CorrelationIdentifierType, CredentialDocumentFormat, CredentialRole, DocumentType, IdentityOrigin, } from '@sphereon/ssi-sdk.data-store';
3
+ import { Loggers } from '@sphereon/ssi-types';
4
+ import { v4 as uuidv4 } from 'uuid';
5
+ import { LOGGER_NAMESPACE, schema, } from '../index';
6
+ import { Siopv2Machine } from '../machine/Siopv2Machine';
7
+ import { getSelectableCredentials, siopSendAuthorizationResponse, translateCorrelationIdToName } from '../services/Siopv2MachineService';
8
+ import { OpSession } from '../session';
9
+ import { PEX, Status } from '@sphereon/pex';
10
+ import { computeEntryHash } from '@veramo/utils';
11
+ import { Siopv2HolderEvent, } from '../types';
12
+ import { DcqlQuery } from 'dcql';
13
+ const logger = Loggers.DEFAULT.options(LOGGER_NAMESPACE, {}).get(LOGGER_NAMESPACE);
25
14
  // Exposing the methods here for any REST implementation
26
- exports.didAuthSiopOpAuthenticatorMethods = [
15
+ export const didAuthSiopOpAuthenticatorMethods = [
27
16
  'cmGetContacts',
28
17
  'cmGetContact',
29
18
  'cmAddContact',
@@ -35,24 +24,31 @@ exports.didAuthSiopOpAuthenticatorMethods = [
35
24
  'dataStoreORMGetVerifiableCredentials',
36
25
  'createVerifiablePresentation',
37
26
  ];
38
- class DidAuthSiopOpAuthenticator {
27
+ export class DidAuthSiopOpAuthenticator {
28
+ schema = schema.IDidAuthSiopOpAuthenticator;
29
+ methods = {
30
+ siopGetOPSession: this.siopGetOPSession.bind(this),
31
+ siopRegisterOPSession: this.siopRegisterOPSession.bind(this),
32
+ siopRemoveOPSession: this.siopRemoveOPSession.bind(this),
33
+ siopRegisterOPCustomApproval: this.siopRegisterOPCustomApproval.bind(this),
34
+ siopRemoveOPCustomApproval: this.siopRemoveOPCustomApproval.bind(this),
35
+ siopGetMachineInterpreter: this.siopGetMachineInterpreter.bind(this),
36
+ siopCreateConfig: this.siopCreateConfig.bind(this),
37
+ siopGetSiopRequest: this.siopGetSiopRequest.bind(this),
38
+ siopRetrieveContact: this.siopRetrieveContact.bind(this),
39
+ siopAddIdentity: this.siopAddContactIdentity.bind(this),
40
+ siopSendResponse: this.siopSendResponse.bind(this),
41
+ siopGetSelectableCredentials: this.siopGetSelectableCredentials.bind(this),
42
+ };
43
+ sessions;
44
+ customApprovals;
45
+ presentationSignCallback;
46
+ onContactIdentityCreated;
47
+ onIdentifierCreated;
48
+ eventEmitter;
49
+ hasher;
39
50
  constructor(options) {
40
- this.schema = index_1.schema.IDidAuthSiopOpAuthenticator;
41
- this.methods = {
42
- siopGetOPSession: this.siopGetOPSession.bind(this),
43
- siopRegisterOPSession: this.siopRegisterOPSession.bind(this),
44
- siopRemoveOPSession: this.siopRemoveOPSession.bind(this),
45
- siopRegisterOPCustomApproval: this.siopRegisterOPCustomApproval.bind(this),
46
- siopRemoveOPCustomApproval: this.siopRemoveOPCustomApproval.bind(this),
47
- siopGetMachineInterpreter: this.siopGetMachineInterpreter.bind(this),
48
- siopCreateConfig: this.siopCreateConfig.bind(this),
49
- siopGetSiopRequest: this.siopGetSiopRequest.bind(this),
50
- siopRetrieveContact: this.siopRetrieveContact.bind(this),
51
- siopAddIdentity: this.siopAddContactIdentity.bind(this),
52
- siopSendResponse: this.siopSendResponse.bind(this),
53
- siopGetSelectableCredentials: this.siopGetSelectableCredentials.bind(this),
54
- };
55
- const { onContactIdentityCreated, onIdentifierCreated, hasher, customApprovals = {}, presentationSignCallback } = Object.assign({}, options);
51
+ const { onContactIdentityCreated, onIdentifierCreated, hasher, customApprovals = {}, presentationSignCallback } = { ...options };
56
52
  this.hasher = hasher;
57
53
  this.onContactIdentityCreated = onContactIdentityCreated;
58
54
  this.onIdentifierCreated = onIdentifierCreated;
@@ -60,264 +56,316 @@ class DidAuthSiopOpAuthenticator {
60
56
  this.sessions = new Map();
61
57
  this.customApprovals = customApprovals;
62
58
  }
63
- onEvent(event, context) {
64
- return __awaiter(this, void 0, void 0, function* () {
65
- var _a, _b;
66
- switch (event.type) {
67
- case types_1.Siopv2HolderEvent.CONTACT_IDENTITY_CREATED:
68
- (_a = this.onContactIdentityCreated) === null || _a === void 0 ? void 0 : _a.call(this, event.data);
69
- break;
70
- case types_1.Siopv2HolderEvent.IDENTIFIER_CREATED:
71
- (_b = this.onIdentifierCreated) === null || _b === void 0 ? void 0 : _b.call(this, event.data);
72
- break;
73
- default:
74
- return Promise.reject(Error(`Event type ${event.type} not supported`));
75
- }
76
- });
59
+ async onEvent(event, context) {
60
+ switch (event.type) {
61
+ case Siopv2HolderEvent.CONTACT_IDENTITY_CREATED:
62
+ this.onContactIdentityCreated?.(event.data);
63
+ break;
64
+ case Siopv2HolderEvent.IDENTIFIER_CREATED:
65
+ this.onIdentifierCreated?.(event.data);
66
+ break;
67
+ default:
68
+ return Promise.reject(Error(`Event type ${event.type} not supported`));
69
+ }
77
70
  }
78
- siopGetOPSession(args, context) {
79
- return __awaiter(this, void 0, void 0, function* () {
80
- // TODO add cleaning up sessions https://sphereon.atlassian.net/browse/MYC-143
81
- if (!this.sessions.has(args.sessionId)) {
82
- throw Error(`No session found for id: ${args.sessionId}`);
83
- }
84
- return this.sessions.get(args.sessionId);
85
- });
71
+ async siopGetOPSession(args, context) {
72
+ // TODO add cleaning up sessions https://sphereon.atlassian.net/browse/MYC-143
73
+ if (!this.sessions.has(args.sessionId)) {
74
+ throw Error(`No session found for id: ${args.sessionId}`);
75
+ }
76
+ return this.sessions.get(args.sessionId);
86
77
  }
87
- siopRegisterOPSession(args, context) {
88
- return __awaiter(this, void 0, void 0, function* () {
89
- var _a;
90
- const sessionId = args.sessionId || (0, uuid_1.v4)();
91
- if (this.sessions.has(sessionId)) {
92
- return Promise.reject(new Error(`Session with id: ${args.sessionId} already present`));
93
- }
94
- const opts = Object.assign(Object.assign({}, args), { sessionId, context });
95
- if (!((_a = opts.op) === null || _a === void 0 ? void 0 : _a.presentationSignCallback)) {
96
- opts.op = Object.assign(Object.assign({}, opts.op), { presentationSignCallback: this.presentationSignCallback });
97
- }
98
- const session = yield session_1.OpSession.init(opts);
99
- this.sessions.set(sessionId, session);
100
- return session;
101
- });
78
+ async siopRegisterOPSession(args, context) {
79
+ const sessionId = args.sessionId || uuidv4();
80
+ if (this.sessions.has(sessionId)) {
81
+ return Promise.reject(new Error(`Session with id: ${args.sessionId} already present`));
82
+ }
83
+ const opts = { ...args, sessionId, context };
84
+ if (!opts.op?.presentationSignCallback) {
85
+ opts.op = { ...opts.op, presentationSignCallback: this.presentationSignCallback };
86
+ }
87
+ const session = await OpSession.init(opts);
88
+ this.sessions.set(sessionId, session);
89
+ return session;
102
90
  }
103
- siopRemoveOPSession(args, context) {
104
- return __awaiter(this, void 0, void 0, function* () {
105
- return this.sessions.delete(args.sessionId);
106
- });
91
+ async siopRemoveOPSession(args, context) {
92
+ return this.sessions.delete(args.sessionId);
107
93
  }
108
- siopRegisterOPCustomApproval(args, context) {
109
- return __awaiter(this, void 0, void 0, function* () {
110
- if (this.customApprovals[args.key] !== undefined) {
111
- return Promise.reject(new Error(`Custom approval with key: ${args.key} already present`));
112
- }
113
- this.customApprovals[args.key] = args.customApproval;
114
- });
94
+ async siopRegisterOPCustomApproval(args, context) {
95
+ if (this.customApprovals[args.key] !== undefined) {
96
+ return Promise.reject(new Error(`Custom approval with key: ${args.key} already present`));
97
+ }
98
+ this.customApprovals[args.key] = args.customApproval;
115
99
  }
116
- siopRemoveOPCustomApproval(args, context) {
117
- return __awaiter(this, void 0, void 0, function* () {
118
- return delete this.customApprovals[args.key];
119
- });
100
+ async siopRemoveOPCustomApproval(args, context) {
101
+ return delete this.customApprovals[args.key];
120
102
  }
121
- siopGetMachineInterpreter(opts, context) {
122
- return __awaiter(this, void 0, void 0, function* () {
123
- const { stateNavigationListener, url } = opts;
124
- const services = Object.assign({ createConfig: (args) => this.siopCreateConfig(args), getSiopRequest: (args) => this.siopGetSiopRequest(args, context), getSelectableCredentials: (args) => this.siopGetSelectableCredentials(args, context), retrieveContact: (args) => this.siopRetrieveContact(args, context), addContactIdentity: (args) => this.siopAddContactIdentity(args, context), sendResponse: (args) => this.siopSendResponse(args, context) }, opts === null || opts === void 0 ? void 0 : opts.services);
125
- const siopv2MachineOpts = Object.assign(Object.assign({}, opts), { url,
126
- stateNavigationListener, services: Object.assign(Object.assign({}, services), opts.services) });
127
- return Siopv2Machine_1.Siopv2Machine.newInstance(siopv2MachineOpts);
128
- });
103
+ async siopGetMachineInterpreter(opts, context) {
104
+ const { stateNavigationListener, url } = opts;
105
+ const services = {
106
+ createConfig: (args) => this.siopCreateConfig(args),
107
+ getSiopRequest: (args) => this.siopGetSiopRequest(args, context),
108
+ getSelectableCredentials: (args) => this.siopGetSelectableCredentials(args, context),
109
+ retrieveContact: (args) => this.siopRetrieveContact(args, context),
110
+ addContactIdentity: (args) => this.siopAddContactIdentity(args, context),
111
+ sendResponse: (args) => this.siopSendResponse(args, context),
112
+ ...opts?.services,
113
+ };
114
+ const siopv2MachineOpts = {
115
+ ...opts,
116
+ url,
117
+ stateNavigationListener,
118
+ services: {
119
+ ...services,
120
+ ...opts.services,
121
+ },
122
+ };
123
+ return Siopv2Machine.newInstance(siopv2MachineOpts);
129
124
  }
130
- siopCreateConfig(context) {
131
- return __awaiter(this, void 0, void 0, function* () {
132
- const { url } = context;
133
- if (!url) {
134
- return Promise.reject(Error('Missing request uri in context'));
135
- }
136
- return {
137
- id: (0, uuid_1.v4)(),
138
- // FIXME: Update these values in SSI-SDK. Only the URI (not a redirectURI) would be available at this point
139
- sessionId: (0, uuid_1.v4)(),
140
- redirectUrl: url,
141
- };
142
- });
125
+ async siopCreateConfig(context) {
126
+ const { url } = context;
127
+ if (!url) {
128
+ return Promise.reject(Error('Missing request uri in context'));
129
+ }
130
+ return {
131
+ id: uuidv4(),
132
+ // FIXME: Update these values in SSI-SDK. Only the URI (not a redirectURI) would be available at this point
133
+ sessionId: uuidv4(),
134
+ redirectUrl: url,
135
+ };
143
136
  }
144
- siopGetSiopRequest(args, context) {
145
- return __awaiter(this, void 0, void 0, function* () {
146
- var _a, _b, _c, _d, _e;
147
- const { agent } = context;
148
- const { didAuthConfig } = args;
149
- if (args.url === undefined) {
150
- return Promise.reject(Error('Missing request uri in context'));
151
- }
152
- if (didAuthConfig === undefined) {
153
- return Promise.reject(Error('Missing config in context'));
154
- }
155
- const { sessionId, redirectUrl } = didAuthConfig;
156
- const session = yield agent
157
- .siopGetOPSession({ sessionId })
158
- .catch(() => __awaiter(this, void 0, void 0, function* () { return yield agent.siopRegisterOPSession({ requestJwtOrUri: redirectUrl, sessionId, op: { eventEmitter: this.eventEmitter, hasher: this.hasher } }); }));
159
- logger.debug(`session: ${JSON.stringify(session.id, null, 2)}`);
160
- const verifiedAuthorizationRequest = yield session.getAuthorizationRequest();
161
- // logger.trace('Request: ' + JSON.stringify(verifiedAuthorizationRequest, null, 2))
162
- const clientName = (_a = verifiedAuthorizationRequest.registrationMetadataPayload) === null || _a === void 0 ? void 0 : _a.client_name;
163
- const url = (_b = verifiedAuthorizationRequest.responseURI) !== null && _b !== void 0 ? _b : (args.url.includes('request_uri')
137
+ async siopGetSiopRequest(args, context) {
138
+ const { agent } = context;
139
+ const { didAuthConfig } = args;
140
+ if (args.url === undefined) {
141
+ return Promise.reject(Error('Missing request uri in context'));
142
+ }
143
+ if (didAuthConfig === undefined) {
144
+ return Promise.reject(Error('Missing config in context'));
145
+ }
146
+ const { sessionId, redirectUrl } = didAuthConfig;
147
+ const session = await agent.siopGetOPSession({ sessionId }).catch(async () => await agent.siopRegisterOPSession({
148
+ requestJwtOrUri: redirectUrl,
149
+ sessionId,
150
+ op: { eventEmitter: this.eventEmitter, hasher: this.hasher },
151
+ }));
152
+ logger.debug(`session: ${JSON.stringify(session.id, null, 2)}`);
153
+ const verifiedAuthorizationRequest = await session.getAuthorizationRequest();
154
+ // logger.trace('Request: ' + JSON.stringify(verifiedAuthorizationRequest, null, 2))
155
+ const clientName = verifiedAuthorizationRequest.registrationMetadataPayload?.client_name;
156
+ const url = verifiedAuthorizationRequest.responseURI ??
157
+ (args.url.includes('request_uri')
164
158
  ? decodeURIComponent(args.url.split('?request_uri=')[1].trim())
165
- : ((_c = verifiedAuthorizationRequest.issuer) !== null && _c !== void 0 ? _c : (_d = verifiedAuthorizationRequest.registrationMetadataPayload) === null || _d === void 0 ? void 0 : _d.client_id));
166
- const uri = url.includes('://') ? new URL(url) : undefined;
167
- const correlationId = (_e = uri === null || uri === void 0 ? void 0 : uri.hostname) !== null && _e !== void 0 ? _e : (yield this.determineCorrelationId(uri, verifiedAuthorizationRequest, clientName, context));
168
- const clientId = yield verifiedAuthorizationRequest.authorizationRequest.getMergedProperty('client_id');
169
- return {
170
- issuer: verifiedAuthorizationRequest.issuer,
171
- correlationId,
172
- registrationMetadataPayload: verifiedAuthorizationRequest.registrationMetadataPayload,
173
- uri,
174
- name: clientName,
175
- clientId,
176
- presentationDefinitions: (yield verifiedAuthorizationRequest.authorizationRequest.containsResponseType('vp_token')) ||
177
- (verifiedAuthorizationRequest.versions.every((version) => version <= did_auth_siop_1.SupportedVersion.JWT_VC_PRESENTATION_PROFILE_v1) &&
178
- verifiedAuthorizationRequest.presentationDefinitions &&
179
- verifiedAuthorizationRequest.presentationDefinitions.length > 0)
180
- ? verifiedAuthorizationRequest.presentationDefinitions
181
- : undefined,
182
- };
183
- });
159
+ : (verifiedAuthorizationRequest.issuer ?? verifiedAuthorizationRequest.registrationMetadataPayload?.client_id));
160
+ const uri = url.includes('://') ? new URL(url) : undefined;
161
+ const correlationId = uri?.hostname ?? (await this.determineCorrelationId(uri, verifiedAuthorizationRequest, clientName, context));
162
+ const clientId = await verifiedAuthorizationRequest.authorizationRequest.getMergedProperty('client_id');
163
+ return {
164
+ issuer: verifiedAuthorizationRequest.issuer,
165
+ correlationId,
166
+ registrationMetadataPayload: verifiedAuthorizationRequest.registrationMetadataPayload,
167
+ uri,
168
+ name: clientName,
169
+ clientId,
170
+ presentationDefinitions: (await verifiedAuthorizationRequest.authorizationRequest.containsResponseType('vp_token')) ||
171
+ (verifiedAuthorizationRequest.versions.every((version) => version <= SupportedVersion.JWT_VC_PRESENTATION_PROFILE_v1) &&
172
+ verifiedAuthorizationRequest.presentationDefinitions &&
173
+ verifiedAuthorizationRequest.presentationDefinitions.length > 0)
174
+ ? verifiedAuthorizationRequest.presentationDefinitions
175
+ : undefined,
176
+ dcqlQuery: verifiedAuthorizationRequest.dcqlQuery,
177
+ };
184
178
  }
185
- determineCorrelationId(uri, verifiedAuthorizationRequest, clientName, context) {
186
- return __awaiter(this, void 0, void 0, function* () {
187
- var _a, _b;
188
- if (uri) {
189
- return (_a = (yield (0, Siopv2MachineService_1.translateCorrelationIdToName)(uri.hostname, context))) !== null && _a !== void 0 ? _a : uri.hostname;
190
- }
191
- if (verifiedAuthorizationRequest.issuer) {
192
- const issuerHostname = verifiedAuthorizationRequest.issuer.split('://')[1];
193
- return (_b = (yield (0, Siopv2MachineService_1.translateCorrelationIdToName)(issuerHostname, context))) !== null && _b !== void 0 ? _b : issuerHostname;
194
- }
195
- if (clientName) {
196
- return clientName;
197
- }
198
- throw new Error("Can't determine correlationId from request");
199
- });
179
+ async determineCorrelationId(uri, verifiedAuthorizationRequest, clientName, context) {
180
+ if (uri) {
181
+ return (await translateCorrelationIdToName(uri.hostname, context)) ?? uri.hostname;
182
+ }
183
+ if (verifiedAuthorizationRequest.issuer) {
184
+ const issuerHostname = verifiedAuthorizationRequest.issuer.split('://')[1];
185
+ return (await translateCorrelationIdToName(issuerHostname, context)) ?? issuerHostname;
186
+ }
187
+ if (clientName) {
188
+ return clientName;
189
+ }
190
+ throw new Error("Can't determine correlationId from request");
200
191
  }
201
- siopRetrieveContact(args, context) {
202
- return __awaiter(this, void 0, void 0, function* () {
203
- const { authorizationRequestData } = args;
204
- const { agent } = context;
205
- if (authorizationRequestData === undefined) {
206
- return Promise.reject(Error('Missing authorization request data in context'));
207
- }
208
- return agent
209
- .cmGetContacts({
210
- filter: [
211
- {
212
- identities: {
213
- identifier: {
214
- correlationId: authorizationRequestData.correlationId,
215
- },
192
+ async siopRetrieveContact(args, context) {
193
+ const { authorizationRequestData } = args;
194
+ const { agent } = context;
195
+ if (authorizationRequestData === undefined) {
196
+ return Promise.reject(Error('Missing authorization request data in context'));
197
+ }
198
+ return agent
199
+ .cmGetContacts({
200
+ filter: [
201
+ {
202
+ identities: {
203
+ identifier: {
204
+ correlationId: authorizationRequestData.correlationId,
216
205
  },
217
206
  },
218
- ],
219
- })
220
- .then((contacts) => (contacts.length === 1 ? contacts[0] : undefined));
221
- });
207
+ },
208
+ ],
209
+ })
210
+ .then((contacts) => (contacts.length === 1 ? contacts[0] : undefined));
222
211
  }
223
- siopAddContactIdentity(args, context) {
224
- return __awaiter(this, void 0, void 0, function* () {
225
- var _a;
226
- const { agent } = context;
227
- const { contact, authorizationRequestData } = args;
228
- if (contact === undefined) {
229
- return Promise.reject(Error('Missing contact in context'));
230
- }
231
- if (authorizationRequestData === undefined) {
232
- return Promise.reject(Error('Missing authorization request data in context'));
233
- }
234
- // TODO: Makes sense to move these types of common queries/retrievals to the SIOP auth request object
235
- const clientId = (_a = authorizationRequestData.clientId) !== null && _a !== void 0 ? _a : authorizationRequestData.issuer;
236
- const correlationId = clientId
237
- ? clientId.startsWith('did:')
238
- ? clientId
239
- : `${new URL(clientId).protocol}//${new URL(clientId).hostname}`
240
- : undefined;
241
- if (correlationId) {
242
- const identity = {
243
- alias: correlationId,
244
- origin: ssi_sdk_data_store_1.IdentityOrigin.EXTERNAL,
245
- roles: [ssi_sdk_data_store_1.CredentialRole.ISSUER],
246
- identifier: {
247
- type: correlationId.startsWith('did:') ? ssi_sdk_data_store_1.CorrelationIdentifierType.DID : ssi_sdk_data_store_1.CorrelationIdentifierType.URL,
248
- correlationId,
249
- },
250
- };
251
- const addedIdentity = yield agent.cmAddIdentity({ contactId: contact.id, identity });
252
- yield context.agent.emit(types_1.Siopv2HolderEvent.CONTACT_IDENTITY_CREATED, {
253
- contactId: contact.id,
254
- identity: addedIdentity,
212
+ async siopAddContactIdentity(args, context) {
213
+ const { agent } = context;
214
+ const { contact, authorizationRequestData } = args;
215
+ if (contact === undefined) {
216
+ return Promise.reject(Error('Missing contact in context'));
217
+ }
218
+ if (authorizationRequestData === undefined) {
219
+ return Promise.reject(Error('Missing authorization request data in context'));
220
+ }
221
+ // TODO: Makes sense to move these types of common queries/retrievals to the SIOP auth request object
222
+ const clientId = authorizationRequestData.clientId ?? authorizationRequestData.issuer;
223
+ const correlationId = clientId
224
+ ? clientId.startsWith('did:')
225
+ ? clientId
226
+ : `${new URL(clientId).protocol}//${new URL(clientId).hostname}`
227
+ : undefined;
228
+ if (correlationId) {
229
+ const identity = {
230
+ alias: correlationId,
231
+ origin: IdentityOrigin.EXTERNAL,
232
+ roles: [CredentialRole.ISSUER],
233
+ identifier: {
234
+ type: correlationId.startsWith('did:') ? CorrelationIdentifierType.DID : CorrelationIdentifierType.URL,
235
+ correlationId,
236
+ },
237
+ };
238
+ const addedIdentity = await agent.cmAddIdentity({ contactId: contact.id, identity });
239
+ await context.agent.emit(Siopv2HolderEvent.CONTACT_IDENTITY_CREATED, {
240
+ contactId: contact.id,
241
+ identity: addedIdentity,
242
+ });
243
+ logger.info(`Contact identity created: ${JSON.stringify(addedIdentity)}`);
244
+ }
245
+ }
246
+ async siopSendResponse(args, context) {
247
+ const { didAuthConfig, authorizationRequestData, selectedCredentials, isFirstParty } = args;
248
+ if (didAuthConfig === undefined) {
249
+ return Promise.reject(Error('Missing config in context'));
250
+ }
251
+ if (authorizationRequestData === undefined) {
252
+ return Promise.reject(Error('Missing authorization request data in context'));
253
+ }
254
+ const pex = new PEX({ hasher: this.hasher });
255
+ const verifiableCredentialsWithDefinition = [];
256
+ const dcqlCredentialsWithCredentials = new Map();
257
+ if (Array.isArray(authorizationRequestData.presentationDefinitions) && authorizationRequestData?.presentationDefinitions.length > 0) {
258
+ try {
259
+ authorizationRequestData.presentationDefinitions?.forEach((presentationDefinition) => {
260
+ const { areRequiredCredentialsPresent, verifiableCredential: verifiableCredentials } = pex.selectFrom(presentationDefinition.definition, selectedCredentials.map((udc) => udc.originalVerifiableCredential));
261
+ if (areRequiredCredentialsPresent !== Status.ERROR && verifiableCredentials) {
262
+ let uniqueDigitalCredentials = [];
263
+ uniqueDigitalCredentials = verifiableCredentials.map((vc) => {
264
+ // @ts-ignore FIXME Funke
265
+ const hash = typeof vc === 'string' ? computeEntryHash(vc.split('~'[0])) : computeEntryHash(vc);
266
+ const udc = selectedCredentials.find((udc) => udc.hash == hash || udc.originalVerifiableCredential == vc);
267
+ if (!udc) {
268
+ throw Error(`UniqueDigitalCredential could not be found in store. Either the credential is not present in the store or the hash is not correct.`);
269
+ }
270
+ return udc;
271
+ });
272
+ verifiableCredentialsWithDefinition.push({
273
+ definition: presentationDefinition,
274
+ credentials: uniqueDigitalCredentials,
275
+ });
276
+ }
255
277
  });
256
- logger.info(`Contact identity created: ${JSON.stringify(addedIdentity)}`);
257
278
  }
258
- });
259
- }
260
- siopSendResponse(args, context) {
261
- return __awaiter(this, void 0, void 0, function* () {
262
- var _a;
263
- const { didAuthConfig, authorizationRequestData, selectedCredentials, isFirstParty } = args;
264
- if (didAuthConfig === undefined) {
265
- return Promise.reject(Error('Missing config in context'));
279
+ catch (e) {
280
+ return Promise.reject(e);
266
281
  }
267
- if (authorizationRequestData === undefined) {
268
- return Promise.reject(Error('Missing authorization request data in context'));
282
+ if (verifiableCredentialsWithDefinition.length === 0) {
283
+ return Promise.reject(Error('None of the selected credentials match any of the presentation definitions.'));
269
284
  }
270
- const pex = new pex_1.PEX({ hasher: this.hasher });
271
- const verifiableCredentialsWithDefinition = [];
272
- (_a = authorizationRequestData.presentationDefinitions) === null || _a === void 0 ? void 0 : _a.forEach((presentationDefinition) => {
273
- const { areRequiredCredentialsPresent, verifiableCredential: verifiableCredentials } = pex.selectFrom(presentationDefinition.definition, selectedCredentials.map((udc) => udc.originalVerifiableCredential));
274
- if (areRequiredCredentialsPresent !== pex_1.Status.ERROR && verifiableCredentials) {
275
- const uniqueDigitalCredentials = verifiableCredentials.map((vc) => {
276
- // @ts-ignore FIXME Funke
277
- const hash = (0, utils_1.computeEntryHash)(vc);
278
- const udc = selectedCredentials.find((udc) => udc.hash == hash);
279
- if (!udc) {
280
- throw Error('UniqueDigitalCredential could not be found');
285
+ }
286
+ else if (authorizationRequestData.dcqlQuery) {
287
+ //TODO Only SD-JWT and MSO MDOC are supported at the moment
288
+ if (this.hasMDocCredentials(selectedCredentials) || this.hasSdJwtCredentials(selectedCredentials)) {
289
+ try {
290
+ selectedCredentials.forEach((vc) => {
291
+ if (this.isSdJwtCredential(vc)) {
292
+ const payload = vc.originalVerifiableCredential.decodedPayload;
293
+ const result = {
294
+ claims: payload,
295
+ vct: payload.vct,
296
+ credential_format: 'vc+sd-jwt',
297
+ };
298
+ dcqlCredentialsWithCredentials.set(result, vc);
299
+ //FIXME MDoc namespaces are incompatible: array of strings vs complex object - https://sphereon.atlassian.net/browse/SPRIND-143
300
+ }
301
+ else {
302
+ throw Error(`Invalid credential format: ${vc.digitalCredential.documentFormat}`);
281
303
  }
282
- return udc;
283
- });
284
- verifiableCredentialsWithDefinition.push({
285
- definition: presentationDefinition,
286
- credentials: uniqueDigitalCredentials,
287
304
  });
288
305
  }
289
- });
290
- if (verifiableCredentialsWithDefinition.length === 0) {
291
- return Promise.reject(Error('None of the selected credentials match any of the presentation definitions.'));
292
- }
293
- const response = yield (0, Siopv2MachineService_1.siopSendAuthorizationResponse)(ssi_sdk_data_store_1.ConnectionType.SIOPv2_OpenID4VP, Object.assign(Object.assign(Object.assign({ sessionId: didAuthConfig.sessionId }, (args.idOpts && { idOpts: args.idOpts })), (authorizationRequestData.presentationDefinitions !== undefined && { verifiableCredentialsWithDefinition })), { isFirstParty, hasher: this.hasher }), context);
294
- const contentType = response.headers.get('content-type') || '';
295
- let responseBody = null;
296
- const text = yield response.text();
297
- if (text) {
298
- responseBody = contentType.includes('application/json') || text.startsWith('{') ? JSON.parse(text) : text;
306
+ catch (e) {
307
+ return Promise.reject(e);
308
+ }
309
+ const dcqlPresentationRecord = {};
310
+ const queryResult = DcqlQuery.query(authorizationRequestData.dcqlQuery, Array.from(dcqlCredentialsWithCredentials.keys()));
311
+ for (const [key, value] of Object.entries(queryResult.credential_matches)) {
312
+ if (value.success) {
313
+ dcqlPresentationRecord[key] = this.retrieveEncodedCredential(dcqlCredentialsWithCredentials.get(value.output));
314
+ }
315
+ }
299
316
  }
300
- return {
301
- body: responseBody,
302
- url: response.url,
303
- queryParams: (0, did_auth_siop_1.decodeUriAsJson)(response.url),
304
- };
305
- });
317
+ }
318
+ const response = await siopSendAuthorizationResponse(ConnectionType.SIOPv2_OpenID4VP, {
319
+ sessionId: didAuthConfig.sessionId,
320
+ ...(args.idOpts && { idOpts: args.idOpts }),
321
+ ...(authorizationRequestData.presentationDefinitions !== undefined && { verifiableCredentialsWithDefinition }),
322
+ isFirstParty,
323
+ hasher: this.hasher,
324
+ }, context);
325
+ const contentType = response.headers.get('content-type') || '';
326
+ let responseBody = null;
327
+ const text = await response.text();
328
+ if (text) {
329
+ responseBody = contentType.includes('application/json') || text.startsWith('{') ? JSON.parse(text) : text;
330
+ }
331
+ return {
332
+ body: responseBody,
333
+ url: response?.url,
334
+ queryParams: decodeUriAsJson(response?.url),
335
+ };
306
336
  }
307
- siopGetSelectableCredentials(args, context) {
308
- return __awaiter(this, void 0, void 0, function* () {
309
- const { authorizationRequestData } = args;
310
- if (!authorizationRequestData ||
311
- !authorizationRequestData.presentationDefinitions ||
312
- authorizationRequestData.presentationDefinitions.length === 0) {
313
- return Promise.reject(Error('Missing required fields in arguments or context'));
314
- }
315
- if (authorizationRequestData.presentationDefinitions.length > 1) {
316
- return Promise.reject(Error('Multiple presentation definitions present'));
317
- }
318
- return (0, Siopv2MachineService_1.getSelectableCredentials)(authorizationRequestData.presentationDefinitions[0].definition, context);
319
- });
337
+ hasMDocCredentials = (credentials) => {
338
+ return credentials.some(this.isMDocCredential);
339
+ };
340
+ isMDocCredential = (credential) => {
341
+ return (credential.digitalCredential.documentFormat === CredentialDocumentFormat.MSO_MDOC &&
342
+ credential.digitalCredential.documentType === DocumentType.VC);
343
+ };
344
+ hasSdJwtCredentials = (credentials) => {
345
+ return credentials.some(this.isSdJwtCredential);
346
+ };
347
+ isSdJwtCredential = (credential) => {
348
+ return (credential.digitalCredential.documentFormat === CredentialDocumentFormat.SD_JWT && credential.digitalCredential.documentType === DocumentType.VC);
349
+ };
350
+ retrieveEncodedCredential = (credential) => {
351
+ return credential.originalVerifiableCredential !== undefined &&
352
+ credential.originalVerifiableCredential !== null &&
353
+ credential?.originalVerifiableCredential?.compactSdJwtVc !== undefined &&
354
+ credential?.originalVerifiableCredential?.compactSdJwtVc !== null
355
+ ? credential.originalVerifiableCredential.compactSdJwtVc
356
+ : credential.originalVerifiableCredential;
357
+ };
358
+ async siopGetSelectableCredentials(args, context) {
359
+ const { authorizationRequestData } = args;
360
+ if (!authorizationRequestData ||
361
+ !authorizationRequestData.presentationDefinitions ||
362
+ authorizationRequestData.presentationDefinitions.length === 0) {
363
+ return Promise.reject(Error('Missing required fields in arguments or context'));
364
+ }
365
+ if (authorizationRequestData.presentationDefinitions.length > 1) {
366
+ return Promise.reject(Error('Multiple presentation definitions present'));
367
+ }
368
+ return getSelectableCredentials(authorizationRequestData.presentationDefinitions[0].definition, context);
320
369
  }
321
370
  }
322
- exports.DidAuthSiopOpAuthenticator = DidAuthSiopOpAuthenticator;
323
371
  //# sourceMappingURL=DidAuthSiopOpAuthenticator.js.map