@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.
- package/dist/agent/OID4VCIHolder.d.ts +1 -0
- package/dist/agent/OID4VCIHolder.d.ts.map +1 -1
- package/dist/agent/OID4VCIHolder.js +733 -721
- package/dist/agent/OID4VCIHolder.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -27
- package/dist/index.js.map +1 -1
- package/dist/link-handler/index.d.ts.map +1 -1
- package/dist/link-handler/index.js +55 -49
- package/dist/link-handler/index.js.map +1 -1
- package/dist/listeners/headlessStateNavListener.js +7 -20
- package/dist/listeners/headlessStateNavListener.js.map +1 -1
- package/dist/localization/Localization.js +38 -43
- package/dist/localization/Localization.js.map +1 -1
- package/dist/machines/firstPartyMachine.d.ts.map +1 -1
- package/dist/machines/firstPartyMachine.js +89 -88
- package/dist/machines/firstPartyMachine.js.map +1 -1
- package/dist/machines/oid4vciMachine.d.ts.map +1 -1
- package/dist/machines/oid4vciMachine.js +307 -326
- package/dist/machines/oid4vciMachine.js.map +1 -1
- package/dist/mappers/OIDC4VCIBrandingMapper.d.ts.map +1 -1
- package/dist/mappers/OIDC4VCIBrandingMapper.js +164 -136
- package/dist/mappers/OIDC4VCIBrandingMapper.js.map +1 -1
- package/dist/services/FirstPartyMachineServices.d.ts.map +1 -1
- package/dist/services/FirstPartyMachineServices.js +20 -30
- package/dist/services/FirstPartyMachineServices.js.map +1 -1
- package/dist/services/OID4VCIHolderService.d.ts.map +1 -1
- package/dist/services/OID4VCIHolderService.js +147 -154
- package/dist/services/OID4VCIHolderService.js.map +1 -1
- package/dist/types/FirstPartyMachine.d.ts.map +1 -1
- package/dist/types/FirstPartyMachine.js +6 -9
- package/dist/types/FirstPartyMachine.js.map +1 -1
- package/dist/types/IOID4VCIHolder.d.ts +6 -6
- package/dist/types/IOID4VCIHolder.d.ts.map +1 -1
- package/dist/types/IOID4VCIHolder.js +20 -23
- package/dist/types/IOID4VCIHolder.js.map +1 -1
- package/package.json +26 -25
- package/src/agent/OID4VCIHolder.ts +33 -11
- package/src/index.ts +1 -0
- package/src/link-handler/index.ts +6 -8
- package/src/machines/firstPartyMachine.ts +60 -69
- package/src/machines/oid4vciMachine.ts +9 -11
- package/src/mappers/OIDC4VCIBrandingMapper.ts +26 -25
- package/src/services/FirstPartyMachineServices.ts +11 -10
- package/src/services/OID4VCIHolderService.ts +25 -24
- package/src/types/FirstPartyMachine.ts +56 -64
- package/src/types/IOID4VCIHolder.ts +35 -32
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OID4VCIHolderService.d.ts","sourceRoot":"","sources":["../../src/services/OID4VCIHolderService.ts"],"names":[],"mappings":"AACA,OAAO,EACL,gCAAgC,EAUhC,kCAAkC,EACnC,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EAAgC,sBAAsB,EAAE,MAAM,iCAAiC,CAAA;AACtG,OAAO,EAIL,uBAAuB,EACvB,uBAAuB,EAExB,MAAM,6CAA6C,CAAA;AAEpD,OAAO,EAAE,8BAA8B,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAA;
|
|
1
|
+
{"version":3,"file":"OID4VCIHolderService.d.ts","sourceRoot":"","sources":["../../src/services/OID4VCIHolderService.ts"],"names":[],"mappings":"AACA,OAAO,EACL,gCAAgC,EAUhC,kCAAkC,EACnC,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EAAgC,sBAAsB,EAAE,MAAM,iCAAiC,CAAA;AACtG,OAAO,EAIL,uBAAuB,EACvB,uBAAuB,EAExB,MAAM,6CAA6C,CAAA;AAEpD,OAAO,EAAE,8BAA8B,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAA;AAiBzG,OAAO,EAEL,yBAAyB,EACzB,iCAAiC,EACjC,iDAAiD,EACjD,iBAAiB,EACjB,0BAA0B,EAC1B,wBAAwB,EACxB,mBAAmB,EACnB,gCAAgC,EAChC,iCAAiC,EACjC,YAAY,EACZ,yBAAyB,EACzB,wBAAwB,EAExB,2BAA2B,EAC3B,kBAAkB,EAClB,4BAA4B,EAC5B,gCAAgC,EAChC,eAAe,EAChB,MAAM,yBAAyB,CAAA;AAMhC,eAAO,MAAM,qBAAqB,SAAgB,yBAAyB,KAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,8BAA8B,CAAC,CAAC,CA6C1I,CAAA;AAED,eAAO,MAAM,4BAA4B,SAAgB,gCAAgC,KAAG,OAAO,CAAC,KAAK,CAAC,0BAA0B,CAAC,CASpI,CAAA;AAED,eAAO,MAAM,qCAAqC,SAC1C,iCAAiC,KACtC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,gCAAgC,CAAC,CAW1D,CAAA;AAED,eAAO,MAAM,8BAA8B,SACnC,2BAA2B,KAChC,OAAO,CAAC,8BAA8B,GAAG,0BAA0B,GAAG,SAAS,CAOjF,CAAA;AAED,eAAO,MAAM,wBAAwB,SAAgB,4BAA4B,KAAG,OAAO,CAAC,kBAAkB,CAkD7G,CAAA;AAED,eAAO,MAAM,qBAAqB,SAAgB,yBAAyB,KAAG,OAAO,CAAC,wBAAwB,CA8C7G,CAAA;AAED,eAAO,MAAM,iBAAiB,SAAgB,iBAAiB,KAAG,OAAO,CAAC,uBAAuB,CAiEhG,CAAA;AAED,eAAO,MAAM,mCAAmC,SACxC,iCAAiC,KACtC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,gCAAgC,CAAC,CAM1D,CAAA;AAED,eAAO,MAAM,6BAA6B,SAClC,iCAAiC,KACtC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,gCAAgC,CAAC,CAAC,CAqBjE,CAAA;AACD;;;;GAIG;AACH,eAAO,MAAM,6CAA6C,SAClD,iDAAiD,KACtD,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,gCAAgC,CAAC,CA8F1D,CAAA;AAED,eAAO,MAAM,eAAe,SAAgB,mBAAmB,KAAG,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAwD5F,CAAA;AAED,eAAO,MAAM,iBAAiB,SACtB,wBAAwB,KAC7B,OAAO,CAAC;IACT,OAAO,EAAE,uBAAuB,EAAE,CAAA;IAClC,SAAS,CAAC,EAAE,sBAAsB,CAAA;CACnC,CAiCA,CAAA;AAED,eAAO,MAAM,sBAAsB,SAAgB,0BAA0B,KAAG,OAAO,CAAC,MAAM,CAiE7F,CAAA;AAED,eAAO,MAAM,gCAAgC,SACrC,gCAAgC,WAC7B,eAAe,KACvB,OAAO,CAAC,kCAAkC,GAAG,MAAM,CAwCrD,CAAA"}
|
|
@@ -1,53 +1,42 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
const ssi_sdk_ext_did_utils_1 = require("@sphereon/ssi-sdk-ext.did-utils");
|
|
17
|
-
const ssi_sdk_ext_identifier_resolution_1 = require("@sphereon/ssi-sdk-ext.identifier-resolution");
|
|
18
|
-
const ssi_sdk_ext_key_utils_1 = require("@sphereon/ssi-sdk-ext.key-utils");
|
|
19
|
-
const ssi_types_1 = require("@sphereon/ssi-types");
|
|
20
|
-
const utils_1 = require("@veramo/utils");
|
|
21
|
-
const Localization_1 = require("../localization/Localization");
|
|
22
|
-
const IOID4VCIHolder_1 = require("../types/IOID4VCIHolder");
|
|
23
|
-
const OIDC4VCIBrandingMapper_1 = require("../mappers/OIDC4VCIBrandingMapper");
|
|
24
|
-
const firstPartyMachine_1 = require("../machines/firstPartyMachine");
|
|
25
|
-
const FirstPartyMachine_1 = require("../types/FirstPartyMachine");
|
|
26
|
-
const getCredentialBranding = (args) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1
|
+
import { LOG } from '@sphereon/oid4vci-client';
|
|
2
|
+
import { getSupportedCredentials, getTypesFromCredentialSupported, getTypesFromObject, OpenId4VCIVersion, } from '@sphereon/oid4vci-common';
|
|
3
|
+
import { KeyUse } from '@sphereon/ssi-sdk-ext.did-resolver-jwk';
|
|
4
|
+
import { getOrCreatePrimaryIdentifier, SupportedDidMethodEnum } from '@sphereon/ssi-sdk-ext.did-utils';
|
|
5
|
+
import { isIIdentifier, isManagedIdentifierDidResult, isManagedIdentifierResult, managedIdentifierToJwk, } from '@sphereon/ssi-sdk-ext.identifier-resolution';
|
|
6
|
+
import { keyTypeFromCryptographicSuite } from '@sphereon/ssi-sdk-ext.key-utils';
|
|
7
|
+
import { CredentialMapper, JoseSignatureAlgorithm, mdocDecodedCredentialToUniformCredential, sdJwtDecodedCredentialToUniformCredential, } from '@sphereon/ssi-types';
|
|
8
|
+
import { asArray } from '@veramo/utils';
|
|
9
|
+
import { translate } from '../localization/Localization';
|
|
10
|
+
import { OID4VCIHolderEvent, } from '../types/IOID4VCIHolder';
|
|
11
|
+
import { oid4vciGetCredentialBrandingFrom, sdJwtGetCredentialBrandingFrom, issuerLocaleBrandingFrom } from '../mappers/OIDC4VCIBrandingMapper';
|
|
12
|
+
import { FirstPartyMachine } from '../machines/firstPartyMachine';
|
|
13
|
+
import { FirstPartyMachineStateTypes } from '../types/FirstPartyMachine';
|
|
14
|
+
import { defaultHasher } from '@sphereon/ssi-sdk.core';
|
|
15
|
+
export const getCredentialBranding = async (args) => {
|
|
27
16
|
const { credentialsSupported, context } = args;
|
|
28
17
|
const credentialBranding = {};
|
|
29
|
-
|
|
18
|
+
await Promise.all(Object.entries(credentialsSupported).map(async ([configId, credentialsConfigSupported]) => {
|
|
30
19
|
let sdJwtTypeMetadata;
|
|
31
20
|
if (credentialsConfigSupported.format === 'vc+sd-jwt') {
|
|
32
21
|
const vct = credentialsConfigSupported.vct;
|
|
33
22
|
if (vct.startsWith('http')) {
|
|
34
23
|
try {
|
|
35
|
-
sdJwtTypeMetadata =
|
|
24
|
+
sdJwtTypeMetadata = await context.agent.fetchSdJwtTypeMetadataFromVctUrl({ vct });
|
|
36
25
|
}
|
|
37
|
-
catch
|
|
26
|
+
catch {
|
|
38
27
|
// For now, we are just going to ignore and continue without any branding as we still have a fallback
|
|
39
28
|
}
|
|
40
29
|
}
|
|
41
30
|
}
|
|
42
31
|
let mappedLocaleBranding = [];
|
|
43
32
|
if (sdJwtTypeMetadata) {
|
|
44
|
-
mappedLocaleBranding =
|
|
33
|
+
mappedLocaleBranding = await sdJwtGetCredentialBrandingFrom({
|
|
45
34
|
credentialDisplay: sdJwtTypeMetadata.display,
|
|
46
|
-
claimsMetadata: sdJwtTypeMetadata.claims
|
|
35
|
+
claimsMetadata: sdJwtTypeMetadata.claims,
|
|
47
36
|
});
|
|
48
37
|
}
|
|
49
38
|
else {
|
|
50
|
-
mappedLocaleBranding =
|
|
39
|
+
mappedLocaleBranding = await oid4vciGetCredentialBrandingFrom({
|
|
51
40
|
credentialDisplay: credentialsConfigSupported.display,
|
|
52
41
|
issuerCredentialSubject:
|
|
53
42
|
// @ts-ignore // FIXME SPRIND-123 add proper support for type recognition as claim display can be located elsewhere for v13
|
|
@@ -55,26 +44,24 @@ const getCredentialBranding = (args) => __awaiter(void 0, void 0, void 0, functi
|
|
|
55
44
|
});
|
|
56
45
|
}
|
|
57
46
|
// TODO we should make the mapper part of the plugin, so that the logic for getting the branding becomes more clear and easier to use
|
|
58
|
-
const localeBranding =
|
|
47
|
+
const localeBranding = await Promise.all(mappedLocaleBranding.map(async (localeBranding) => await context.agent.ibCredentialLocaleBrandingFrom({ localeBranding })));
|
|
59
48
|
const defaultCredentialType = 'VerifiableCredential';
|
|
60
|
-
const configSupportedTypes =
|
|
61
|
-
const credentialTypes = configSupportedTypes.length === 0 ?
|
|
49
|
+
const configSupportedTypes = getTypesFromCredentialSupported(credentialsConfigSupported);
|
|
50
|
+
const credentialTypes = configSupportedTypes.length === 0 ? asArray(defaultCredentialType) : configSupportedTypes;
|
|
62
51
|
const filteredCredentialTypes = credentialTypes.filter((type) => type !== defaultCredentialType);
|
|
63
52
|
credentialBranding[filteredCredentialTypes[0]] = localeBranding; // TODO for now taking the first type
|
|
64
|
-
}))
|
|
53
|
+
}));
|
|
65
54
|
return credentialBranding;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const getBasicIssuerLocaleBranding = (args) => __awaiter(void 0, void 0, void 0, function* () {
|
|
55
|
+
};
|
|
56
|
+
export const getBasicIssuerLocaleBranding = async (args) => {
|
|
69
57
|
const { display, dynamicRegistrationClientMetadata, context } = args;
|
|
70
|
-
return
|
|
58
|
+
return await Promise.all(display.map(async (issuerDisplay) => {
|
|
71
59
|
// FIXME for now we do not have locale support for dynamicRegistrationClientMetadata, so we add all the metadata to every locale
|
|
72
|
-
const branding =
|
|
60
|
+
const branding = await issuerLocaleBrandingFrom({ issuerDisplay, dynamicRegistrationClientMetadata });
|
|
73
61
|
return context.agent.ibIssuerLocaleBrandingFrom({ localeBranding: branding });
|
|
74
|
-
}))
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const getCredentialConfigsBasedOnFormatPref = (args) => __awaiter(void 0, void 0, void 0, function* () {
|
|
62
|
+
}));
|
|
63
|
+
};
|
|
64
|
+
export const getCredentialConfigsBasedOnFormatPref = async (args) => {
|
|
78
65
|
const { vcFormatPreferences, credentials } = args;
|
|
79
66
|
const prefConfigs = {};
|
|
80
67
|
Object.entries(credentials).forEach(([key, config]) => {
|
|
@@ -84,34 +71,31 @@ const getCredentialConfigsBasedOnFormatPref = (args) => __awaiter(void 0, void 0
|
|
|
84
71
|
}
|
|
85
72
|
});
|
|
86
73
|
return prefConfigs;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const selectCredentialLocaleBranding = (args) => __awaiter(void 0, void 0, void 0, function* () {
|
|
74
|
+
};
|
|
75
|
+
export const selectCredentialLocaleBranding = async (args) => {
|
|
90
76
|
const { locale, localeBranding } = args;
|
|
91
|
-
return localeBranding
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
const verifyCredentialToAccept = (args) => __awaiter(void 0, void 0, void 0, function* () {
|
|
95
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
77
|
+
return localeBranding?.find((branding) => locale ? branding.locale?.startsWith(locale) || branding.locale === undefined : branding.locale === undefined);
|
|
78
|
+
};
|
|
79
|
+
export const verifyCredentialToAccept = async (args) => {
|
|
96
80
|
const { mappedCredential, hasher, onVerifyEBSICredentialIssuer, schemaValidation, context } = args;
|
|
97
81
|
const credential = mappedCredential.credentialToAccept.credentialResponse.credential;
|
|
98
82
|
if (!credential) {
|
|
99
83
|
return Promise.reject(Error('No credential found in credential response'));
|
|
100
84
|
}
|
|
101
|
-
const wrappedVC =
|
|
102
|
-
if (
|
|
103
|
-
(typeof
|
|
104
|
-
?
|
|
105
|
-
:
|
|
85
|
+
const wrappedVC = CredentialMapper.toWrappedVerifiableCredential(credential, { hasher: hasher ?? defaultHasher });
|
|
86
|
+
if (wrappedVC.decoded?.iss?.includes('did:ebsi:') ||
|
|
87
|
+
(typeof wrappedVC.decoded?.vc?.issuer === 'string'
|
|
88
|
+
? wrappedVC.decoded?.vc?.issuer?.includes('did:ebsi:')
|
|
89
|
+
: wrappedVC.decoded?.vc?.issuer?.existingInstanceId?.includes('did:ebsi:'))) {
|
|
106
90
|
// TODO: Skipping VC validation for EBSI conformance issued credential, as their Issuer is not present in the ledger (sigh)
|
|
107
91
|
// just calling the verifySchema functionality for ebsi credentials
|
|
108
|
-
|
|
92
|
+
await context.agent.cvVerifySchema({ credential, hasher, validationPolicy: schemaValidation });
|
|
109
93
|
if (JSON.stringify(wrappedVC.decoded).includes('vc:ebsi:conformance')) {
|
|
110
94
|
return { source: wrappedVC, error: undefined, result: true, subResults: [] };
|
|
111
95
|
}
|
|
112
96
|
if (onVerifyEBSICredentialIssuer) {
|
|
113
97
|
try {
|
|
114
|
-
|
|
98
|
+
await onVerifyEBSICredentialIssuer({
|
|
115
99
|
wrappedVc: wrappedVC,
|
|
116
100
|
});
|
|
117
101
|
}
|
|
@@ -120,7 +104,7 @@ const verifyCredentialToAccept = (args) => __awaiter(void 0, void 0, void 0, fun
|
|
|
120
104
|
}
|
|
121
105
|
}
|
|
122
106
|
}
|
|
123
|
-
const verificationResult =
|
|
107
|
+
const verificationResult = await context.agent.cvVerifyCredential({
|
|
124
108
|
credential,
|
|
125
109
|
hasher,
|
|
126
110
|
// TODO WAL-675 we might want to allow these types of options as part of the context, now we have state machines. Allows us to pre-determine whether these policies apply and whether remote context should be fetched
|
|
@@ -133,98 +117,102 @@ const verifyCredentialToAccept = (args) => __awaiter(void 0, void 0, void 0, fun
|
|
|
133
117
|
},
|
|
134
118
|
});
|
|
135
119
|
if (!verificationResult.result || verificationResult.error) {
|
|
136
|
-
return Promise.reject(Error(
|
|
120
|
+
return Promise.reject(Error(verificationResult.error ?? translate('oid4vci_machine_credential_verification_failed_message')));
|
|
137
121
|
}
|
|
138
122
|
return verificationResult;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
const mapCredentialToAccept = (args) => __awaiter(void 0, void 0, void 0, function* () {
|
|
123
|
+
};
|
|
124
|
+
export const mapCredentialToAccept = async (args) => {
|
|
142
125
|
const { credentialToAccept, hasher } = args;
|
|
143
126
|
const credentialResponse = credentialToAccept.credentialResponse;
|
|
144
127
|
const verifiableCredential = credentialResponse.credential;
|
|
145
128
|
if (!verifiableCredential) {
|
|
146
129
|
return Promise.reject(Error('No credential found in credential response'));
|
|
147
130
|
}
|
|
148
|
-
const wrappedVerifiableCredential =
|
|
131
|
+
const wrappedVerifiableCredential = CredentialMapper.toWrappedVerifiableCredential(verifiableCredential, { hasher });
|
|
149
132
|
let uniformVerifiableCredential;
|
|
150
|
-
if (
|
|
151
|
-
uniformVerifiableCredential =
|
|
133
|
+
if (CredentialMapper.isSdJwtDecodedCredential(wrappedVerifiableCredential.credential)) {
|
|
134
|
+
uniformVerifiableCredential = await sdJwtDecodedCredentialToUniformCredential(wrappedVerifiableCredential.credential);
|
|
152
135
|
}
|
|
153
|
-
else if (
|
|
136
|
+
else if (CredentialMapper.isSdJwtEncoded(wrappedVerifiableCredential.credential)) {
|
|
154
137
|
if (!hasher) {
|
|
155
138
|
return Promise.reject('a hasher is required for encoded SD-JWT credentials');
|
|
156
139
|
}
|
|
157
140
|
const asyncHasher = (data, algorithm) => Promise.resolve(hasher(data, algorithm));
|
|
158
|
-
const decodedSdJwt =
|
|
159
|
-
uniformVerifiableCredential =
|
|
141
|
+
const decodedSdJwt = await CredentialMapper.decodeSdJwtVcAsync(wrappedVerifiableCredential.credential, asyncHasher);
|
|
142
|
+
uniformVerifiableCredential = sdJwtDecodedCredentialToUniformCredential(decodedSdJwt);
|
|
160
143
|
}
|
|
161
|
-
else if (
|
|
162
|
-
uniformVerifiableCredential =
|
|
144
|
+
else if (CredentialMapper.isMsoMdocDecodedCredential(wrappedVerifiableCredential.credential)) {
|
|
145
|
+
uniformVerifiableCredential = mdocDecodedCredentialToUniformCredential(wrappedVerifiableCredential.credential);
|
|
163
146
|
}
|
|
164
147
|
else {
|
|
165
148
|
uniformVerifiableCredential = wrappedVerifiableCredential.credential;
|
|
166
149
|
}
|
|
167
150
|
const correlationId = typeof uniformVerifiableCredential.issuer === 'string'
|
|
168
151
|
? uniformVerifiableCredential.issuer
|
|
169
|
-
:
|
|
152
|
+
: CredentialMapper.isSdJwtDecodedCredential(uniformVerifiableCredential)
|
|
170
153
|
? uniformVerifiableCredential.decodedPayload.iss
|
|
171
154
|
: uniformVerifiableCredential.issuer.id;
|
|
172
|
-
return
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
155
|
+
return {
|
|
156
|
+
correlationId,
|
|
157
|
+
credentialToAccept,
|
|
158
|
+
types: credentialToAccept.types,
|
|
159
|
+
rawVerifiableCredential: verifiableCredential,
|
|
160
|
+
uniformVerifiableCredential,
|
|
161
|
+
...(credentialResponse.credential_subject_issuance && { credential_subject_issuance: credentialResponse.credential_subject_issuance }),
|
|
162
|
+
};
|
|
163
|
+
};
|
|
164
|
+
export const getIdentifierOpts = async (args) => {
|
|
177
165
|
const { issuanceOpt, context } = args;
|
|
178
166
|
const { identifier: identifierArg } = issuanceOpt;
|
|
179
|
-
if (identifierArg &&
|
|
167
|
+
if (identifierArg && isManagedIdentifierResult(identifierArg)) {
|
|
180
168
|
return identifierArg;
|
|
181
169
|
}
|
|
182
|
-
const { supportedPreferredDidMethod, supportedBindingMethods, keyType = 'Secp256r1', kms =
|
|
170
|
+
const { supportedPreferredDidMethod, supportedBindingMethods, keyType = 'Secp256r1', kms = await context.agent.keyManagerGetDefaultKeyManagementSystem(), } = issuanceOpt;
|
|
183
171
|
let identifier;
|
|
184
172
|
if (identifierArg) {
|
|
185
|
-
if (
|
|
186
|
-
identifier =
|
|
173
|
+
if (isIIdentifier(identifierArg.identifier)) {
|
|
174
|
+
identifier = await context.agent.identifierManagedGet(identifierArg);
|
|
187
175
|
}
|
|
188
176
|
else if (!identifierArg.method && issuanceOpt.supportedBindingMethods.includes('jwk')) {
|
|
189
|
-
identifier =
|
|
177
|
+
identifier = await managedIdentifierToJwk(identifierArg, context);
|
|
190
178
|
}
|
|
191
179
|
else if (identifierArg.method && !supportedBindingMethods.includes(identifierArg.method)) {
|
|
192
180
|
throw Error(`Supplied identifier method ${identifierArg.method} not supported by the issuer: ${supportedBindingMethods.join(',')}`);
|
|
193
181
|
}
|
|
194
182
|
else {
|
|
195
|
-
identifier =
|
|
183
|
+
identifier = await context.agent.identifierManagedGet(identifierArg);
|
|
196
184
|
}
|
|
197
185
|
}
|
|
198
|
-
const agentContext =
|
|
199
|
-
if ((!identifierArg ||
|
|
186
|
+
const agentContext = { ...context, agent: context.agent };
|
|
187
|
+
if ((!identifierArg || isIIdentifier(identifierArg.identifier)) &&
|
|
200
188
|
supportedPreferredDidMethod &&
|
|
201
189
|
(!supportedBindingMethods || supportedBindingMethods.length === 0 || supportedBindingMethods.filter((method) => method.startsWith('did')))) {
|
|
202
190
|
// previous code for managing DIDs only
|
|
203
|
-
const { result, created } =
|
|
191
|
+
const { result, created } = await getOrCreatePrimaryIdentifier(agentContext, {
|
|
204
192
|
method: supportedPreferredDidMethod,
|
|
205
193
|
createOpts: {
|
|
206
194
|
options: {
|
|
207
195
|
type: issuanceOpt.keyType,
|
|
208
|
-
use:
|
|
196
|
+
use: KeyUse.Signature,
|
|
209
197
|
codecName: issuanceOpt.codecName,
|
|
210
198
|
kms: issuanceOpt.kms,
|
|
211
199
|
},
|
|
212
200
|
},
|
|
213
201
|
});
|
|
214
|
-
identifier =
|
|
202
|
+
identifier = await context.agent.identifierManagedGetByDid({
|
|
215
203
|
identifier: result,
|
|
216
204
|
keyType,
|
|
217
205
|
offlineWhenNoDIDRegistered: result.did.startsWith('did:ebsi:'),
|
|
218
206
|
});
|
|
219
207
|
if (created) {
|
|
220
|
-
|
|
208
|
+
await agentContext.agent.emit(OID4VCIHolderEvent.IDENTIFIER_CREATED, { identifier });
|
|
221
209
|
}
|
|
222
210
|
}
|
|
223
211
|
else if (supportedBindingMethods.includes('jwk')) {
|
|
224
212
|
// todo: we probably should do something similar as with DIDs for re-use/new keys
|
|
225
|
-
const key =
|
|
213
|
+
const key = await context.agent.keyManagerCreate({ type: keyType, kms, meta: { keyAlias: `key_${keyType}_${Date.now()}` } });
|
|
226
214
|
// TODO. Create/move this to identifier service await agentContext.agent.emit(OID4VCIHolderEvent.IDENTIFIER_CREATED, { key })
|
|
227
|
-
identifier =
|
|
215
|
+
identifier = await managedIdentifierToJwk({ method: 'key', identifier: key, kmsKeyRef: key.kid }, context);
|
|
228
216
|
// } else if (supportedBindingMethods.includes('cose_key')) {
|
|
229
217
|
// // TODO COSE HERE
|
|
230
218
|
// throw Error(`Holder currently does not support binding method: ${supportedBindingMethods.join(',')}`)
|
|
@@ -234,40 +222,44 @@ const getIdentifierOpts = (args) => __awaiter(void 0, void 0, void 0, function*
|
|
|
234
222
|
}
|
|
235
223
|
args.issuanceOpt.identifier = identifier;
|
|
236
224
|
return identifier;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
const getCredentialConfigsSupportedMerged = (args) => __awaiter(void 0, void 0, void 0, function* () {
|
|
225
|
+
};
|
|
226
|
+
export const getCredentialConfigsSupportedMerged = async (args) => {
|
|
240
227
|
let result = {};
|
|
241
|
-
(
|
|
242
|
-
result =
|
|
228
|
+
(await getCredentialConfigsSupported(args)).forEach((supported) => {
|
|
229
|
+
result = { ...result, ...supported };
|
|
243
230
|
});
|
|
244
231
|
return result;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
const getCredentialConfigsSupported = (args) => __awaiter(void 0, void 0, void 0, function* () {
|
|
232
|
+
};
|
|
233
|
+
export const getCredentialConfigsSupported = async (args) => {
|
|
248
234
|
const { types, configurationIds } = args;
|
|
249
235
|
if (Array.isArray(types) && types.length > 0) {
|
|
250
|
-
return Promise.all(types.map((type) =>
|
|
236
|
+
return Promise.all(types.map((type) => getCredentialConfigsSupportedBySingleTypeOrId({ ...args, types: type })));
|
|
251
237
|
}
|
|
252
238
|
else if (Array.isArray(configurationIds) && configurationIds.length > 0) {
|
|
253
|
-
return Promise.all(configurationIds.map((configurationId) =>
|
|
254
|
-
|
|
255
|
-
|
|
239
|
+
return Promise.all(configurationIds.map((configurationId) => getCredentialConfigsSupportedBySingleTypeOrId({
|
|
240
|
+
...args,
|
|
241
|
+
configurationId,
|
|
242
|
+
types: undefined,
|
|
243
|
+
})));
|
|
244
|
+
}
|
|
245
|
+
const configs = await getCredentialConfigsSupportedBySingleTypeOrId({
|
|
246
|
+
...args,
|
|
247
|
+
types: undefined,
|
|
248
|
+
configurationId: undefined,
|
|
249
|
+
});
|
|
256
250
|
return configs && Object.keys(configs).length > 0 ? [configs] : [];
|
|
257
|
-
}
|
|
258
|
-
exports.getCredentialConfigsSupported = getCredentialConfigsSupported;
|
|
251
|
+
};
|
|
259
252
|
/**
|
|
260
253
|
* Please note that this method only returns configs supported for a single set of credential types or a single config id.
|
|
261
254
|
* If an offer contains multiple formats/types in an array or multiple config ids, you will have to call this method for all of them
|
|
262
255
|
* @param args
|
|
263
256
|
*/
|
|
264
|
-
const getCredentialConfigsSupportedBySingleTypeOrId = (args) =>
|
|
257
|
+
export const getCredentialConfigsSupportedBySingleTypeOrId = async (args) => {
|
|
265
258
|
const { client, vcFormatPreferences, configurationId } = args;
|
|
266
259
|
let { format = undefined, types = undefined } = args;
|
|
267
260
|
function createIdFromTypes(supported) {
|
|
268
|
-
var _a, _b;
|
|
269
261
|
const format = supported.format;
|
|
270
|
-
const type =
|
|
262
|
+
const type = getTypesFromObject(supported)?.join() ?? '';
|
|
271
263
|
const id = `${type}:${format}`;
|
|
272
264
|
return id;
|
|
273
265
|
}
|
|
@@ -282,18 +274,18 @@ const getCredentialConfigsSupportedBySingleTypeOrId = (args) => __awaiter(void 0
|
|
|
282
274
|
}
|
|
283
275
|
// We should always have a credential offer at this point given the above
|
|
284
276
|
if (!Array.isArray(format) && client.credentialOffer) {
|
|
285
|
-
if (client.version() >
|
|
277
|
+
if (client.version() > OpenId4VCIVersion.VER_1_0_09 &&
|
|
286
278
|
typeof client.credentialOffer.credential_offer === 'object' &&
|
|
287
279
|
'credentials' in client.credentialOffer.credential_offer) {
|
|
288
280
|
format = client.credentialOffer.credential_offer.credentials
|
|
289
281
|
.filter((cred) => typeof cred !== 'string')
|
|
290
282
|
.map((cred) => cred.format);
|
|
291
|
-
if (
|
|
283
|
+
if (format?.length === 0) {
|
|
292
284
|
format = undefined; // Otherwise we would match nothing
|
|
293
285
|
}
|
|
294
286
|
}
|
|
295
287
|
}
|
|
296
|
-
const offerSupported =
|
|
288
|
+
const offerSupported = getSupportedCredentials({
|
|
297
289
|
types: types ? [types] : client.getCredentialOfferTypes(),
|
|
298
290
|
format,
|
|
299
291
|
version: client.version(),
|
|
@@ -314,12 +306,12 @@ const getCredentialConfigsSupportedBySingleTypeOrId = (args) => __awaiter(void 0
|
|
|
314
306
|
allSupported[id] = supported;
|
|
315
307
|
});
|
|
316
308
|
}
|
|
317
|
-
let credentialConfigsSupported =
|
|
309
|
+
let credentialConfigsSupported = await getCredentialConfigsBasedOnFormatPref({
|
|
318
310
|
credentials: allSupported,
|
|
319
311
|
vcFormatPreferences,
|
|
320
312
|
});
|
|
321
313
|
if (!credentialConfigsSupported || Object.keys(credentialConfigsSupported).length === 0) {
|
|
322
|
-
|
|
314
|
+
LOG.warning(`No matching supported credential found for ${client.getIssuer()}`);
|
|
323
315
|
}
|
|
324
316
|
if (client.credentialOffer === undefined) {
|
|
325
317
|
return credentialConfigsSupported;
|
|
@@ -341,27 +333,25 @@ const getCredentialConfigsSupportedBySingleTypeOrId = (args) => __awaiter(void 0
|
|
|
341
333
|
throw new Error(`No matching supported credential configs found for offer`);
|
|
342
334
|
}
|
|
343
335
|
return credentialsToOffer;
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
const getIssuanceOpts = (args) => __awaiter(void 0, void 0, void 0, function* () {
|
|
336
|
+
};
|
|
337
|
+
export const getIssuanceOpts = async (args) => {
|
|
347
338
|
const { client, credentialsSupported,
|
|
348
339
|
// serverMetadata,
|
|
349
340
|
context, didMethodPreferences, jwtCryptographicSuitePreferences, jsonldCryptographicSuitePreferences, forceIssuanceOpt, } = args;
|
|
350
341
|
if (credentialsSupported === undefined || Object.keys(credentialsSupported).length === 0) {
|
|
351
342
|
return Promise.reject(Error('No credentials supported'));
|
|
352
343
|
}
|
|
353
|
-
const getIssuanceOpts = Object.values(credentialsSupported).map((credentialSupported) =>
|
|
344
|
+
const getIssuanceOpts = Object.values(credentialsSupported).map(async (credentialSupported) => {
|
|
354
345
|
/*if (!serverMetadata?.credentialIssuerMetadata) {
|
|
355
346
|
return await getDefaultIssuanceOpts({ credentialSupported, opts: { client }, context })
|
|
356
347
|
}*/
|
|
357
|
-
|
|
358
|
-
const cryptographicSuite = yield (0, exports.getIssuanceCryptoSuite)({
|
|
348
|
+
const cryptographicSuite = await getIssuanceCryptoSuite({
|
|
359
349
|
credentialSupported,
|
|
360
350
|
client,
|
|
361
351
|
jwtCryptographicSuitePreferences,
|
|
362
352
|
jsonldCryptographicSuitePreferences,
|
|
363
353
|
});
|
|
364
|
-
const { didMethod, methods } =
|
|
354
|
+
const { didMethod, methods } = await getIssuanceMethod({
|
|
365
355
|
credentialSupported,
|
|
366
356
|
client,
|
|
367
357
|
didMethodPreferences,
|
|
@@ -371,19 +361,26 @@ const getIssuanceOpts = (args) => __awaiter(void 0, void 0, void 0, function* ()
|
|
|
371
361
|
methods.push('did');
|
|
372
362
|
}
|
|
373
363
|
const issuanceOpt = forceIssuanceOpt
|
|
374
|
-
?
|
|
375
|
-
|
|
376
|
-
|
|
364
|
+
? { ...credentialSupported, ...forceIssuanceOpt }
|
|
365
|
+
: {
|
|
366
|
+
...credentialSupported,
|
|
367
|
+
supportedPreferredDidMethod: didMethod,
|
|
368
|
+
supportedBindingMethods: methods,
|
|
369
|
+
format: credentialSupported.format,
|
|
370
|
+
keyType: client.isEBSI() ? 'Secp256r1' : keyTypeFromCryptographicSuite({ crv: cryptographicSuite }),
|
|
371
|
+
...(client.isEBSI() && { codecName: 'EBSI' }),
|
|
372
|
+
};
|
|
373
|
+
const identifier = await getIdentifierOpts({ issuanceOpt, context });
|
|
374
|
+
if (!client.clientId && isManagedIdentifierDidResult(identifier)) {
|
|
377
375
|
// FIXME: We really should fetch server metadata. Have user select required credentials. Take the first cred to determine a kid when no clientId is present and set that.
|
|
378
376
|
// Needs a preference service for crypto, keys, dids, and clientId, with ecosystem support
|
|
379
|
-
client.clientId =
|
|
377
|
+
client.clientId = identifier.issuer ?? identifier.did;
|
|
380
378
|
}
|
|
381
|
-
return
|
|
382
|
-
})
|
|
383
|
-
return
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
const getIssuanceMethod = (opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
379
|
+
return { ...issuanceOpt, identifier };
|
|
380
|
+
});
|
|
381
|
+
return await Promise.all(getIssuanceOpts);
|
|
382
|
+
};
|
|
383
|
+
export const getIssuanceMethod = async (opts) => {
|
|
387
384
|
const { client, credentialSupported, didMethodPreferences } = opts;
|
|
388
385
|
const { format, cryptographic_binding_methods_supported } = credentialSupported;
|
|
389
386
|
let methods = []; // we use the external identifier method, as we should be supporting all values in the server metadata anyway
|
|
@@ -402,21 +399,19 @@ const getIssuanceMethod = (opts) => __awaiter(void 0, void 0, void 0, function*
|
|
|
402
399
|
console.warn(`We should have been able to determine cryptographic_binding_methods_supported, will fall back to legacy behaviour. This is likely a bug`);
|
|
403
400
|
}
|
|
404
401
|
if (client.isEBSI()) {
|
|
405
|
-
return { methods: ['did'], didMethod:
|
|
402
|
+
return { methods: ['did'], didMethod: SupportedDidMethodEnum.DID_KEY };
|
|
406
403
|
}
|
|
407
404
|
// legacy fallback
|
|
408
405
|
methods = ['did'];
|
|
409
|
-
if (!format || (format.includes('jwt') && !
|
|
406
|
+
if (!format || (format.includes('jwt') && !format?.includes('jwt_vc_json_ld'))) {
|
|
410
407
|
return { methods, didMethod: format ? didMethodPreferences[1] : didMethodPreferences[0] };
|
|
411
408
|
}
|
|
412
409
|
else {
|
|
413
410
|
// JsonLD
|
|
414
411
|
return { methods, didMethod: didMethodPreferences[0] };
|
|
415
412
|
}
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
const getIssuanceCryptoSuite = (opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
419
|
-
var _a, _b;
|
|
413
|
+
};
|
|
414
|
+
export const getIssuanceCryptoSuite = async (opts) => {
|
|
420
415
|
const { client, credentialSupported, jwtCryptographicSuitePreferences, jsonldCryptographicSuitePreferences } = opts;
|
|
421
416
|
let signing_algs_supported;
|
|
422
417
|
if ('proof_types_supported' in credentialSupported && credentialSupported.proof_types_supported) {
|
|
@@ -435,9 +430,9 @@ const getIssuanceCryptoSuite = (opts) => __awaiter(void 0, void 0, void 0, funct
|
|
|
435
430
|
}
|
|
436
431
|
}
|
|
437
432
|
else {
|
|
438
|
-
signing_algs_supported =
|
|
433
|
+
signing_algs_supported = asArray(
|
|
439
434
|
// @ts-ignore // legacy
|
|
440
|
-
|
|
435
|
+
credentialSupported.credential_signing_alg_values_supported ?? credentialSupported.proof_signing_alg_values_supported ?? []);
|
|
441
436
|
}
|
|
442
437
|
// TODO: Return array, so the wallet/user could choose
|
|
443
438
|
switch (credentialSupported.format) {
|
|
@@ -452,7 +447,7 @@ const getIssuanceCryptoSuite = (opts) => __awaiter(void 0, void 0, void 0, funct
|
|
|
452
447
|
return supportedPreferences[0];
|
|
453
448
|
}
|
|
454
449
|
else if (client.isEBSI()) {
|
|
455
|
-
return
|
|
450
|
+
return JoseSignatureAlgorithm.ES256;
|
|
456
451
|
}
|
|
457
452
|
// if we cannot find supported cryptographic suites, we just try with the first preference
|
|
458
453
|
const fallback = jwtCryptographicSuitePreferences[0];
|
|
@@ -476,9 +471,8 @@ const getIssuanceCryptoSuite = (opts) => __awaiter(void 0, void 0, void 0, funct
|
|
|
476
471
|
default:
|
|
477
472
|
return Promise.reject(Error(`Credential format '${credentialSupported.format}' not supported`));
|
|
478
473
|
}
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
const startFirstPartApplicationMachine = (args, context) => __awaiter(void 0, void 0, void 0, function* () {
|
|
474
|
+
};
|
|
475
|
+
export const startFirstPartApplicationMachine = async (args, context) => {
|
|
482
476
|
const { openID4VCIClientState, stateNavigationListener, contact } = args;
|
|
483
477
|
if (!openID4VCIClientState) {
|
|
484
478
|
return Promise.reject(Error('Missing openID4VCI client state in context'));
|
|
@@ -486,29 +480,29 @@ const startFirstPartApplicationMachine = (args, context) => __awaiter(void 0, vo
|
|
|
486
480
|
if (!contact) {
|
|
487
481
|
return Promise.reject(Error('Missing contact in context'));
|
|
488
482
|
}
|
|
489
|
-
const firstPartyMachineInstance =
|
|
483
|
+
const firstPartyMachineInstance = FirstPartyMachine.newInstance({
|
|
490
484
|
openID4VCIClientState,
|
|
491
485
|
contact,
|
|
492
486
|
agentContext: context,
|
|
493
|
-
stateNavigationListener
|
|
487
|
+
stateNavigationListener,
|
|
494
488
|
});
|
|
495
489
|
return new Promise((resolve, reject) => {
|
|
496
490
|
try {
|
|
497
491
|
firstPartyMachineInstance.onTransition((state) => {
|
|
498
|
-
if (state.matches(
|
|
492
|
+
if (state.matches(FirstPartyMachineStateTypes.done)) {
|
|
499
493
|
const authorizationCodeResponse = state.context.authorizationCodeResponse;
|
|
500
494
|
if (!authorizationCodeResponse) {
|
|
501
495
|
reject(Error('No authorizationCodeResponse acquired'));
|
|
502
496
|
}
|
|
503
497
|
resolve(authorizationCodeResponse);
|
|
504
498
|
}
|
|
505
|
-
else if (state.matches(
|
|
506
|
-
resolve(
|
|
499
|
+
else if (state.matches(FirstPartyMachineStateTypes.aborted)) {
|
|
500
|
+
resolve(FirstPartyMachineStateTypes.aborted);
|
|
507
501
|
}
|
|
508
|
-
else if (state.matches(
|
|
509
|
-
resolve(
|
|
502
|
+
else if (state.matches(FirstPartyMachineStateTypes.declined)) {
|
|
503
|
+
resolve(FirstPartyMachineStateTypes.declined);
|
|
510
504
|
}
|
|
511
|
-
else if (state.matches(
|
|
505
|
+
else if (state.matches(FirstPartyMachineStateTypes.error)) {
|
|
512
506
|
reject(state.context.error);
|
|
513
507
|
}
|
|
514
508
|
});
|
|
@@ -518,6 +512,5 @@ const startFirstPartApplicationMachine = (args, context) => __awaiter(void 0, vo
|
|
|
518
512
|
reject(error);
|
|
519
513
|
}
|
|
520
514
|
});
|
|
521
|
-
}
|
|
522
|
-
exports.startFirstPartApplicationMachine = startFirstPartApplicationMachine;
|
|
515
|
+
};
|
|
523
516
|
//# sourceMappingURL=OID4VCIHolderService.js.map
|