@sphereon/ssi-sdk.oid4vci-holder 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 (48) hide show
  1. package/dist/agent/OID4VCIHolder.d.ts +1 -0
  2. package/dist/agent/OID4VCIHolder.d.ts.map +1 -1
  3. package/dist/agent/OID4VCIHolder.js +733 -721
  4. package/dist/agent/OID4VCIHolder.js.map +1 -1
  5. package/dist/index.d.ts +1 -0
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +8 -27
  8. package/dist/index.js.map +1 -1
  9. package/dist/link-handler/index.d.ts.map +1 -1
  10. package/dist/link-handler/index.js +55 -49
  11. package/dist/link-handler/index.js.map +1 -1
  12. package/dist/listeners/headlessStateNavListener.js +7 -20
  13. package/dist/listeners/headlessStateNavListener.js.map +1 -1
  14. package/dist/localization/Localization.js +38 -43
  15. package/dist/localization/Localization.js.map +1 -1
  16. package/dist/machines/firstPartyMachine.d.ts.map +1 -1
  17. package/dist/machines/firstPartyMachine.js +89 -88
  18. package/dist/machines/firstPartyMachine.js.map +1 -1
  19. package/dist/machines/oid4vciMachine.d.ts.map +1 -1
  20. package/dist/machines/oid4vciMachine.js +307 -326
  21. package/dist/machines/oid4vciMachine.js.map +1 -1
  22. package/dist/mappers/OIDC4VCIBrandingMapper.d.ts.map +1 -1
  23. package/dist/mappers/OIDC4VCIBrandingMapper.js +164 -136
  24. package/dist/mappers/OIDC4VCIBrandingMapper.js.map +1 -1
  25. package/dist/services/FirstPartyMachineServices.d.ts.map +1 -1
  26. package/dist/services/FirstPartyMachineServices.js +20 -30
  27. package/dist/services/FirstPartyMachineServices.js.map +1 -1
  28. package/dist/services/OID4VCIHolderService.d.ts.map +1 -1
  29. package/dist/services/OID4VCIHolderService.js +147 -154
  30. package/dist/services/OID4VCIHolderService.js.map +1 -1
  31. package/dist/types/FirstPartyMachine.d.ts.map +1 -1
  32. package/dist/types/FirstPartyMachine.js +6 -9
  33. package/dist/types/FirstPartyMachine.js.map +1 -1
  34. package/dist/types/IOID4VCIHolder.d.ts +6 -6
  35. package/dist/types/IOID4VCIHolder.d.ts.map +1 -1
  36. package/dist/types/IOID4VCIHolder.js +20 -23
  37. package/dist/types/IOID4VCIHolder.js.map +1 -1
  38. package/package.json +26 -25
  39. package/src/agent/OID4VCIHolder.ts +33 -11
  40. package/src/index.ts +1 -0
  41. package/src/link-handler/index.ts +6 -8
  42. package/src/machines/firstPartyMachine.ts +60 -69
  43. package/src/machines/oid4vciMachine.ts +9 -11
  44. package/src/mappers/OIDC4VCIBrandingMapper.ts +26 -25
  45. package/src/services/FirstPartyMachineServices.ts +11 -10
  46. package/src/services/OID4VCIHolderService.ts +25 -24
  47. package/src/types/FirstPartyMachine.ts +56 -64
  48. package/src/types/IOID4VCIHolder.ts +35 -32
@@ -1,36 +1,23 @@
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.OID4VCIHolder = exports.oid4vciHolderContextMethods = void 0;
13
- exports.signCallback = signCallback;
14
- exports.verifyEBSICredentialIssuer = verifyEBSICredentialIssuer;
15
- const oid4vci_client_1 = require("@sphereon/oid4vci-client");
16
- const oid4vci_common_1 = require("@sphereon/oid4vci-common");
17
- const ssi_sdk_ext_did_utils_1 = require("@sphereon/ssi-sdk-ext.did-utils");
18
- const ssi_sdk_ext_identifier_resolution_1 = require("@sphereon/ssi-sdk-ext.identifier-resolution");
19
- const ssi_sdk_ext_key_utils_1 = require("@sphereon/ssi-sdk-ext.key-utils");
20
- const ssi_sdk_data_store_1 = require("@sphereon/ssi-sdk.data-store");
21
- const ssi_types_1 = require("@sphereon/ssi-types");
22
- const utils_1 = require("@veramo/utils");
23
- const did_jwt_1 = require("did-jwt");
24
- const uuid_1 = require("uuid");
25
- const oid4vciMachine_1 = require("../machines/oid4vciMachine");
26
- const IOID4VCIHolder_1 = require("../types/IOID4VCIHolder");
27
- const OID4VCIHolderService_1 = require("../services/OID4VCIHolderService");
28
- require("cross-fetch/polyfill");
1
+ import { CredentialOfferClient, MetadataClient, OpenID4VCIClient } from '@sphereon/oid4vci-client';
2
+ import { DefaultURISchemes, getTypesFromAuthorizationDetails, getTypesFromCredentialOffer, getTypesFromObject, } from '@sphereon/oid4vci-common';
3
+ import { SupportedDidMethodEnum } from '@sphereon/ssi-sdk-ext.did-utils';
4
+ import { isManagedIdentifierDidOpts, isManagedIdentifierDidResult, isManagedIdentifierJwkResult, isManagedIdentifierKidResult, isManagedIdentifierResult, isManagedIdentifierX5cOpts, isManagedIdentifierX5cResult, } from '@sphereon/ssi-sdk-ext.identifier-resolution';
5
+ import { signatureAlgorithmFromKey } from '@sphereon/ssi-sdk-ext.key-utils';
6
+ import { ConnectionType, CorrelationIdentifierType, CredentialCorrelationType, CredentialRole, ensureRawDocument, IdentityOrigin, } from '@sphereon/ssi-sdk.data-store';
7
+ import { CredentialMapper, JoseSignatureAlgorithm, Loggers, parseDid, } from '@sphereon/ssi-types';
8
+ import { asArray, computeEntryHash } from '@veramo/utils';
9
+ import { decodeJWT } from 'did-jwt';
10
+ import { v4 as uuidv4 } from 'uuid';
11
+ import { OID4VCIMachine } from '../machines/oid4vciMachine';
12
+ import { OID4VCIHolderEvent, OID4VCIMachineServices, RequestType, } from '../types/IOID4VCIHolder';
13
+ import { getBasicIssuerLocaleBranding, getCredentialBranding, getCredentialConfigsSupportedMerged, getIdentifierOpts, getIssuanceOpts, mapCredentialToAccept, selectCredentialLocaleBranding, startFirstPartApplicationMachine, verifyCredentialToAccept, } from '../services/OID4VCIHolderService';
14
+ import 'cross-fetch/polyfill';
15
+ import { defaultHasher } from '@sphereon/ssi-sdk.core';
29
16
  /**
30
17
  * {@inheritDoc IOID4VCIHolder}
31
18
  */
32
19
  // Exposing the methods here for any REST implementation
33
- exports.oid4vciHolderContextMethods = [
20
+ export const oid4vciHolderContextMethods = [
34
21
  'cmGetContacts',
35
22
  'cmGetContact',
36
23
  'cmAddContact',
@@ -43,12 +30,11 @@ exports.oid4vciHolderContextMethods = [
43
30
  'keyManagerSign',
44
31
  'verifyCredential',
45
32
  ];
46
- const logger = ssi_types_1.Loggers.DEFAULT.get('sphereon:oid4vci:holder');
47
- function signCallback(identifier, context, nonce) {
48
- return (jwt, kid) => __awaiter(this, void 0, void 0, function* () {
49
- var _a;
50
- let resolution = yield context.agent.identifierManagedGet(identifier);
51
- const jwk = (_a = jwt.header.jwk) !== null && _a !== void 0 ? _a : (resolution.method === 'jwk' ? resolution.jwk : undefined);
33
+ const logger = Loggers.DEFAULT.get('sphereon:oid4vci:holder');
34
+ export function signCallback(identifier, context, nonce) {
35
+ return async (jwt, kid) => {
36
+ let resolution = await context.agent.identifierManagedGet(identifier);
37
+ const jwk = jwt.header.jwk ?? (resolution.method === 'jwk' ? resolution.jwk : undefined);
52
38
  if (!resolution.issuer && !jwt.payload.iss) {
53
39
  return Promise.reject(Error(`No issuer could be determined from the JWT ${JSON.stringify(jwt)} or identifier resolution`));
54
40
  }
@@ -61,78 +47,82 @@ function signCallback(identifier, context, nonce) {
61
47
  console.log(`Deleting kid, as we are using a jwk and the oid4vci spec does not allow both to be present (which is not the case in the JOSE spec)`);
62
48
  delete header.kid; // The OID4VCI spec does not allow a JWK with kid present although the JWS spec does
63
49
  }
64
- return (yield context.agent.jwtCreateJwsCompactSignature({
65
- issuer: Object.assign(Object.assign({}, resolution), { noIssPayloadUpdate: false }),
50
+ return (await context.agent.jwtCreateJwsCompactSignature({
51
+ issuer: { ...resolution, noIssPayloadUpdate: false },
66
52
  protectedHeader: header,
67
53
  payload,
68
54
  })).jwt;
69
- });
55
+ };
70
56
  }
71
- function verifyEBSICredentialIssuer(args) {
72
- return __awaiter(this, void 0, void 0, function* () {
73
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
74
- const { wrappedVc, issuerType = ['TI'] } = args;
75
- const issuer = (_b = (_a = wrappedVc.decoded) === null || _a === void 0 ? void 0 : _a.iss) !== null && _b !== void 0 ? _b : (typeof ((_d = (_c = wrappedVc.decoded) === null || _c === void 0 ? void 0 : _c.vc) === null || _d === void 0 ? void 0 : _d.issuer) === 'string' ? (_f = (_e = wrappedVc.decoded) === null || _e === void 0 ? void 0 : _e.vc) === null || _f === void 0 ? void 0 : _f.issuer : (_j = (_h = (_g = wrappedVc.decoded) === null || _g === void 0 ? void 0 : _g.vc) === null || _h === void 0 ? void 0 : _h.issuer) === null || _j === void 0 ? void 0 : _j.existingInstanceId);
76
- if (!issuer) {
77
- throw Error('The issuer of the VC is required to be present');
78
- }
79
- const url = `https://api-conformance.ebsi.eu/trusted-issuers-registry/v4/issuers/${issuer}`;
80
- const response = yield fetch(url);
81
- if (response.status !== 200) {
82
- throw Error('The issuer of the VC cannot be trusted');
83
- }
84
- const payload = yield response.json();
85
- if (!payload.attributes.some((a) => issuerType.includes(a.issuerType))) {
86
- throw Error(`The issuer type is required to be one of: ${issuerType.join(', ')}`);
87
- }
88
- return payload;
89
- });
57
+ export async function verifyEBSICredentialIssuer(args) {
58
+ const { wrappedVc, issuerType = ['TI'] } = args;
59
+ const issuer = wrappedVc.decoded?.iss ??
60
+ (typeof wrappedVc.decoded?.vc?.issuer === 'string' ? wrappedVc.decoded?.vc?.issuer : wrappedVc.decoded?.vc?.issuer?.existingInstanceId);
61
+ if (!issuer) {
62
+ throw Error('The issuer of the VC is required to be present');
63
+ }
64
+ const url = `https://api-conformance.ebsi.eu/trusted-issuers-registry/v4/issuers/${issuer}`;
65
+ const response = await fetch(url);
66
+ if (response.status !== 200) {
67
+ throw Error('The issuer of the VC cannot be trusted');
68
+ }
69
+ const payload = await response.json();
70
+ if (!payload.attributes.some((a) => issuerType.includes(a.issuerType))) {
71
+ throw Error(`The issuer type is required to be one of: ${issuerType.join(', ')}`);
72
+ }
73
+ return payload;
90
74
  }
91
- class OID4VCIHolder {
75
+ export class OID4VCIHolder {
76
+ hasher;
77
+ eventTypes = [
78
+ OID4VCIHolderEvent.CONTACT_IDENTITY_CREATED,
79
+ OID4VCIHolderEvent.CREDENTIAL_STORED,
80
+ OID4VCIHolderEvent.IDENTIFIER_CREATED,
81
+ ];
82
+ methods = {
83
+ oid4vciHolderStart: this.oid4vciHolderStart.bind(this),
84
+ oid4vciHolderGetIssuerMetadata: this.oid4vciHolderGetIssuerMetadata.bind(this),
85
+ oid4vciHolderGetMachineInterpreter: this.oid4vciHolderGetMachineInterpreter.bind(this),
86
+ oid4vciHolderCreateCredentialsToSelectFrom: this.oid4vciHolderCreateCredentialsToSelectFrom.bind(this),
87
+ oid4vciHolderGetContact: this.oid4vciHolderGetContact.bind(this),
88
+ oid4vciHolderGetCredentials: this.oid4vciHolderGetCredentials.bind(this),
89
+ oid4vciHolderGetCredential: this.oid4vciHolderGetCredential.bind(this),
90
+ oid4vciHolderAddContactIdentity: this.oid4vciHolderAddContactIdentity.bind(this),
91
+ oid4vciHolderAssertValidCredentials: this.oid4vciHolderAssertValidCredentials.bind(this),
92
+ oid4vciHolderStoreCredentialBranding: this.oid4vciHolderStoreCredentialBranding.bind(this),
93
+ oid4vciHolderStoreCredentials: this.oid4vciHolderStoreCredentials.bind(this),
94
+ oid4vciHolderSendNotification: this.oid4vciHolderSendNotification.bind(this),
95
+ oid4vciHolderGetIssuerBranding: this.oid4vciHolderGetIssuerBranding.bind(this),
96
+ oid4vciHolderStoreIssuerBranding: this.oid4vciHolderStoreIssuerBranding.bind(this),
97
+ };
98
+ vcFormatPreferences = ['vc+sd-jwt', 'mso_mdoc', 'jwt_vc_json', 'jwt_vc', 'ldp_vc'];
99
+ jsonldCryptographicSuitePreferences = [
100
+ 'Ed25519Signature2018',
101
+ 'EcdsaSecp256k1Signature2019',
102
+ 'Ed25519Signature2020',
103
+ 'JsonWebSignature2020',
104
+ // "JcsEd25519Signature2020"
105
+ ];
106
+ didMethodPreferences = [
107
+ SupportedDidMethodEnum.DID_JWK, // FIXME prefer JWK until we devise a method to detect when to use EBSI/jcs for did:key and when not
108
+ SupportedDidMethodEnum.DID_KEY,
109
+ SupportedDidMethodEnum.DID_OYD,
110
+ SupportedDidMethodEnum.DID_EBSI,
111
+ SupportedDidMethodEnum.DID_ION,
112
+ ];
113
+ jwtCryptographicSuitePreferences = [
114
+ JoseSignatureAlgorithm.ES256,
115
+ JoseSignatureAlgorithm.ES256K,
116
+ JoseSignatureAlgorithm.EdDSA,
117
+ ];
118
+ static DEFAULT_MOBILE_REDIRECT_URI = `${DefaultURISchemes.CREDENTIAL_OFFER}://`;
119
+ defaultAuthorizationRequestOpts = { redirectUri: OID4VCIHolder.DEFAULT_MOBILE_REDIRECT_URI };
120
+ onContactIdentityCreated;
121
+ onCredentialStored;
122
+ onIdentifierCreated;
123
+ onVerifyEBSICredentialIssuer;
92
124
  constructor(options) {
93
- this.eventTypes = [
94
- IOID4VCIHolder_1.OID4VCIHolderEvent.CONTACT_IDENTITY_CREATED,
95
- IOID4VCIHolder_1.OID4VCIHolderEvent.CREDENTIAL_STORED,
96
- IOID4VCIHolder_1.OID4VCIHolderEvent.IDENTIFIER_CREATED,
97
- ];
98
- this.methods = {
99
- oid4vciHolderStart: this.oid4vciHolderStart.bind(this),
100
- oid4vciHolderGetIssuerMetadata: this.oid4vciHolderGetIssuerMetadata.bind(this),
101
- oid4vciHolderGetMachineInterpreter: this.oid4vciHolderGetMachineInterpreter.bind(this),
102
- oid4vciHolderCreateCredentialsToSelectFrom: this.oid4vciHolderCreateCredentialsToSelectFrom.bind(this),
103
- oid4vciHolderGetContact: this.oid4vciHolderGetContact.bind(this),
104
- oid4vciHolderGetCredentials: this.oid4vciHolderGetCredentials.bind(this),
105
- oid4vciHolderGetCredential: this.oid4vciHolderGetCredential.bind(this),
106
- oid4vciHolderAddContactIdentity: this.oid4vciHolderAddContactIdentity.bind(this),
107
- oid4vciHolderAssertValidCredentials: this.oid4vciHolderAssertValidCredentials.bind(this),
108
- oid4vciHolderStoreCredentialBranding: this.oid4vciHolderStoreCredentialBranding.bind(this),
109
- oid4vciHolderStoreCredentials: this.oid4vciHolderStoreCredentials.bind(this),
110
- oid4vciHolderSendNotification: this.oid4vciHolderSendNotification.bind(this),
111
- oid4vciHolderGetIssuerBranding: this.oid4vciHolderGetIssuerBranding.bind(this),
112
- oid4vciHolderStoreIssuerBranding: this.oid4vciHolderStoreIssuerBranding.bind(this),
113
- };
114
- this.vcFormatPreferences = ['vc+sd-jwt', 'mso_mdoc', 'jwt_vc_json', 'jwt_vc', 'ldp_vc'];
115
- this.jsonldCryptographicSuitePreferences = [
116
- 'Ed25519Signature2018',
117
- 'EcdsaSecp256k1Signature2019',
118
- 'Ed25519Signature2020',
119
- 'JsonWebSignature2020',
120
- // "JcsEd25519Signature2020"
121
- ];
122
- this.didMethodPreferences = [
123
- ssi_sdk_ext_did_utils_1.SupportedDidMethodEnum.DID_JWK, // FIXME prefer JWK until we devise a method to detect when to use EBSI/jcs for did:key and when not
124
- ssi_sdk_ext_did_utils_1.SupportedDidMethodEnum.DID_KEY,
125
- ssi_sdk_ext_did_utils_1.SupportedDidMethodEnum.DID_OYD,
126
- ssi_sdk_ext_did_utils_1.SupportedDidMethodEnum.DID_EBSI,
127
- ssi_sdk_ext_did_utils_1.SupportedDidMethodEnum.DID_ION,
128
- ];
129
- this.jwtCryptographicSuitePreferences = [
130
- ssi_types_1.JoseSignatureAlgorithm.ES256,
131
- ssi_types_1.JoseSignatureAlgorithm.ES256K,
132
- ssi_types_1.JoseSignatureAlgorithm.EdDSA,
133
- ];
134
- this.defaultAuthorizationRequestOpts = { redirectUri: OID4VCIHolder.DEFAULT_MOBILE_REDIRECT_URI };
135
- const { onContactIdentityCreated, onCredentialStored, onIdentifierCreated, onVerifyEBSICredentialIssuer, vcFormatPreferences, jsonldCryptographicSuitePreferences, didMethodPreferences, jwtCryptographicSuitePreferences, defaultAuthorizationRequestOptions, hasher, } = Object.assign({}, options);
125
+ const { onContactIdentityCreated, onCredentialStored, onIdentifierCreated, onVerifyEBSICredentialIssuer, vcFormatPreferences, jsonldCryptographicSuitePreferences, didMethodPreferences, jwtCryptographicSuitePreferences, defaultAuthorizationRequestOptions, hasher = defaultHasher, } = { ...options };
136
126
  this.hasher = hasher;
137
127
  if (vcFormatPreferences !== undefined && vcFormatPreferences.length > 0) {
138
128
  this.vcFormatPreferences = vcFormatPreferences;
@@ -154,51 +144,56 @@ class OID4VCIHolder {
154
144
  this.onIdentifierCreated = onIdentifierCreated;
155
145
  this.onVerifyEBSICredentialIssuer = onVerifyEBSICredentialIssuer;
156
146
  }
157
- onEvent(event, context) {
158
- return __awaiter(this, void 0, void 0, function* () {
159
- var _a, _b, _c;
160
- switch (event.type) {
161
- case IOID4VCIHolder_1.OID4VCIHolderEvent.CONTACT_IDENTITY_CREATED:
162
- (_a = this.onContactIdentityCreated) === null || _a === void 0 ? void 0 : _a.call(this, event.data);
163
- break;
164
- case IOID4VCIHolder_1.OID4VCIHolderEvent.CREDENTIAL_STORED:
165
- (_b = this.onCredentialStored) === null || _b === void 0 ? void 0 : _b.call(this, event.data);
166
- break;
167
- case IOID4VCIHolder_1.OID4VCIHolderEvent.IDENTIFIER_CREATED:
168
- (_c = this.onIdentifierCreated) === null || _c === void 0 ? void 0 : _c.call(this, event.data);
169
- break;
170
- default:
171
- return Promise.reject(Error(`Event type ${event.type} not supported`));
172
- }
173
- });
147
+ async onEvent(event, context) {
148
+ switch (event.type) {
149
+ case OID4VCIHolderEvent.CONTACT_IDENTITY_CREATED:
150
+ this.onContactIdentityCreated?.(event.data);
151
+ break;
152
+ case OID4VCIHolderEvent.CREDENTIAL_STORED:
153
+ this.onCredentialStored?.(event.data);
154
+ break;
155
+ case OID4VCIHolderEvent.IDENTIFIER_CREATED:
156
+ this.onIdentifierCreated?.(event.data);
157
+ break;
158
+ default:
159
+ return Promise.reject(Error(`Event type ${event.type} not supported`));
160
+ }
174
161
  }
175
162
  /**
176
163
  * FIXME: This method can only be used locally. Creating the interpreter should be local to where the agent is running
177
164
  */
178
- oid4vciHolderGetMachineInterpreter(opts, context) {
179
- return __awaiter(this, void 0, void 0, function* () {
180
- const authorizationRequestOpts = Object.assign(Object.assign({}, this.defaultAuthorizationRequestOpts), opts.authorizationRequestOpts);
181
- const services = {
182
- [IOID4VCIHolder_1.OID4VCIMachineServices.start]: (args) => this.oid4vciHolderStart(Object.assign(Object.assign({}, args), { authorizationRequestOpts }), context),
183
- [IOID4VCIHolder_1.OID4VCIMachineServices.startFirstPartApplicationFlow]: (args) => (0, OID4VCIHolderService_1.startFirstPartApplicationMachine)(Object.assign(Object.assign({}, args), { stateNavigationListener: opts.firstPartyStateNavigationListener }), context),
184
- [IOID4VCIHolder_1.OID4VCIMachineServices.createCredentialsToSelectFrom]: (args) => this.oid4vciHolderCreateCredentialsToSelectFrom(args, context),
185
- [IOID4VCIHolder_1.OID4VCIMachineServices.getContact]: (args) => this.oid4vciHolderGetContact(args, context),
186
- [IOID4VCIHolder_1.OID4VCIMachineServices.getCredentials]: (args) => { var _a; return this.oid4vciHolderGetCredentials(Object.assign({ accessTokenOpts: (_a = args.accessTokenOpts) !== null && _a !== void 0 ? _a : opts.accessTokenOpts }, args), context); },
187
- [IOID4VCIHolder_1.OID4VCIMachineServices.addContactIdentity]: (args) => this.oid4vciHolderAddContactIdentity(args, context),
188
- [IOID4VCIHolder_1.OID4VCIMachineServices.getIssuerBranding]: (args) => this.oid4vciHolderGetIssuerBranding(args, context),
189
- [IOID4VCIHolder_1.OID4VCIMachineServices.storeIssuerBranding]: (args) => this.oid4vciHolderStoreIssuerBranding(args, context),
190
- [IOID4VCIHolder_1.OID4VCIMachineServices.assertValidCredentials]: (args) => this.oid4vciHolderAssertValidCredentials(args, context),
191
- [IOID4VCIHolder_1.OID4VCIMachineServices.storeCredentialBranding]: (args) => this.oid4vciHolderStoreCredentialBranding(args, context),
192
- [IOID4VCIHolder_1.OID4VCIMachineServices.storeCredentials]: (args) => this.oid4vciHolderStoreCredentials(args, context),
193
- [IOID4VCIHolder_1.OID4VCIMachineServices.sendNotification]: (args) => this.oid4vciHolderSendNotification(args, context),
194
- [IOID4VCIHolder_1.OID4VCIMachineServices.getFederationTrust]: (args) => this.getFederationTrust(args, context),
195
- };
196
- const oid4vciMachineInstanceArgs = Object.assign(Object.assign({}, opts), { authorizationRequestOpts, services: Object.assign(Object.assign({}, services), opts.services) });
197
- const { interpreter } = yield oid4vciMachine_1.OID4VCIMachine.newInstance(oid4vciMachineInstanceArgs, context);
198
- return {
199
- interpreter,
200
- };
201
- });
165
+ async oid4vciHolderGetMachineInterpreter(opts, context) {
166
+ const authorizationRequestOpts = { ...this.defaultAuthorizationRequestOpts, ...opts.authorizationRequestOpts };
167
+ const services = {
168
+ [OID4VCIMachineServices.start]: (args) => this.oid4vciHolderStart({
169
+ ...args,
170
+ authorizationRequestOpts,
171
+ }, context),
172
+ [OID4VCIMachineServices.startFirstPartApplicationFlow]: (args) => startFirstPartApplicationMachine({ ...args, stateNavigationListener: opts.firstPartyStateNavigationListener }, context),
173
+ [OID4VCIMachineServices.createCredentialsToSelectFrom]: (args) => this.oid4vciHolderCreateCredentialsToSelectFrom(args, context),
174
+ [OID4VCIMachineServices.getContact]: (args) => this.oid4vciHolderGetContact(args, context),
175
+ [OID4VCIMachineServices.getCredentials]: (args) => this.oid4vciHolderGetCredentials({ accessTokenOpts: args.accessTokenOpts ?? opts.accessTokenOpts, ...args }, context),
176
+ [OID4VCIMachineServices.addContactIdentity]: (args) => this.oid4vciHolderAddContactIdentity(args, context),
177
+ [OID4VCIMachineServices.getIssuerBranding]: (args) => this.oid4vciHolderGetIssuerBranding(args, context),
178
+ [OID4VCIMachineServices.storeIssuerBranding]: (args) => this.oid4vciHolderStoreIssuerBranding(args, context),
179
+ [OID4VCIMachineServices.assertValidCredentials]: (args) => this.oid4vciHolderAssertValidCredentials(args, context),
180
+ [OID4VCIMachineServices.storeCredentialBranding]: (args) => this.oid4vciHolderStoreCredentialBranding(args, context),
181
+ [OID4VCIMachineServices.storeCredentials]: (args) => this.oid4vciHolderStoreCredentials(args, context),
182
+ [OID4VCIMachineServices.sendNotification]: (args) => this.oid4vciHolderSendNotification(args, context),
183
+ [OID4VCIMachineServices.getFederationTrust]: (args) => this.getFederationTrust(args, context),
184
+ };
185
+ const oid4vciMachineInstanceArgs = {
186
+ ...opts,
187
+ authorizationRequestOpts,
188
+ services: {
189
+ ...services,
190
+ ...opts.services,
191
+ },
192
+ };
193
+ const { interpreter } = await OID4VCIMachine.newInstance(oid4vciMachineInstanceArgs, context);
194
+ return {
195
+ interpreter,
196
+ };
202
197
  }
203
198
  /**
204
199
  * This method is run before the machine starts! So there is no concept of the state machine context or states yet
@@ -208,307 +203,327 @@ class OID4VCIHolder {
208
203
  * @param context
209
204
  * @private
210
205
  */
211
- oid4vciHolderStart(args, context) {
212
- return __awaiter(this, void 0, void 0, function* () {
213
- var _a, _b, _c;
214
- const { requestData } = args;
215
- if (!requestData) {
216
- throw Error(`Cannot start the OID4VCI holder flow without request data being provided`);
217
- }
218
- const { uri = undefined } = requestData;
219
- if (!uri) {
220
- return Promise.reject(Error('Missing request URI in context'));
221
- }
222
- const authorizationRequestOpts = Object.assign(Object.assign({}, this.defaultAuthorizationRequestOpts), args.authorizationRequestOpts);
223
- // We filter the details first against our vcformat prefs
224
- authorizationRequestOpts.authorizationDetails = (authorizationRequestOpts === null || authorizationRequestOpts === void 0 ? void 0 : authorizationRequestOpts.authorizationDetails)
225
- ? (0, utils_1.asArray)(authorizationRequestOpts.authorizationDetails).filter((detail) => typeof detail === 'string' || this.vcFormatPreferences.includes(detail.format))
226
- : undefined;
227
- if (!authorizationRequestOpts.redirectUri) {
228
- authorizationRequestOpts.redirectUri = OID4VCIHolder.DEFAULT_MOBILE_REDIRECT_URI;
229
- }
230
- if (authorizationRequestOpts.redirectUri.startsWith('http') && !authorizationRequestOpts.clientId) {
231
- // At least set a default for a web based wallet.
232
- // TODO: We really need (dynamic) client registration support
233
- authorizationRequestOpts.clientId = authorizationRequestOpts.redirectUri;
234
- }
235
- let formats = this.vcFormatPreferences;
236
- const authFormats = (_a = authorizationRequestOpts === null || authorizationRequestOpts === void 0 ? void 0 : authorizationRequestOpts.authorizationDetails) === null || _a === void 0 ? void 0 : _a.map((detail) => (typeof detail === 'object' && 'format' in detail && detail.format ? detail.format : undefined)).filter((format) => !!format).map((format) => format);
237
- if (authFormats && authFormats.length > 0) {
238
- formats = Array.from(new Set(authFormats));
239
- }
240
- let oid4vciClient;
241
- let types = undefined;
242
- let offer;
243
- if (requestData.existingClientState) {
244
- oid4vciClient = yield oid4vci_client_1.OpenID4VCIClient.fromState({ state: requestData.existingClientState });
245
- offer = oid4vciClient.credentialOffer;
246
- }
247
- else {
248
- offer = requestData.credentialOffer;
249
- if (uri.startsWith(IOID4VCIHolder_1.RequestType.OPENID_INITIATE_ISSUANCE) ||
250
- uri.startsWith(IOID4VCIHolder_1.RequestType.OPENID_CREDENTIAL_OFFER) ||
251
- uri.match(/https?:\/\/.*credential_offer(_uri)=?.*/)) {
252
- if (!offer) {
253
- // Let's make sure to convert the URI to offer, as it matches the regexes. Normally this should already have happened at this point though
254
- offer = yield oid4vci_client_1.CredentialOfferClient.fromURI(uri);
255
- }
256
- }
257
- else {
258
- if (!!offer) {
259
- logger.warning(`Non default URI used for credential offer: ${uri}`);
260
- }
261
- }
206
+ async oid4vciHolderStart(args, context) {
207
+ const { requestData } = args;
208
+ if (!requestData) {
209
+ throw Error(`Cannot start the OID4VCI holder flow without request data being provided`);
210
+ }
211
+ const { uri = undefined } = requestData;
212
+ if (!uri) {
213
+ return Promise.reject(Error('Missing request URI in context'));
214
+ }
215
+ const authorizationRequestOpts = { ...this.defaultAuthorizationRequestOpts, ...args.authorizationRequestOpts };
216
+ // We filter the details first against our vcformat prefs
217
+ authorizationRequestOpts.authorizationDetails = authorizationRequestOpts?.authorizationDetails
218
+ ? asArray(authorizationRequestOpts.authorizationDetails).filter((detail) => typeof detail === 'string' || this.vcFormatPreferences.includes(detail.format))
219
+ : undefined;
220
+ if (!authorizationRequestOpts.redirectUri) {
221
+ authorizationRequestOpts.redirectUri = OID4VCIHolder.DEFAULT_MOBILE_REDIRECT_URI;
222
+ }
223
+ if (authorizationRequestOpts.redirectUri.startsWith('http') && !authorizationRequestOpts.clientId) {
224
+ // At least set a default for a web based wallet.
225
+ // TODO: We really need (dynamic) client registration support
226
+ authorizationRequestOpts.clientId = authorizationRequestOpts.redirectUri;
227
+ }
228
+ let formats = this.vcFormatPreferences;
229
+ const authFormats = authorizationRequestOpts?.authorizationDetails
230
+ ?.map((detail) => (typeof detail === 'object' && 'format' in detail && detail.format ? detail.format : undefined))
231
+ .filter((format) => !!format)
232
+ .map((format) => format);
233
+ if (authFormats && authFormats.length > 0) {
234
+ formats = Array.from(new Set(authFormats));
235
+ }
236
+ let oid4vciClient;
237
+ let types = undefined;
238
+ let offer;
239
+ if (requestData.existingClientState) {
240
+ oid4vciClient = await OpenID4VCIClient.fromState({ state: requestData.existingClientState });
241
+ offer = oid4vciClient.credentialOffer;
242
+ }
243
+ else {
244
+ offer = requestData.credentialOffer;
245
+ if (uri.startsWith(RequestType.OPENID_INITIATE_ISSUANCE) ||
246
+ uri.startsWith(RequestType.OPENID_CREDENTIAL_OFFER) ||
247
+ uri.match(/https?:\/\/.*credential_offer(_uri)=?.*/)) {
262
248
  if (!offer) {
263
- // else no offer, meaning we have an issuer URL
264
- logger.log(`Issuer url received (no credential offer): ${uri}`);
265
- oid4vciClient = yield oid4vci_client_1.OpenID4VCIClient.fromCredentialIssuer({
266
- credentialIssuer: uri,
267
- authorizationRequest: authorizationRequestOpts,
268
- clientId: authorizationRequestOpts.clientId,
269
- createAuthorizationRequestURL: (_b = requestData.createAuthorizationRequestURL) !== null && _b !== void 0 ? _b : true,
270
- });
249
+ // Let's make sure to convert the URI to offer, as it matches the regexes. Normally this should already have happened at this point though
250
+ offer = await CredentialOfferClient.fromURI(uri);
271
251
  }
272
- else {
273
- logger.log(`Credential offer received: ${uri}`);
274
- oid4vciClient = yield oid4vci_client_1.OpenID4VCIClient.fromURI({
275
- uri,
276
- authorizationRequest: authorizationRequestOpts,
277
- clientId: authorizationRequestOpts.clientId,
278
- createAuthorizationRequestURL: (_c = requestData.createAuthorizationRequestURL) !== null && _c !== void 0 ? _c : true,
279
- });
252
+ }
253
+ else {
254
+ if (!!offer) {
255
+ logger.warning(`Non default URI used for credential offer: ${uri}`);
280
256
  }
281
257
  }
282
- if (offer) {
283
- types = (0, oid4vci_common_1.getTypesFromCredentialOffer)(offer.original_credential_offer);
258
+ if (!offer) {
259
+ // else no offer, meaning we have an issuer URL
260
+ logger.log(`Issuer url received (no credential offer): ${uri}`);
261
+ oid4vciClient = await OpenID4VCIClient.fromCredentialIssuer({
262
+ credentialIssuer: uri,
263
+ authorizationRequest: authorizationRequestOpts,
264
+ clientId: authorizationRequestOpts.clientId,
265
+ createAuthorizationRequestURL: requestData.createAuthorizationRequestURL ?? true,
266
+ });
284
267
  }
285
268
  else {
286
- types = (0, utils_1.asArray)(authorizationRequestOpts.authorizationDetails)
287
- .map((authReqOpts) => { var _a; return (_a = (0, oid4vci_common_1.getTypesFromAuthorizationDetails)(authReqOpts)) !== null && _a !== void 0 ? _a : []; })
288
- .filter((inner) => inner.length > 0);
289
- }
290
- const serverMetadata = yield oid4vciClient.retrieveServerMetadata();
291
- const credentialsSupported = yield (0, OID4VCIHolderService_1.getCredentialConfigsSupportedMerged)({
292
- client: oid4vciClient,
293
- vcFormatPreferences: formats,
294
- types,
295
- });
296
- const credentialBranding = yield (0, OID4VCIHolderService_1.getCredentialBranding)({ credentialsSupported, context });
297
- const authorizationCodeURL = oid4vciClient.authorizationURL;
298
- if (authorizationCodeURL) {
299
- logger.log(`authorization code URL ${authorizationCodeURL}`);
269
+ logger.log(`Credential offer received: ${uri}`);
270
+ oid4vciClient = await OpenID4VCIClient.fromURI({
271
+ uri,
272
+ authorizationRequest: authorizationRequestOpts,
273
+ clientId: authorizationRequestOpts.clientId,
274
+ createAuthorizationRequestURL: requestData.createAuthorizationRequestURL ?? true,
275
+ });
300
276
  }
301
- const oid4vciClientState = JSON.parse(yield oid4vciClient.exportState());
302
- return {
303
- authorizationCodeURL,
304
- credentialBranding,
305
- credentialsSupported,
306
- serverMetadata,
307
- oid4vciClientState,
308
- };
277
+ }
278
+ if (offer) {
279
+ types = getTypesFromCredentialOffer(offer.original_credential_offer);
280
+ }
281
+ else {
282
+ types = asArray(authorizationRequestOpts.authorizationDetails)
283
+ .map((authReqOpts) => getTypesFromAuthorizationDetails(authReqOpts) ?? [])
284
+ .filter((inner) => inner.length > 0);
285
+ }
286
+ const serverMetadata = await oid4vciClient.retrieveServerMetadata();
287
+ const credentialsSupported = await getCredentialConfigsSupportedMerged({
288
+ client: oid4vciClient,
289
+ vcFormatPreferences: formats,
290
+ types,
309
291
  });
292
+ const credentialBranding = await getCredentialBranding({ credentialsSupported, context });
293
+ const authorizationCodeURL = oid4vciClient.authorizationURL;
294
+ if (authorizationCodeURL) {
295
+ logger.log(`authorization code URL ${authorizationCodeURL}`);
296
+ }
297
+ const oid4vciClientState = JSON.parse(await oid4vciClient.exportState());
298
+ return {
299
+ authorizationCodeURL,
300
+ credentialBranding,
301
+ credentialsSupported,
302
+ serverMetadata,
303
+ oid4vciClientState,
304
+ };
310
305
  }
311
- oid4vciHolderCreateCredentialsToSelectFrom(args, context) {
312
- return __awaiter(this, void 0, void 0, function* () {
313
- const { credentialBranding, locale, selectedCredentials /*, openID4VCIClientState*/, credentialsSupported } = args;
314
- // const client = await OpenID4VCIClient.fromState({ state: openID4VCIClientState! }) // TODO see if we need the check openID4VCIClientState defined
315
- /*const credentialsSupported = await getCredentialConfigsSupportedBySingleTypeOrId({
316
- client,
317
- vcFormatPreferences: this.vcFormatPreferences,
318
- })*/
319
- logger.info(`Credentials supported ${Object.keys(credentialsSupported).join(', ')}`);
320
- const credentialSelection = yield Promise.all(Object.entries(credentialsSupported).map((_a) => __awaiter(this, [_a], void 0, function* ([id, credentialConfigSupported]) {
321
- // FIXME this allows for duplicate VerifiableCredential, which the user has no idea which ones those are and we also have a branding map with unique keys, so some branding will not match
322
- // const defaultCredentialType = 'VerifiableCredential'
323
- var _b, _c, _d;
324
- const credentialTypes = (0, oid4vci_common_1.getTypesFromObject)(credentialConfigSupported);
325
- // const credentialType = id /*?? credentialTypes?.find((type) => type !== defaultCredentialType) ?? defaultCredentialType*/
326
- const localeBranding = !credentialBranding
327
- ? undefined
328
- : ((_b = credentialBranding === null || credentialBranding === void 0 ? void 0 : credentialBranding[id]) !== null && _b !== void 0 ? _b : (_c = Object.entries(credentialBranding)
306
+ async oid4vciHolderCreateCredentialsToSelectFrom(args, context) {
307
+ const { credentialBranding, locale, selectedCredentials /*, openID4VCIClientState*/, credentialsSupported } = args;
308
+ // const client = await OpenID4VCIClient.fromState({ state: openID4VCIClientState! }) // TODO see if we need the check openID4VCIClientState defined
309
+ /*const credentialsSupported = await getCredentialConfigsSupportedBySingleTypeOrId({
310
+ client,
311
+ vcFormatPreferences: this.vcFormatPreferences,
312
+ })*/
313
+ logger.info(`Credentials supported ${Object.keys(credentialsSupported).join(', ')}`);
314
+ const credentialSelection = await Promise.all(Object.entries(credentialsSupported).map(async ([id, credentialConfigSupported]) => {
315
+ // FIXME this allows for duplicate VerifiableCredential, which the user has no idea which ones those are and we also have a branding map with unique keys, so some branding will not match
316
+ // const defaultCredentialType = 'VerifiableCredential'
317
+ const credentialTypes = getTypesFromObject(credentialConfigSupported);
318
+ // const credentialType = id /*?? credentialTypes?.find((type) => type !== defaultCredentialType) ?? defaultCredentialType*/
319
+ const localeBranding = !credentialBranding
320
+ ? undefined
321
+ : (credentialBranding?.[id] ??
322
+ Object.entries(credentialBranding)
329
323
  .find(([type, _brandings]) => {
330
324
  credentialTypes && type in credentialTypes;
331
- })) === null || _c === void 0 ? void 0 : _c.map(([type, supported]) => supported));
332
- const credentialAlias = (_d = (yield (0, OID4VCIHolderService_1.selectCredentialLocaleBranding)({
333
- locale,
334
- localeBranding,
335
- }))) === null || _d === void 0 ? void 0 : _d.alias;
336
- return {
337
- id: (0, uuid_1.v4)(),
338
- credentialId: id,
339
- credentialTypes: credentialTypes !== null && credentialTypes !== void 0 ? credentialTypes : (0, utils_1.asArray)(id),
340
- credentialAlias: credentialAlias !== null && credentialAlias !== void 0 ? credentialAlias : id,
341
- isSelected: false,
342
- };
343
- })));
344
- // TODO find better place to do this, would be nice if the machine does this?
345
- if (credentialSelection.length >= 1) {
346
- credentialSelection.map((sel) => selectedCredentials.push(sel.credentialId));
347
- }
348
- logger.log(`Credential selection ${JSON.stringify(credentialSelection)}`);
349
- return credentialSelection;
350
- });
325
+ })
326
+ ?.map(([type, supported]) => supported));
327
+ const credentialAlias = (await selectCredentialLocaleBranding({
328
+ locale,
329
+ localeBranding,
330
+ }))?.alias;
331
+ return {
332
+ id: uuidv4(),
333
+ credentialId: id,
334
+ credentialTypes: credentialTypes ?? asArray(id),
335
+ credentialAlias: credentialAlias ?? id,
336
+ isSelected: false,
337
+ };
338
+ }));
339
+ // TODO find better place to do this, would be nice if the machine does this?
340
+ if (credentialSelection.length >= 1) {
341
+ credentialSelection.map((sel) => selectedCredentials.push(sel.credentialId));
342
+ }
343
+ logger.log(`Credential selection ${JSON.stringify(credentialSelection)}`);
344
+ return credentialSelection;
351
345
  }
352
- oid4vciHolderGetContact(args, context) {
353
- return __awaiter(this, void 0, void 0, function* () {
354
- var _a, _b, _c;
355
- const { serverMetadata } = args;
356
- if (serverMetadata === undefined) {
357
- return Promise.reject(Error('Missing serverMetadata in context'));
358
- }
359
- const names = new Set((_c = (_b = (_a = serverMetadata.credentialIssuerMetadata) === null || _a === void 0 ? void 0 : _a.display) === null || _b === void 0 ? void 0 : _b.map((display) => display.name).filter((name) => name != undefined).map((name) => name)) !== null && _c !== void 0 ? _c : []);
360
- const name = names.size > 0 ? Array.from(names)[0] : undefined;
361
- const correlationId = new URL(serverMetadata.issuer).hostname;
362
- const filter = [
363
- {
364
- identities: {
365
- identifier: {
366
- correlationId,
367
- },
346
+ async oid4vciHolderGetContact(args, context) {
347
+ const { serverMetadata } = args;
348
+ if (serverMetadata === undefined) {
349
+ return Promise.reject(Error('Missing serverMetadata in context'));
350
+ }
351
+ const names = new Set(serverMetadata.credentialIssuerMetadata?.display
352
+ ?.map((display) => display.name)
353
+ .filter((name) => name != undefined)
354
+ .map((name) => name) ?? []);
355
+ const name = names.size > 0 ? Array.from(names)[0] : undefined;
356
+ const correlationId = new URL(serverMetadata.issuer).hostname;
357
+ const filter = [
358
+ {
359
+ identities: {
360
+ identifier: {
361
+ correlationId,
368
362
  },
369
363
  },
370
- ];
371
- if (name) {
372
- filter.push({
373
- contact: {
374
- legalName: name,
375
- },
376
- });
377
- filter.push({
378
- contact: {
379
- displayName: name,
380
- },
381
- });
382
- }
383
- const parties = yield context.agent.cmGetContacts({
384
- filter,
364
+ },
365
+ ];
366
+ if (name) {
367
+ filter.push({
368
+ contact: {
369
+ legalName: name,
370
+ },
385
371
  });
386
- if (parties.length > 1) {
387
- logger.warning(`Get contacts returned more than one result: ${parties.length}, ${parties.map((party) => party.contact.displayName).join(',')}`);
388
- }
389
- const party = parties.length >= 1 ? parties[0] : undefined;
390
- logger.log(`Party involved: `, party);
391
- return party;
372
+ filter.push({
373
+ contact: {
374
+ displayName: name,
375
+ },
376
+ });
377
+ }
378
+ const parties = await context.agent.cmGetContacts({
379
+ filter,
392
380
  });
381
+ if (parties.length > 1) {
382
+ logger.warning(`Get contacts returned more than one result: ${parties.length}, ${parties.map((party) => party.contact.displayName).join(',')}`);
383
+ }
384
+ const party = parties.length >= 1 ? parties[0] : undefined;
385
+ logger.log(`Party involved: `, party);
386
+ return party;
393
387
  }
394
- oid4vciHolderGetCredentials(args, context) {
395
- return __awaiter(this, void 0, void 0, function* () {
396
- const { verificationCode, openID4VCIClientState, didMethodPreferences = this.didMethodPreferences, issuanceOpt, accessTokenOpts } = args;
397
- logger.debug(`Getting credentials`, issuanceOpt, accessTokenOpts);
398
- if (!openID4VCIClientState) {
399
- return Promise.reject(Error('Missing openID4VCI client state in context'));
400
- }
401
- const client = yield oid4vci_client_1.OpenID4VCIClient.fromState({ state: openID4VCIClientState });
402
- const credentialsSupported = yield (0, OID4VCIHolderService_1.getCredentialConfigsSupportedMerged)({
403
- client,
404
- vcFormatPreferences: this.vcFormatPreferences,
405
- configurationIds: args.selectedCredentials,
406
- });
407
- const serverMetadata = yield client.retrieveServerMetadata();
408
- const issuanceOpts = yield (0, OID4VCIHolderService_1.getIssuanceOpts)(Object.assign({ client,
409
- credentialsSupported,
410
- serverMetadata,
411
- context, didMethodPreferences: Array.isArray(didMethodPreferences) && didMethodPreferences.length > 0 ? didMethodPreferences : this.didMethodPreferences, jwtCryptographicSuitePreferences: this.jwtCryptographicSuitePreferences, jsonldCryptographicSuitePreferences: this.jsonldCryptographicSuitePreferences }, (issuanceOpt && { forceIssuanceOpt: issuanceOpt })));
412
- const getCredentials = issuanceOpts.map((issuanceOpt) => __awaiter(this, void 0, void 0, function* () {
413
- return yield this.oid4vciHolderGetCredential({
414
- issuanceOpt,
415
- pin: verificationCode,
416
- client,
417
- accessTokenOpts,
418
- }, context);
419
- }));
420
- const allCredentials = yield Promise.all(getCredentials);
421
- logger.log(`Credentials received`, allCredentials);
422
- return allCredentials;
388
+ async oid4vciHolderGetCredentials(args, context) {
389
+ const { verificationCode, openID4VCIClientState, didMethodPreferences = this.didMethodPreferences, issuanceOpt, accessTokenOpts } = args;
390
+ logger.debug(`Getting credentials`, issuanceOpt, accessTokenOpts);
391
+ if (!openID4VCIClientState) {
392
+ return Promise.reject(Error('Missing openID4VCI client state in context'));
393
+ }
394
+ const client = await OpenID4VCIClient.fromState({ state: openID4VCIClientState });
395
+ const credentialsSupported = await getCredentialConfigsSupportedMerged({
396
+ client,
397
+ vcFormatPreferences: this.vcFormatPreferences,
398
+ configurationIds: args.selectedCredentials,
423
399
  });
400
+ const serverMetadata = await client.retrieveServerMetadata();
401
+ const issuanceOpts = await getIssuanceOpts({
402
+ client,
403
+ credentialsSupported,
404
+ serverMetadata,
405
+ context,
406
+ didMethodPreferences: Array.isArray(didMethodPreferences) && didMethodPreferences.length > 0 ? didMethodPreferences : this.didMethodPreferences,
407
+ jwtCryptographicSuitePreferences: this.jwtCryptographicSuitePreferences,
408
+ jsonldCryptographicSuitePreferences: this.jsonldCryptographicSuitePreferences,
409
+ ...(issuanceOpt && { forceIssuanceOpt: issuanceOpt }),
410
+ });
411
+ const getCredentials = issuanceOpts.map(async (issuanceOpt) => await this.oid4vciHolderGetCredential({
412
+ issuanceOpt,
413
+ pin: verificationCode,
414
+ client,
415
+ accessTokenOpts,
416
+ }, context));
417
+ const allCredentials = await Promise.all(getCredentials);
418
+ logger.log(`Credentials received`, allCredentials);
419
+ return allCredentials;
424
420
  }
425
- oid4vciHolderGetCredential(args, context) {
426
- return __awaiter(this, void 0, void 0, function* () {
427
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
428
- const { issuanceOpt, pin, client, accessTokenOpts } = args;
429
- logger.info(`Getting credential`, issuanceOpt);
430
- if (!issuanceOpt) {
431
- return Promise.reject(Error(`Cannot get credential issuance options`));
432
- }
433
- const identifier = yield (0, OID4VCIHolderService_1.getIdentifierOpts)({ issuanceOpt, context });
434
- issuanceOpt.identifier = identifier;
435
- logger.info(`ID opts`, identifier);
436
- const alg = yield (0, ssi_sdk_ext_key_utils_1.signatureAlgorithmFromKey)({ key: identifier.key });
437
- // The VCI lib either expects a jwk or a kid
438
- const jwk = (0, ssi_sdk_ext_identifier_resolution_1.isManagedIdentifierJwkResult)(identifier) ? identifier.jwk : undefined;
439
- const callbacks = {
440
- signCallback: signCallback(identifier, context),
441
- };
442
- try {
443
- // We need to make sure we have acquired the access token
444
- if (!client.clientId) {
445
- client.clientId = (0, ssi_sdk_ext_identifier_resolution_1.isManagedIdentifierDidResult)(identifier) ? identifier.did : identifier.issuer;
446
- }
447
- let asOpts = undefined;
448
- let kid = (_b = (_a = accessTokenOpts === null || accessTokenOpts === void 0 ? void 0 : accessTokenOpts.clientOpts) === null || _a === void 0 ? void 0 : _a.kid) !== null && _b !== void 0 ? _b : identifier.kid;
449
- if (accessTokenOpts === null || accessTokenOpts === void 0 ? void 0 : accessTokenOpts.clientOpts) {
450
- const clientId = (_d = (_c = accessTokenOpts.clientOpts.clientId) !== null && _c !== void 0 ? _c : client.clientId) !== null && _d !== void 0 ? _d : identifier.issuer;
451
- if (client.isEBSI() && (clientId === null || clientId === void 0 ? void 0 : clientId.startsWith('http')) && (kid === null || kid === void 0 ? void 0 : kid.includes('#'))) {
452
- kid = kid.split('#')[1];
453
- }
454
- //todo: investigate if the jwk should be used here as well if present
455
- const clientOpts = Object.assign(Object.assign({}, accessTokenOpts.clientOpts), { clientId,
456
- kid,
457
- // @ts-ignore
458
- alg: (_e = accessTokenOpts.clientOpts.alg) !== null && _e !== void 0 ? _e : alg, signCallbacks: (_f = accessTokenOpts.clientOpts.signCallbacks) !== null && _f !== void 0 ? _f : callbacks });
459
- asOpts = {
460
- clientOpts,
461
- };
462
- }
463
- yield client.acquireAccessToken(Object.assign({ clientId: client.clientId, pin, authorizationResponse: JSON.parse(yield client.exportState()).authorizationCodeResponse, additionalRequestParams: accessTokenOpts === null || accessTokenOpts === void 0 ? void 0 : accessTokenOpts.additionalRequestParams }, (asOpts && { asOpts })));
464
- // FIXME: This type mapping is wrong. It should use credential_identifier in case the access token response has authorization details
465
- const types = (0, oid4vci_common_1.getTypesFromObject)(issuanceOpt);
466
- const id = 'id' in issuanceOpt && issuanceOpt.id ? issuanceOpt.id : undefined;
467
- const credentialTypes = (0, utils_1.asArray)((_h = (_g = issuanceOpt.credentialConfigurationId) !== null && _g !== void 0 ? _g : types) !== null && _h !== void 0 ? _h : id);
468
- if (!credentialTypes || credentialTypes.length === 0) {
469
- return Promise.reject(Error('cannot determine credential id to request'));
421
+ async oid4vciHolderGetCredential(args, context) {
422
+ const { issuanceOpt, pin, client, accessTokenOpts } = args;
423
+ logger.info(`Getting credential`, issuanceOpt);
424
+ if (!issuanceOpt) {
425
+ return Promise.reject(Error(`Cannot get credential issuance options`));
426
+ }
427
+ const identifier = await getIdentifierOpts({ issuanceOpt, context });
428
+ issuanceOpt.identifier = identifier;
429
+ logger.info(`ID opts`, identifier);
430
+ const alg = await signatureAlgorithmFromKey({ key: identifier.key });
431
+ // The VCI lib either expects a jwk or a kid
432
+ const jwk = isManagedIdentifierJwkResult(identifier) ? identifier.jwk : undefined;
433
+ const callbacks = {
434
+ signCallback: signCallback(identifier, context),
435
+ };
436
+ try {
437
+ // We need to make sure we have acquired the access token
438
+ if (!client.clientId) {
439
+ client.clientId = isManagedIdentifierDidResult(identifier) ? identifier.did : identifier.issuer;
440
+ }
441
+ let asOpts = undefined;
442
+ let kid = accessTokenOpts?.clientOpts?.kid ?? identifier.kid;
443
+ if (accessTokenOpts?.clientOpts) {
444
+ const clientId = accessTokenOpts.clientOpts.clientId ?? client.clientId ?? identifier.issuer;
445
+ if (client.isEBSI() && clientId?.startsWith('http') && kid?.includes('#')) {
446
+ kid = kid.split('#')[1];
470
447
  }
471
- const credentialResponse = yield client.acquireCredentials(Object.assign(Object.assign({ credentialTypes, proofCallbacks: callbacks, format: issuanceOpt.format,
472
- // TODO: We need to update the machine and add notifications support for actual deferred credentials instead of just waiting/retrying
473
- deferredCredentialAwait: true }, (!jwk && { kid })), { // vci client either wants a jwk or kid. If we have used the jwk method do not provide the kid
474
- jwk,
475
- alg, jti: (0, uuid_1.v4)() }));
476
- const credential = {
477
- id: (_j = issuanceOpt.credentialConfigurationId) !== null && _j !== void 0 ? _j : id,
478
- types: types !== null && types !== void 0 ? types : (0, utils_1.asArray)(credentialTypes),
479
- issuanceOpt,
480
- credentialResponse,
448
+ //todo: investigate if the jwk should be used here as well if present
449
+ const clientOpts = {
450
+ ...accessTokenOpts.clientOpts,
451
+ clientId,
452
+ kid,
453
+ // @ts-ignore
454
+ alg: accessTokenOpts.clientOpts.alg ?? alg,
455
+ signCallbacks: accessTokenOpts.clientOpts.signCallbacks ?? callbacks,
456
+ };
457
+ asOpts = {
458
+ clientOpts,
481
459
  };
482
- return (0, OID4VCIHolderService_1.mapCredentialToAccept)({ credentialToAccept: credential, hasher: this.hasher });
483
- }
484
- catch (error) {
485
- return Promise.reject(error);
486
460
  }
487
- });
461
+ await client.acquireAccessToken({
462
+ clientId: client.clientId,
463
+ pin,
464
+ authorizationResponse: JSON.parse(await client.exportState()).authorizationCodeResponse,
465
+ additionalRequestParams: accessTokenOpts?.additionalRequestParams,
466
+ ...(asOpts && { asOpts }),
467
+ });
468
+ // FIXME: This type mapping is wrong. It should use credential_identifier in case the access token response has authorization details
469
+ const types = getTypesFromObject(issuanceOpt);
470
+ const id = 'id' in issuanceOpt && issuanceOpt.id ? issuanceOpt.id : undefined;
471
+ const credentialTypes = asArray(issuanceOpt.credentialConfigurationId ?? types ?? id);
472
+ if (!credentialTypes || credentialTypes.length === 0) {
473
+ return Promise.reject(Error('cannot determine credential id to request'));
474
+ }
475
+ const credentialDefinition = this.getCredentialDefinition(issuanceOpt);
476
+ const credentialResponse = await client.acquireCredentials({
477
+ ...(credentialDefinition && { context: credentialDefinition['@context'] }),
478
+ credentialTypes,
479
+ proofCallbacks: callbacks,
480
+ format: issuanceOpt.format,
481
+ // TODO: We need to update the machine and add notifications support for actual deferred credentials instead of just waiting/retrying
482
+ deferredCredentialAwait: true,
483
+ ...(!jwk && { kid }), // vci client either wants a jwk or kid. If we have used the jwk method do not provide the kid
484
+ jwk,
485
+ alg,
486
+ jti: uuidv4(),
487
+ });
488
+ const credential = {
489
+ id: issuanceOpt.credentialConfigurationId ?? id,
490
+ types: types ?? asArray(credentialTypes),
491
+ issuanceOpt,
492
+ credentialResponse,
493
+ };
494
+ return mapCredentialToAccept({ credentialToAccept: credential, hasher: this.hasher });
495
+ }
496
+ catch (error) {
497
+ return Promise.reject(error);
498
+ }
488
499
  }
489
- oid4vciHolderAddContactIdentity(args, context) {
490
- return __awaiter(this, void 0, void 0, function* () {
491
- const { credentialsToAccept, contact } = args;
492
- if (!contact) {
493
- return Promise.reject(Error('Missing contact in context'));
494
- }
495
- if (credentialsToAccept === undefined || credentialsToAccept.length === 0) {
496
- return Promise.reject(Error('Missing credential offers in context'));
497
- }
498
- let correlationId = credentialsToAccept[0].correlationId;
499
- let identifierType = ssi_sdk_data_store_1.CorrelationIdentifierType.DID;
500
- if (!correlationId.toLowerCase().startsWith('did:')) {
501
- identifierType = ssi_sdk_data_store_1.CorrelationIdentifierType.URL;
502
- if (correlationId.startsWith('http')) {
503
- correlationId = new URL(correlationId).hostname;
504
- }
500
+ async oid4vciHolderAddContactIdentity(args, context) {
501
+ const { credentialsToAccept, contact } = args;
502
+ if (!contact) {
503
+ return Promise.reject(Error('Missing contact in context'));
504
+ }
505
+ if (credentialsToAccept === undefined || credentialsToAccept.length === 0) {
506
+ return Promise.reject(Error('Missing credential offers in context'));
507
+ }
508
+ let correlationId = credentialsToAccept[0].correlationId;
509
+ let identifierType = CorrelationIdentifierType.DID;
510
+ if (!correlationId.toLowerCase().startsWith('did:')) {
511
+ identifierType = CorrelationIdentifierType.URL;
512
+ if (correlationId.startsWith('http')) {
513
+ correlationId = new URL(correlationId).hostname;
505
514
  }
506
- const identity = Object.assign({ alias: credentialsToAccept[0].correlationId, origin: ssi_sdk_data_store_1.IdentityOrigin.EXTERNAL, roles: [ssi_sdk_data_store_1.CredentialRole.ISSUER], identifier: {
507
- type: identifierType,
508
- correlationId,
509
- } }, (identifierType === ssi_sdk_data_store_1.CorrelationIdentifierType.URL && {
515
+ }
516
+ const identity = {
517
+ alias: credentialsToAccept[0].correlationId,
518
+ origin: IdentityOrigin.EXTERNAL,
519
+ roles: [CredentialRole.ISSUER],
520
+ identifier: {
521
+ type: identifierType,
522
+ correlationId,
523
+ },
524
+ ...(identifierType === CorrelationIdentifierType.URL && {
510
525
  connection: {
511
- type: ssi_sdk_data_store_1.ConnectionType.OPENID_CONNECT,
526
+ type: ConnectionType.OPENID_CONNECT,
512
527
  config: {
513
528
  clientId: '138d7bf8-c930-4c6e-b928-97d3a4928b01',
514
529
  clientSecret: '03b3955f-d020-4f2a-8a27-4e452d4e27a0',
@@ -519,352 +534,349 @@ class OID4VCIHolder {
519
534
  clientAuthMethod: 'post',
520
535
  },
521
536
  },
522
- }));
523
- yield context.agent.emit(IOID4VCIHolder_1.OID4VCIHolderEvent.CONTACT_IDENTITY_CREATED, {
524
- contactId: contact.id,
525
- identity,
526
- });
527
- logger.log(`Contact added: ${correlationId}`);
528
- return context.agent.cmAddIdentity({ contactId: contact.id, identity });
529
- });
530
- }
531
- oid4vciHolderGetIssuerBranding(args, context) {
532
- return __awaiter(this, void 0, void 0, function* () {
533
- var _a, _b;
534
- const { serverMetadata, contact } = args;
535
- // Here we are fetching issuer branding for a contact. If no contact is found that means we encounter this contact for the first time. This also means we do not have any branding for the contact.
536
- const issuerCorrelationId = contact === null || contact === void 0 ? void 0 : contact.identities.filter((identity) => identity.roles.includes(ssi_sdk_data_store_1.CredentialRole.ISSUER)).map((identity) => identity.identifier.correlationId)[0];
537
- if (issuerCorrelationId) {
538
- const branding = yield context.agent.ibGetIssuerBranding({ filter: [{ issuerCorrelationId }] });
539
- if (branding.length > 0) {
540
- return branding[0].localeBranding;
541
- }
542
- }
543
- // We should have serverMetadata in the context else something went wrong
544
- if (!serverMetadata) {
545
- return Promise.reject(Error('Missing serverMetadata in context'));
546
- }
547
- return (0, OID4VCIHolderService_1.getBasicIssuerLocaleBranding)({
548
- display: (_b = (_a = serverMetadata.credentialIssuerMetadata) === null || _a === void 0 ? void 0 : _a.display) !== null && _b !== void 0 ? _b : [],
549
- dynamicRegistrationClientMetadata: serverMetadata.credentialIssuerMetadata,
550
- context,
551
- });
537
+ }),
538
+ };
539
+ await context.agent.emit(OID4VCIHolderEvent.CONTACT_IDENTITY_CREATED, {
540
+ contactId: contact.id,
541
+ identity,
552
542
  });
543
+ logger.log(`Contact added: ${correlationId}`);
544
+ return context.agent.cmAddIdentity({ contactId: contact.id, identity });
553
545
  }
554
- oid4vciHolderStoreIssuerBranding(args, context) {
555
- return __awaiter(this, void 0, void 0, function* () {
556
- const { issuerBranding, contact } = args;
557
- if (!issuerBranding || issuerBranding.length === 0 || issuerBranding[0].id) {
558
- // FIXME we need better separation between a contact(issuer) we encountered before and it's branding vs a new contact and it's branding
559
- return;
560
- }
561
- if (!contact) {
562
- return Promise.reject(Error('Missing contact in context'));
563
- }
564
- const issuerCorrelationId = contact === null || contact === void 0 ? void 0 : contact.identities.filter((identity) => identity.roles.includes(ssi_sdk_data_store_1.CredentialRole.ISSUER)).map((identity) => identity.identifier.correlationId)[0];
565
- // we check for issuer branding as adding an identity might also trigger storing the issuer branding
566
- const branding = yield context.agent.ibGetIssuerBranding({ filter: [{ issuerCorrelationId }] });
546
+ async oid4vciHolderGetIssuerBranding(args, context) {
547
+ const { serverMetadata, contact } = args;
548
+ // Here we are fetching issuer branding for a contact. If no contact is found that means we encounter this contact for the first time. This also means we do not have any branding for the contact.
549
+ const issuerCorrelationId = contact?.identities
550
+ .filter((identity) => identity.roles.includes(CredentialRole.ISSUER))
551
+ .map((identity) => identity.identifier.correlationId)[0];
552
+ if (issuerCorrelationId) {
553
+ const branding = await context.agent.ibGetIssuerBranding({ filter: [{ issuerCorrelationId }] });
567
554
  if (branding.length > 0) {
568
- return;
555
+ return branding[0].localeBranding;
569
556
  }
570
- yield context.agent.ibAddIssuerBranding({
571
- localeBranding: issuerBranding,
572
- issuerCorrelationId,
573
- });
557
+ }
558
+ // We should have serverMetadata in the context else something went wrong
559
+ if (!serverMetadata) {
560
+ return Promise.reject(Error('Missing serverMetadata in context'));
561
+ }
562
+ return getBasicIssuerLocaleBranding({
563
+ display: serverMetadata.credentialIssuerMetadata?.display ?? [],
564
+ dynamicRegistrationClientMetadata: serverMetadata.credentialIssuerMetadata,
565
+ context,
574
566
  });
575
567
  }
576
- oid4vciHolderAssertValidCredentials(args, context) {
577
- return __awaiter(this, void 0, void 0, function* () {
578
- const { credentialsToAccept, issuanceOpt } = args;
579
- return yield Promise.all(credentialsToAccept.map((credentialToAccept) => (0, OID4VCIHolderService_1.verifyCredentialToAccept)({
580
- mappedCredential: credentialToAccept,
581
- onVerifyEBSICredentialIssuer: this.onVerifyEBSICredentialIssuer,
582
- hasher: this.hasher,
583
- schemaValidation: issuanceOpt === null || issuanceOpt === void 0 ? void 0 : issuanceOpt.schemaValidation,
584
- context,
585
- })));
568
+ async oid4vciHolderStoreIssuerBranding(args, context) {
569
+ const { issuerBranding, contact } = args;
570
+ if (!issuerBranding || issuerBranding.length === 0 || issuerBranding[0].id) {
571
+ // FIXME we need better separation between a contact(issuer) we encountered before and it's branding vs a new contact and it's branding
572
+ return;
573
+ }
574
+ if (!contact) {
575
+ return Promise.reject(Error('Missing contact in context'));
576
+ }
577
+ const issuerCorrelationId = contact?.identities
578
+ .filter((identity) => identity.roles.includes(CredentialRole.ISSUER))
579
+ .map((identity) => identity.identifier.correlationId)[0];
580
+ // we check for issuer branding as adding an identity might also trigger storing the issuer branding
581
+ const branding = await context.agent.ibGetIssuerBranding({ filter: [{ issuerCorrelationId }] });
582
+ if (branding.length > 0) {
583
+ return;
584
+ }
585
+ await context.agent.ibAddIssuerBranding({
586
+ localeBranding: issuerBranding,
587
+ issuerCorrelationId,
586
588
  });
587
589
  }
588
- oid4vciHolderStoreCredentialBranding(args, context) {
589
- return __awaiter(this, void 0, void 0, function* () {
590
- const { credentialBranding, serverMetadata, selectedCredentials, credentialsToAccept } = args;
591
- if (serverMetadata === undefined) {
592
- return Promise.reject(Error('Missing serverMetadata in context'));
590
+ async oid4vciHolderAssertValidCredentials(args, context) {
591
+ const { credentialsToAccept, issuanceOpt } = args;
592
+ return await Promise.all(credentialsToAccept.map((credentialToAccept) => verifyCredentialToAccept({
593
+ mappedCredential: credentialToAccept,
594
+ onVerifyEBSICredentialIssuer: this.onVerifyEBSICredentialIssuer,
595
+ hasher: this.hasher,
596
+ schemaValidation: issuanceOpt?.schemaValidation,
597
+ context,
598
+ })));
599
+ }
600
+ async oid4vciHolderStoreCredentialBranding(args, context) {
601
+ const { credentialBranding, serverMetadata, selectedCredentials, credentialsToAccept } = args;
602
+ if (serverMetadata === undefined) {
603
+ return Promise.reject(Error('Missing serverMetadata in context'));
604
+ }
605
+ else if (selectedCredentials.length === 0) {
606
+ logger.warning(`No credentials selected for issuer: ${serverMetadata.issuer}`);
607
+ return;
608
+ }
609
+ let counter = 0;
610
+ for (const credentialId of selectedCredentials) {
611
+ const localeBranding = credentialBranding?.[credentialId];
612
+ if (localeBranding && localeBranding.length > 0) {
613
+ const credential = credentialsToAccept.find((credAccept) => credAccept.credentialToAccept.id === credentialId || JSON.stringify(credAccept.types) === credentialId || credentialsToAccept[counter]);
614
+ counter++;
615
+ await context.agent.ibAddCredentialBranding({
616
+ vcHash: computeEntryHash(credential.rawVerifiableCredential),
617
+ issuerCorrelationId: new URL(serverMetadata.issuer).hostname,
618
+ localeBranding,
619
+ });
620
+ logger.log(`Credential branding for issuer ${serverMetadata.issuer} and type ${credentialId} stored with locales ${localeBranding.map((b) => b.locale).join(',')}`);
621
+ }
622
+ else {
623
+ logger.warning(`No credential branding found for issuer: ${serverMetadata.issuer} and type ${credentialId}`);
593
624
  }
594
- else if (selectedCredentials.length === 0) {
595
- logger.warning(`No credentials selected for issuer: ${serverMetadata.issuer}`);
596
- return;
625
+ }
626
+ }
627
+ async oid4vciHolderStoreCredentials(args, context) {
628
+ function trimmed(input) {
629
+ const trim = input?.trim();
630
+ if (trim === '') {
631
+ return undefined;
597
632
  }
598
- let counter = 0;
599
- for (const credentialId of selectedCredentials) {
600
- const localeBranding = credentialBranding === null || credentialBranding === void 0 ? void 0 : credentialBranding[credentialId];
601
- if (localeBranding && localeBranding.length > 0) {
602
- const credential = credentialsToAccept.find((credAccept) => credAccept.credentialToAccept.id === credentialId || JSON.stringify(credAccept.types) === credentialId || credentialsToAccept[counter]);
603
- counter++;
604
- yield context.agent.ibAddCredentialBranding({
605
- vcHash: (0, utils_1.computeEntryHash)(credential.rawVerifiableCredential),
606
- issuerCorrelationId: new URL(serverMetadata.issuer).hostname,
607
- localeBranding,
608
- });
609
- logger.log(`Credential branding for issuer ${serverMetadata.issuer} and type ${credentialId} stored with locales ${localeBranding.map((b) => b.locale).join(',')}`);
633
+ return trim;
634
+ }
635
+ const { credentialsToAccept, openID4VCIClientState, credentialsSupported, serverMetadata, selectedCredentials } = args;
636
+ const mappedCredentialToAccept = credentialsToAccept[0];
637
+ if (selectedCredentials && selectedCredentials.length > 1) {
638
+ logger.error(`More than 1 credential selected ${selectedCredentials.join(', ')}, but current service only stores 1 credential!`);
639
+ }
640
+ // TODO determine when and how we should store credentials without key kmsKeyRef & id method), this should be tested with the code below
641
+ const issuanceOpt = args.issuanceOpt ?? mappedCredentialToAccept.credentialToAccept.issuanceOpt;
642
+ if (!issuanceOpt || !issuanceOpt.identifier) {
643
+ return Promise.reject(Error('issuanceOpt.identifier must me set in order to store a credential'));
644
+ }
645
+ const { kmsKeyRef, method } = issuanceOpt.identifier;
646
+ let persist = true;
647
+ const verifiableCredential = mappedCredentialToAccept.uniformVerifiableCredential;
648
+ const notificationId = mappedCredentialToAccept.credentialToAccept.credentialResponse.notification_id;
649
+ const subjectIssuance = mappedCredentialToAccept.credential_subject_issuance;
650
+ const notificationEndpoint = serverMetadata?.credentialIssuerMetadata?.notification_endpoint;
651
+ let holderCredential = undefined;
652
+ if (!notificationEndpoint) {
653
+ logger.log(`Notifications not supported by issuer ${serverMetadata?.issuer}. Will not provide a notification`);
654
+ }
655
+ else if (notificationEndpoint && !notificationId) {
656
+ logger.warning(`Notification endpoint available in issuer metadata with value ${notificationEndpoint}, but no ${notificationId} provided. Will not send a notification to issuer ${serverMetadata?.issuer}`);
657
+ }
658
+ else if (notificationEndpoint && notificationId) {
659
+ logger.log(`Notification id ${notificationId} found, will send back a notification to ${notificationEndpoint}`);
660
+ let event = 'credential_accepted';
661
+ if (Array.isArray(subjectIssuance?.notification_events_supported)) {
662
+ // experimental subject issuance, where a new credential is being created
663
+ event = subjectIssuance.notification_events_supported.includes('credential_accepted_holder_signed')
664
+ ? 'credential_accepted_holder_signed'
665
+ : 'credential_deleted_holder_signed';
666
+ logger.log(`Subject issuance/signing will be used, with event`, event);
667
+ const issuerVC = mappedCredentialToAccept.credentialToAccept.credentialResponse.credential;
668
+ const wrappedIssuerVC = CredentialMapper.toWrappedVerifiableCredential(issuerVC, { hasher: this.hasher ?? defaultHasher });
669
+ console.log(`Wrapped VC: ${wrappedIssuerVC.type}, ${wrappedIssuerVC.format}`);
670
+ // We will use the subject of the VCI Issuer (the holder, as the issuer of the new credential, so the below is not a mistake!)
671
+ let issuer;
672
+ if (CredentialMapper.isWrappedSdJwtVerifiableCredential(wrappedIssuerVC)) {
673
+ issuer = trimmed(wrappedIssuerVC.decoded?.sub);
610
674
  }
611
- else {
612
- logger.warning(`No credential branding found for issuer: ${serverMetadata.issuer} and type ${credentialId}`);
675
+ else if (CredentialMapper.isWrappedW3CVerifiableCredential(wrappedIssuerVC)) {
676
+ issuer = trimmed(wrappedIssuerVC.credential?.sub) ?? trimmed(this.idFromW3cCredentialSubject(wrappedIssuerVC));
613
677
  }
614
- }
615
- });
616
- }
617
- oid4vciHolderStoreCredentials(args, context) {
618
- return __awaiter(this, void 0, void 0, function* () {
619
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
620
- function trimmed(input) {
621
- const trim = input === null || input === void 0 ? void 0 : input.trim();
622
- if (trim === '') {
623
- return undefined;
678
+ else if (CredentialMapper.isWrappedMdocCredential(wrappedIssuerVC)) {
679
+ return Promise.reject(Error('mdoc not yet supported'));
624
680
  }
625
- return trim;
626
- }
627
- const { credentialsToAccept, openID4VCIClientState, credentialsSupported, serverMetadata, selectedCredentials } = args;
628
- const mappedCredentialToAccept = credentialsToAccept[0];
629
- if (selectedCredentials && selectedCredentials.length > 1) {
630
- logger.error(`More than 1 credential selected ${selectedCredentials.join(', ')}, but current service only stores 1 credential!`);
631
- }
632
- // TODO determine when and how we should store credentials without key kmsKeyRef & id method), this should be tested with the code below
633
- const issuanceOpt = (_a = args.issuanceOpt) !== null && _a !== void 0 ? _a : mappedCredentialToAccept.credentialToAccept.issuanceOpt;
634
- if (!issuanceOpt || !issuanceOpt.identifier) {
635
- return Promise.reject(Error('issuanceOpt.identifier must me set in order to store a credential'));
636
- }
637
- const { kmsKeyRef, method } = issuanceOpt.identifier;
638
- let persist = true;
639
- const verifiableCredential = mappedCredentialToAccept.uniformVerifiableCredential;
640
- const notificationId = mappedCredentialToAccept.credentialToAccept.credentialResponse.notification_id;
641
- const subjectIssuance = mappedCredentialToAccept.credential_subject_issuance;
642
- const notificationEndpoint = (_b = serverMetadata === null || serverMetadata === void 0 ? void 0 : serverMetadata.credentialIssuerMetadata) === null || _b === void 0 ? void 0 : _b.notification_endpoint;
643
- let holderCredential = undefined;
644
- if (!notificationEndpoint) {
645
- logger.log(`Notifications not supported by issuer ${serverMetadata === null || serverMetadata === void 0 ? void 0 : serverMetadata.issuer}. Will not provide a notification`);
646
- }
647
- else if (notificationEndpoint && !notificationId) {
648
- logger.warning(`Notification endpoint available in issuer metadata with value ${notificationEndpoint}, but no ${notificationId} provided. Will not send a notification to issuer ${serverMetadata === null || serverMetadata === void 0 ? void 0 : serverMetadata.issuer}`);
649
- }
650
- else if (notificationEndpoint && notificationId) {
651
- logger.log(`Notification id ${notificationId} found, will send back a notification to ${notificationEndpoint}`);
652
- let event = 'credential_accepted';
653
- if (Array.isArray(subjectIssuance === null || subjectIssuance === void 0 ? void 0 : subjectIssuance.notification_events_supported)) {
654
- // experimental subject issuance, where a new credential is being created
655
- event = subjectIssuance.notification_events_supported.includes('credential_accepted_holder_signed')
656
- ? 'credential_accepted_holder_signed'
657
- : 'credential_deleted_holder_signed';
658
- logger.log(`Subject issuance/signing will be used, with event`, event);
659
- const issuerVC = mappedCredentialToAccept.credentialToAccept.credentialResponse.credential;
660
- const wrappedIssuerVC = ssi_types_1.CredentialMapper.toWrappedVerifiableCredential(issuerVC, { hasher: this.hasher });
661
- console.log(`Wrapped VC: ${wrappedIssuerVC.type}, ${wrappedIssuerVC.format}`);
662
- // We will use the subject of the VCI Issuer (the holder, as the issuer of the new credential, so the below is not a mistake!)
663
- let issuer;
664
- if (ssi_types_1.CredentialMapper.isWrappedSdJwtVerifiableCredential(wrappedIssuerVC)) {
665
- issuer = trimmed((_c = wrappedIssuerVC.decoded) === null || _c === void 0 ? void 0 : _c.sub);
666
- }
667
- else if (ssi_types_1.CredentialMapper.isWrappedW3CVerifiableCredential(wrappedIssuerVC)) {
668
- issuer = (_e = trimmed((_d = wrappedIssuerVC.credential) === null || _d === void 0 ? void 0 : _d.sub)) !== null && _e !== void 0 ? _e : trimmed(this.idFromW3cCredentialSubject(wrappedIssuerVC));
669
- }
670
- else if (ssi_types_1.CredentialMapper.isWrappedMdocCredential(wrappedIssuerVC)) {
671
- return Promise.reject(Error('mdoc not yet supported'));
672
- }
673
- if (!issuer) {
674
- issuer = trimmed((_f = verifiableCredential.credentialSubject) === null || _f === void 0 ? void 0 : _f.id);
675
- }
676
- if (!issuer && ((_g = openID4VCIClientState === null || openID4VCIClientState === void 0 ? void 0 : openID4VCIClientState.kid) === null || _g === void 0 ? void 0 : _g.startsWith('did:'))) {
677
- issuer = (0, ssi_types_1.parseDid)(openID4VCIClientState === null || openID4VCIClientState === void 0 ? void 0 : openID4VCIClientState.kid).did;
678
- }
679
- if (!issuer && ((_j = (_h = openID4VCIClientState === null || openID4VCIClientState === void 0 ? void 0 : openID4VCIClientState.jwk) === null || _h === void 0 ? void 0 : _h.kid) === null || _j === void 0 ? void 0 : _j.startsWith('did:'))) {
680
- issuer = (0, ssi_types_1.parseDid)(openID4VCIClientState.jwk.kid).did;
681
- }
682
- if (!issuer && (openID4VCIClientState === null || openID4VCIClientState === void 0 ? void 0 : openID4VCIClientState.clientId)) {
683
- issuer = trimmed(openID4VCIClientState.clientId);
684
- }
685
- if (!issuer && (openID4VCIClientState === null || openID4VCIClientState === void 0 ? void 0 : openID4VCIClientState.accessTokenResponse)) {
686
- const decodedJwt = (0, did_jwt_1.decodeJWT)(openID4VCIClientState.accessTokenResponse.access_token);
687
- issuer = decodedJwt.payload.sub;
688
- }
689
- if (!issuer && mappedCredentialToAccept.credentialToAccept.issuanceOpt.identifier) {
690
- const resolution = yield context.agent.identifierManagedGet(mappedCredentialToAccept.credentialToAccept.issuanceOpt.identifier);
691
- issuer = resolution.issuer;
692
- }
693
- if (!issuer) {
694
- throw Error(`We could not determine the issuer, which means we cannot sign the credential`);
695
- }
696
- logger.log(`Issuer for self-issued credential will be: ${issuer}`);
697
- const holderCredentialToSign = wrappedIssuerVC.decoded;
698
- let proofFormat = 'lds';
699
- if (wrappedIssuerVC.format.includes('jwt') && !wrappedIssuerVC.format.includes('mso_mdoc')) {
700
- holderCredentialToSign.iss = issuer;
701
- proofFormat = 'jwt';
702
- }
703
- if ('issuer' in holderCredentialToSign && !('iss' in holderCredentialToSign)) {
704
- holderCredentialToSign.issuer = issuer;
705
- }
706
- if ('sub' in holderCredentialToSign) {
707
- holderCredentialToSign.sub = issuer;
708
- }
709
- if ('credentialSubject' in holderCredentialToSign && !Array.isArray(holderCredentialToSign.credentialSubject)) {
710
- holderCredentialToSign.credentialSubject.id = issuer;
711
- }
712
- if ('vc' in holderCredentialToSign) {
713
- if (holderCredentialToSign.vc.credentialSubject) {
714
- holderCredentialToSign.vc.credentialSubject.id = issuer;
715
- }
716
- holderCredentialToSign.vc.issuer = issuer;
717
- delete holderCredentialToSign.vc.proof;
718
- delete holderCredentialToSign.vc.issuanceDate;
719
- }
720
- delete holderCredentialToSign.proof;
721
- delete holderCredentialToSign.issuanceDate;
722
- delete holderCredentialToSign.iat;
723
- logger.log(`Subject issuance/signing will sign credential of type ${proofFormat}:`, holderCredentialToSign);
724
- const issuedVC = yield context.agent.createVerifiableCredential({
725
- credential: holderCredentialToSign,
726
- fetchRemoteContexts: true,
727
- save: false,
728
- proofFormat,
729
- });
730
- if (!issuedVC) {
731
- throw Error(`Could not issue holder credential from the wallet`);
681
+ if (!issuer) {
682
+ issuer = trimmed(verifiableCredential.credentialSubject?.id);
683
+ }
684
+ if (!issuer && openID4VCIClientState?.kid?.startsWith('did:')) {
685
+ issuer = parseDid(openID4VCIClientState?.kid).did;
686
+ }
687
+ if (!issuer && openID4VCIClientState?.jwk?.kid?.startsWith('did:')) {
688
+ issuer = parseDid(openID4VCIClientState.jwk.kid).did;
689
+ }
690
+ if (!issuer && openID4VCIClientState?.clientId) {
691
+ issuer = trimmed(openID4VCIClientState.clientId);
692
+ }
693
+ if (!issuer && openID4VCIClientState?.accessTokenResponse) {
694
+ const decodedJwt = decodeJWT(openID4VCIClientState.accessTokenResponse.access_token);
695
+ issuer = decodedJwt.payload.sub;
696
+ }
697
+ if (!issuer && mappedCredentialToAccept.credentialToAccept.issuanceOpt.identifier) {
698
+ const resolution = await context.agent.identifierManagedGet(mappedCredentialToAccept.credentialToAccept.issuanceOpt.identifier);
699
+ issuer = resolution.issuer;
700
+ }
701
+ if (!issuer) {
702
+ throw Error(`We could not determine the issuer, which means we cannot sign the credential`);
703
+ }
704
+ logger.log(`Issuer for self-issued credential will be: ${issuer}`);
705
+ const holderCredentialToSign = wrappedIssuerVC.decoded;
706
+ let proofFormat = 'lds';
707
+ if (wrappedIssuerVC.format.includes('jwt') && !wrappedIssuerVC.format.includes('mso_mdoc')) {
708
+ holderCredentialToSign.iss = issuer;
709
+ proofFormat = 'jwt';
710
+ }
711
+ if ('issuer' in holderCredentialToSign && !('iss' in holderCredentialToSign)) {
712
+ holderCredentialToSign.issuer = issuer;
713
+ }
714
+ if ('sub' in holderCredentialToSign) {
715
+ holderCredentialToSign.sub = issuer;
716
+ }
717
+ if ('credentialSubject' in holderCredentialToSign && !Array.isArray(holderCredentialToSign.credentialSubject)) {
718
+ holderCredentialToSign.credentialSubject.id = issuer;
719
+ }
720
+ if ('vc' in holderCredentialToSign) {
721
+ if (holderCredentialToSign.vc.credentialSubject) {
722
+ holderCredentialToSign.vc.credentialSubject.id = issuer;
732
723
  }
733
- logger.log(`Holder ${issuedVC.issuer} issued new credential with id ${issuedVC.id}`, issuedVC);
734
- holderCredential = ssi_types_1.CredentialMapper.storedCredentialToOriginalFormat(issuedVC);
735
- persist = event === 'credential_accepted_holder_signed';
724
+ holderCredentialToSign.vc.issuer = issuer;
725
+ delete holderCredentialToSign.vc.proof;
726
+ delete holderCredentialToSign.vc.issuanceDate;
736
727
  }
737
- const notificationRequest = Object.assign(Object.assign({ notification_id: notificationId }, (holderCredential && { credential: holderCredential })), { event });
738
- yield this.oid4vciHolderSendNotification({
739
- openID4VCIClientState,
740
- stored: persist,
741
- credentialsToAccept,
742
- credentialsSupported,
743
- notificationRequest,
744
- serverMetadata,
745
- }, context);
746
- }
747
- const persistCredential = holderCredential
748
- ? ssi_types_1.CredentialMapper.storedCredentialToOriginalFormat(holderCredential)
749
- : mappedCredentialToAccept.rawVerifiableCredential;
750
- if (!persist && holderCredential) {
751
- logger.log(`Will not persist credential, since we are signing as a holder and the issuer asked not to persist`);
752
- }
753
- else {
754
- logger.log(`Persisting credential`, persistCredential);
755
- const issuer = ssi_types_1.CredentialMapper.issuerCorrelationIdFromIssuerType(verifiableCredential.issuer);
756
- const [subjectCorrelationType, subjectCorrelationId] = this.determineSubjectCorrelation(issuanceOpt.identifier, issuer);
757
- const persistedCredential = yield context.agent.crsAddCredential({
758
- credential: {
759
- rawDocument: (0, ssi_sdk_data_store_1.ensureRawDocument)(persistCredential),
760
- kmsKeyRef: kmsKeyRef,
761
- identifierMethod: method,
762
- credentialRole: ssi_sdk_data_store_1.CredentialRole.HOLDER,
763
- issuerCorrelationType: (issuer === null || issuer === void 0 ? void 0 : issuer.startsWith('did:')) ? ssi_sdk_data_store_1.CredentialCorrelationType.DID : ssi_sdk_data_store_1.CredentialCorrelationType.URL,
764
- issuerCorrelationId: issuer,
765
- subjectCorrelationType,
766
- subjectCorrelationId,
767
- },
768
- });
769
- yield context.agent.emit(IOID4VCIHolder_1.OID4VCIHolderEvent.CREDENTIAL_STORED, {
770
- credential: persistedCredential,
771
- vcHash: persistedCredential.hash,
728
+ delete holderCredentialToSign.proof;
729
+ delete holderCredentialToSign.issuanceDate;
730
+ delete holderCredentialToSign.iat;
731
+ logger.log(`Subject issuance/signing will sign credential of type ${proofFormat}:`, holderCredentialToSign);
732
+ const issuedVC = await context.agent.createVerifiableCredential({
733
+ credential: holderCredentialToSign,
734
+ fetchRemoteContexts: true,
735
+ save: false,
736
+ proofFormat,
772
737
  });
773
- }
774
- });
738
+ if (!issuedVC) {
739
+ throw Error(`Could not issue holder credential from the wallet`);
740
+ }
741
+ logger.log(`Holder ${issuedVC.issuer} issued new credential with id ${issuedVC.id}`, issuedVC);
742
+ holderCredential = CredentialMapper.storedCredentialToOriginalFormat(issuedVC);
743
+ persist = event === 'credential_accepted_holder_signed';
744
+ }
745
+ const notificationRequest = {
746
+ notification_id: notificationId,
747
+ ...(holderCredential && { credential: holderCredential }),
748
+ event,
749
+ };
750
+ await this.oid4vciHolderSendNotification({
751
+ openID4VCIClientState,
752
+ stored: persist,
753
+ credentialsToAccept,
754
+ credentialsSupported,
755
+ notificationRequest,
756
+ serverMetadata,
757
+ }, context);
758
+ }
759
+ const persistCredential = holderCredential
760
+ ? CredentialMapper.storedCredentialToOriginalFormat(holderCredential)
761
+ : mappedCredentialToAccept.rawVerifiableCredential;
762
+ if (!persist && holderCredential) {
763
+ logger.log(`Will not persist credential, since we are signing as a holder and the issuer asked not to persist`);
764
+ }
765
+ else {
766
+ logger.log(`Persisting credential`, persistCredential);
767
+ const issuer = CredentialMapper.issuerCorrelationIdFromIssuerType(verifiableCredential.issuer);
768
+ const [subjectCorrelationType, subjectCorrelationId] = this.determineSubjectCorrelation(issuanceOpt.identifier, issuer);
769
+ const persistedCredential = await context.agent.crsAddCredential({
770
+ credential: {
771
+ rawDocument: ensureRawDocument(persistCredential),
772
+ kmsKeyRef: kmsKeyRef,
773
+ identifierMethod: method,
774
+ credentialRole: CredentialRole.HOLDER,
775
+ issuerCorrelationType: issuer?.startsWith('did:') ? CredentialCorrelationType.DID : CredentialCorrelationType.URL,
776
+ issuerCorrelationId: issuer,
777
+ subjectCorrelationType,
778
+ subjectCorrelationId,
779
+ },
780
+ });
781
+ await context.agent.emit(OID4VCIHolderEvent.CREDENTIAL_STORED, {
782
+ credential: persistedCredential,
783
+ vcHash: persistedCredential.hash,
784
+ });
785
+ }
775
786
  }
776
- oid4vciHolderSendNotification(args, context) {
777
- return __awaiter(this, void 0, void 0, function* () {
778
- var _a, _b;
779
- const { serverMetadata, notificationRequest, openID4VCIClientState } = args;
780
- const notificationEndpoint = (_a = serverMetadata === null || serverMetadata === void 0 ? void 0 : serverMetadata.credentialIssuerMetadata) === null || _a === void 0 ? void 0 : _a.notification_endpoint;
781
- if (!notificationEndpoint) {
782
- return;
783
- }
784
- else if (!openID4VCIClientState) {
785
- return Promise.reject(Error('Missing openID4VCI client state in context'));
786
- }
787
- else if (!notificationRequest) {
788
- return Promise.reject(Error('Missing notification request'));
789
- }
790
- logger.log(`Will send notification to ${notificationEndpoint}`, notificationRequest);
791
- const client = yield oid4vci_client_1.OpenID4VCIClient.fromState({ state: openID4VCIClientState });
792
- yield client.sendNotification({ notificationEndpoint }, notificationRequest, (_b = openID4VCIClientState === null || openID4VCIClientState === void 0 ? void 0 : openID4VCIClientState.accessTokenResponse) === null || _b === void 0 ? void 0 : _b.access_token);
793
- logger.log(`Notification to ${notificationEndpoint} has been dispatched`);
794
- });
787
+ async oid4vciHolderSendNotification(args, context) {
788
+ const { serverMetadata, notificationRequest, openID4VCIClientState } = args;
789
+ const notificationEndpoint = serverMetadata?.credentialIssuerMetadata?.notification_endpoint;
790
+ if (!notificationEndpoint) {
791
+ return;
792
+ }
793
+ else if (!openID4VCIClientState) {
794
+ return Promise.reject(Error('Missing openID4VCI client state in context'));
795
+ }
796
+ else if (!notificationRequest) {
797
+ return Promise.reject(Error('Missing notification request'));
798
+ }
799
+ logger.log(`Will send notification to ${notificationEndpoint}`, notificationRequest);
800
+ const client = await OpenID4VCIClient.fromState({ state: openID4VCIClientState });
801
+ await client.sendNotification({ notificationEndpoint }, notificationRequest, openID4VCIClientState?.accessTokenResponse?.access_token);
802
+ logger.log(`Notification to ${notificationEndpoint} has been dispatched`);
795
803
  }
796
- getFederationTrust(args, context) {
797
- return __awaiter(this, void 0, void 0, function* () {
798
- const { requestData, serverMetadata, trustAnchors } = args;
799
- if (trustAnchors.length === 0) {
800
- return Promise.reject(Error('No trust anchors found'));
801
- }
802
- if (!(requestData === null || requestData === void 0 ? void 0 : requestData.uri)) {
803
- return Promise.reject(Error('Missing request URI in context'));
804
- }
805
- if (!serverMetadata) {
806
- return Promise.reject(Error('Missing serverMetadata in context'));
807
- }
808
- const url = new URL(requestData === null || requestData === void 0 ? void 0 : requestData.uri);
809
- const params = new URLSearchParams(url.search);
810
- const openidFederation = params.get('openid_federation');
811
- const entityIdentifier = openidFederation !== null && openidFederation !== void 0 ? openidFederation : serverMetadata.issuer;
812
- const result = yield context.agent.identifierExternalResolveByOIDFEntityId({
813
- method: 'entity_id',
814
- trustAnchors: trustAnchors,
815
- identifier: entityIdentifier,
816
- });
817
- return result.trustedAnchors;
804
+ async getFederationTrust(args, context) {
805
+ const { requestData, serverMetadata, trustAnchors } = args;
806
+ if (trustAnchors.length === 0) {
807
+ return Promise.reject(Error('No trust anchors found'));
808
+ }
809
+ if (!requestData?.uri) {
810
+ return Promise.reject(Error('Missing request URI in context'));
811
+ }
812
+ if (!serverMetadata) {
813
+ return Promise.reject(Error('Missing serverMetadata in context'));
814
+ }
815
+ const url = new URL(requestData?.uri);
816
+ const params = new URLSearchParams(url.search);
817
+ const openidFederation = params.get('openid_federation');
818
+ const entityIdentifier = openidFederation ?? serverMetadata.issuer;
819
+ if (entityIdentifier.startsWith('http://')) {
820
+ console.warn(`OpenID federation does not support http://, only https:// allowed; got: (${url.toString()})`);
821
+ // OIDF always needs to be https
822
+ return [];
823
+ }
824
+ const result = await context.agent.identifierExternalResolveByOIDFEntityId({
825
+ method: 'entity_id',
826
+ trustAnchors: trustAnchors,
827
+ identifier: entityIdentifier,
818
828
  });
829
+ return result.trustedAnchors;
819
830
  }
820
- oid4vciHolderGetIssuerMetadata(args, context) {
821
- return __awaiter(this, void 0, void 0, function* () {
822
- const { issuer, errorOnNotFound = true } = args;
823
- return oid4vci_client_1.MetadataClient.retrieveAllMetadata(issuer, { errorOnNotFound });
824
- });
831
+ async oid4vciHolderGetIssuerMetadata(args, context) {
832
+ const { issuer, errorOnNotFound = true } = args;
833
+ return MetadataClient.retrieveAllMetadata(issuer, { errorOnNotFound });
825
834
  }
826
835
  determineSubjectCorrelation(identifier, issuer) {
827
836
  switch (identifier.method) {
828
837
  case 'did':
829
- if ((0, ssi_sdk_ext_identifier_resolution_1.isManagedIdentifierResult)(identifier) && (0, ssi_sdk_ext_identifier_resolution_1.isManagedIdentifierDidResult)(identifier)) {
830
- return [ssi_sdk_data_store_1.CredentialCorrelationType.DID, identifier.did];
838
+ if (isManagedIdentifierResult(identifier) && isManagedIdentifierDidResult(identifier)) {
839
+ return [CredentialCorrelationType.DID, identifier.did];
831
840
  }
832
- else if ((0, ssi_sdk_ext_identifier_resolution_1.isManagedIdentifierDidOpts)(identifier)) {
833
- return [ssi_sdk_data_store_1.CredentialCorrelationType.DID, typeof identifier.identifier === 'string' ? identifier.identifier : identifier.identifier.did];
841
+ else if (isManagedIdentifierDidOpts(identifier)) {
842
+ return [CredentialCorrelationType.DID, typeof identifier.identifier === 'string' ? identifier.identifier : identifier.identifier.did];
834
843
  }
835
844
  break;
836
845
  case 'kid':
837
- if ((0, ssi_sdk_ext_identifier_resolution_1.isManagedIdentifierResult)(identifier) && (0, ssi_sdk_ext_identifier_resolution_1.isManagedIdentifierKidResult)(identifier)) {
838
- return [ssi_sdk_data_store_1.CredentialCorrelationType.KID, identifier.kid];
846
+ if (isManagedIdentifierResult(identifier) && isManagedIdentifierKidResult(identifier)) {
847
+ return [CredentialCorrelationType.KID, identifier.kid];
839
848
  }
840
- else if ((0, ssi_sdk_ext_identifier_resolution_1.isManagedIdentifierDidOpts)(identifier)) {
841
- return [ssi_sdk_data_store_1.CredentialCorrelationType.KID, identifier.identifier];
849
+ else if (isManagedIdentifierDidOpts(identifier)) {
850
+ return [CredentialCorrelationType.KID, identifier.identifier];
842
851
  }
843
852
  break;
844
853
  case 'x5c':
845
- if ((0, ssi_sdk_ext_identifier_resolution_1.isManagedIdentifierResult)(identifier) && (0, ssi_sdk_ext_identifier_resolution_1.isManagedIdentifierX5cResult)(identifier)) {
846
- return [ssi_sdk_data_store_1.CredentialCorrelationType.X509_SAN, identifier.x5c.join('\r\n')];
854
+ if (isManagedIdentifierResult(identifier) && isManagedIdentifierX5cResult(identifier)) {
855
+ return [CredentialCorrelationType.X509_SAN, identifier.x5c.join('\r\n')];
847
856
  }
848
- else if ((0, ssi_sdk_ext_identifier_resolution_1.isManagedIdentifierX5cOpts)(identifier)) {
849
- return [ssi_sdk_data_store_1.CredentialCorrelationType.X509_SAN, identifier.identifier.join('\r\n')];
857
+ else if (isManagedIdentifierX5cOpts(identifier)) {
858
+ return [CredentialCorrelationType.X509_SAN, identifier.identifier.join('\r\n')];
850
859
  }
851
860
  break;
852
861
  }
853
- return [ssi_sdk_data_store_1.CredentialCorrelationType.URL, issuer];
862
+ return [CredentialCorrelationType.URL, issuer];
854
863
  }
855
864
  idFromW3cCredentialSubject(wrappedIssuerVC) {
856
- var _a, _b, _c, _d, _e;
857
- if (Array.isArray((_a = wrappedIssuerVC.credential) === null || _a === void 0 ? void 0 : _a.credentialSubject)) {
858
- if (((_b = wrappedIssuerVC.credential) === null || _b === void 0 ? void 0 : _b.credentialSubject.length) > 0) {
859
- return (_c = wrappedIssuerVC.credential) === null || _c === void 0 ? void 0 : _c.credentialSubject[0].id;
865
+ if (Array.isArray(wrappedIssuerVC.credential?.credentialSubject)) {
866
+ if (wrappedIssuerVC.credential?.credentialSubject.length > 0) {
867
+ return wrappedIssuerVC.credential?.credentialSubject[0].id;
860
868
  }
861
869
  }
862
870
  else {
863
- return (_e = (_d = wrappedIssuerVC.credential) === null || _d === void 0 ? void 0 : _d.credentialSubject) === null || _e === void 0 ? void 0 : _e.id;
871
+ return wrappedIssuerVC.credential?.credentialSubject?.id;
872
+ }
873
+ return undefined;
874
+ }
875
+ getCredentialDefinition(issuanceOpt) {
876
+ if (issuanceOpt.format == 'ldp_vc' || issuanceOpt.format == 'jwt_vc_json-ld') {
877
+ return issuanceOpt.credential_definition;
864
878
  }
865
879
  return undefined;
866
880
  }
867
881
  }
868
- exports.OID4VCIHolder = OID4VCIHolder;
869
- OID4VCIHolder.DEFAULT_MOBILE_REDIRECT_URI = `${oid4vci_common_1.DefaultURISchemes.CREDENTIAL_OFFER}://`;
870
882
  //# sourceMappingURL=OID4VCIHolder.js.map