@credo-ts/openid4vc 0.6.0-pr-2195-20250226100854 → 0.6.0-pr-2209-20250321171013
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/build/openid4vc-holder/OpenId4VcHolderApi.d.ts +14 -119
- package/build/openid4vc-holder/OpenId4VcHolderApi.js +9 -24
- package/build/openid4vc-holder/OpenId4VcHolderApi.js.map +1 -1
- package/build/openid4vc-holder/OpenId4VcHolderModule.js +1 -1
- package/build/openid4vc-holder/OpenId4VcHolderModule.js.map +1 -1
- package/build/openid4vc-holder/OpenId4VciHolderService.d.ts +8 -7
- package/build/openid4vc-holder/OpenId4VciHolderService.js +21 -19
- package/build/openid4vc-holder/OpenId4VciHolderService.js.map +1 -1
- package/build/openid4vc-holder/OpenId4VciHolderServiceOptions.d.ts +4 -4
- package/build/openid4vc-holder/OpenId4VciHolderServiceOptions.js +2 -2
- package/build/openid4vc-holder/OpenId4VciHolderServiceOptions.js.map +1 -1
- package/build/openid4vc-holder/OpenId4vcSiopHolderService.d.ts +15 -116
- package/build/openid4vc-holder/OpenId4vcSiopHolderService.js +233 -239
- package/build/openid4vc-holder/OpenId4vcSiopHolderService.js.map +1 -1
- package/build/openid4vc-holder/OpenId4vcSiopHolderServiceOptions.d.ts +9 -25
- package/build/openid4vc-issuer/OpenId4VcIssuerApi.d.ts +44 -194
- package/build/openid4vc-issuer/OpenId4VcIssuerEvents.d.ts +1 -1
- package/build/openid4vc-issuer/OpenId4VcIssuerModule.d.ts +1 -1
- package/build/openid4vc-issuer/OpenId4VcIssuerModule.js +1 -1
- package/build/openid4vc-issuer/OpenId4VcIssuerModule.js.map +1 -1
- package/build/openid4vc-issuer/OpenId4VcIssuerModuleConfig.d.ts +8 -8
- package/build/openid4vc-issuer/OpenId4VcIssuerModuleConfig.js +10 -2
- package/build/openid4vc-issuer/OpenId4VcIssuerModuleConfig.js.map +1 -1
- package/build/openid4vc-issuer/OpenId4VcIssuerService.d.ts +48 -198
- package/build/openid4vc-issuer/OpenId4VcIssuerService.js +27 -39
- package/build/openid4vc-issuer/OpenId4VcIssuerService.js.map +1 -1
- package/build/openid4vc-issuer/OpenId4VcIssuerServiceOptions.d.ts +6 -11
- package/build/openid4vc-issuer/repository/OpenId4VcIssuanceSessionRecord.d.ts +2 -2
- package/build/openid4vc-issuer/repository/OpenId4VcIssuanceSessionRecord.js +1 -0
- package/build/openid4vc-issuer/repository/OpenId4VcIssuanceSessionRecord.js.map +1 -1
- package/build/openid4vc-issuer/repository/OpenId4VcIssuanceSessionRepository.d.ts +1 -1
- package/build/openid4vc-issuer/repository/OpenId4VcIssuerRecord.d.ts +1 -1
- package/build/openid4vc-issuer/repository/OpenId4VcIssuerRecord.js +3 -3
- package/build/openid4vc-issuer/repository/OpenId4VcIssuerRecord.js.map +1 -1
- package/build/openid4vc-issuer/repository/OpenId4VcIssuerRepository.d.ts +1 -1
- package/build/openid4vc-issuer/router/accessTokenEndpoint.d.ts +2 -2
- package/build/openid4vc-issuer/router/accessTokenEndpoint.js +1 -1
- package/build/openid4vc-issuer/router/accessTokenEndpoint.js.map +1 -1
- package/build/openid4vc-issuer/router/authorizationChallengeEndpoint.js +1 -1
- package/build/openid4vc-issuer/router/authorizationChallengeEndpoint.js.map +1 -1
- package/build/openid4vc-issuer/router/authorizationServerMetadataEndpoint.js +1 -1
- package/build/openid4vc-issuer/router/authorizationServerMetadataEndpoint.js.map +1 -1
- package/build/openid4vc-issuer/router/credentialEndpoint.d.ts +1 -1
- package/build/openid4vc-issuer/router/credentialEndpoint.js +3 -3
- package/build/openid4vc-issuer/router/credentialEndpoint.js.map +1 -1
- package/build/openid4vc-issuer/router/credentialOfferEndpoint.d.ts +1 -1
- package/build/openid4vc-issuer/router/issuerMetadataEndpoint.js +1 -1
- package/build/openid4vc-issuer/router/issuerMetadataEndpoint.js.map +1 -1
- package/build/openid4vc-issuer/router/jwksEndpoint.d.ts +1 -1
- package/build/openid4vc-issuer/router/nonceEndpoint.d.ts +1 -1
- package/build/openid4vc-issuer/util/txCode.d.ts +1 -1
- package/build/openid4vc-verifier/OpenId4VcSiopVerifierService.d.ts +13 -25
- package/build/openid4vc-verifier/OpenId4VcSiopVerifierService.js +326 -579
- package/build/openid4vc-verifier/OpenId4VcSiopVerifierService.js.map +1 -1
- package/build/openid4vc-verifier/OpenId4VcSiopVerifierServiceOptions.d.ts +20 -36
- package/build/openid4vc-verifier/OpenId4VcVerifierApi.d.ts +2 -2
- package/build/openid4vc-verifier/OpenId4VcVerifierApi.js +1 -1
- package/build/openid4vc-verifier/OpenId4VcVerifierApi.js.map +1 -1
- package/build/openid4vc-verifier/OpenId4VcVerifierEvents.d.ts +1 -1
- package/build/openid4vc-verifier/OpenId4VcVerifierModule.d.ts +1 -1
- package/build/openid4vc-verifier/OpenId4VcVerifierModule.js +4 -1
- package/build/openid4vc-verifier/OpenId4VcVerifierModule.js.map +1 -1
- package/build/openid4vc-verifier/OpenId4VcVerifierModuleConfig.d.ts +2 -2
- package/build/openid4vc-verifier/repository/OpenId4VcRelyingPartyEventEmitter.d.ts +49 -0
- package/build/openid4vc-verifier/repository/OpenId4VcRelyingPartyEventEmitter.js +230 -0
- package/build/openid4vc-verifier/repository/OpenId4VcRelyingPartyEventEmitter.js.map +1 -0
- package/build/openid4vc-verifier/repository/OpenId4VcRelyingPartySessionManager.d.ts +19 -0
- package/build/openid4vc-verifier/repository/OpenId4VcRelyingPartySessionManager.js +144 -0
- package/build/openid4vc-verifier/repository/OpenId4VcRelyingPartySessionManager.js.map +1 -0
- package/build/openid4vc-verifier/repository/OpenId4VcVerificationSessionRecord.d.ts +11 -20
- package/build/openid4vc-verifier/repository/OpenId4VcVerificationSessionRecord.js +7 -18
- package/build/openid4vc-verifier/repository/OpenId4VcVerificationSessionRecord.js.map +1 -1
- package/build/openid4vc-verifier/repository/OpenId4VcVerificationSessionRepository.d.ts +1 -1
- package/build/openid4vc-verifier/repository/OpenId4VcVerifierRecord.d.ts +1 -1
- package/build/openid4vc-verifier/repository/OpenId4VcVerifierRepository.d.ts +1 -1
- package/build/openid4vc-verifier/router/authorizationEndpoint.js +103 -5
- package/build/openid4vc-verifier/router/authorizationEndpoint.js.map +1 -1
- package/build/openid4vc-verifier/router/authorizationRequestEndpoint.js +16 -3
- package/build/openid4vc-verifier/router/authorizationRequestEndpoint.js.map +1 -1
- package/build/shared/callbacks.d.ts +6 -14
- package/build/shared/callbacks.js +14 -102
- package/build/shared/callbacks.js.map +1 -1
- package/build/shared/issuerMetadataUtils.d.ts +144 -102
- package/build/shared/models/OpenId4VcJwtIssuer.d.ts +3 -2
- package/build/shared/models/index.d.ts +10 -10
- package/build/shared/models/index.js +5 -5
- package/build/shared/models/index.js.map +1 -1
- package/build/shared/router/context.d.ts +3 -3
- package/build/shared/router/context.js +4 -4
- package/build/shared/router/context.js.map +1 -1
- package/build/shared/router/express.js +1 -2
- package/build/shared/router/express.js.map +1 -1
- package/build/shared/transform.d.ts +5 -0
- package/build/shared/transform.js +69 -0
- package/build/shared/transform.js.map +1 -0
- package/build/shared/utils.d.ts +8 -6
- package/build/shared/utils.js +105 -34
- package/build/shared/utils.js.map +1 -1
- package/package.json +8 -6
|
@@ -14,15 +14,17 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.OpenId4VcSiopVerifierService = void 0;
|
|
16
16
|
const core_1 = require("@credo-ts/core");
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
const
|
|
17
|
+
const did_auth_siop_1 = require("@sphereon/did-auth-siop");
|
|
18
|
+
const OpenID4VP_1 = require("@sphereon/did-auth-siop/dist/authorization-response/OpenID4VP");
|
|
19
|
+
const rxjs_1 = require("rxjs");
|
|
20
20
|
const router_1 = require("../shared/router");
|
|
21
|
+
const transform_1 = require("../shared/transform");
|
|
21
22
|
const utils_1 = require("../shared/utils");
|
|
22
23
|
const OpenId4VcVerificationSessionState_1 = require("./OpenId4VcVerificationSessionState");
|
|
23
|
-
const OpenId4VcVerifierEvents_1 = require("./OpenId4VcVerifierEvents");
|
|
24
24
|
const OpenId4VcVerifierModuleConfig_1 = require("./OpenId4VcVerifierModuleConfig");
|
|
25
25
|
const repository_1 = require("./repository");
|
|
26
|
+
const OpenId4VcRelyingPartyEventEmitter_1 = require("./repository/OpenId4VcRelyingPartyEventEmitter");
|
|
27
|
+
const OpenId4VcRelyingPartySessionManager_1 = require("./repository/OpenId4VcRelyingPartySessionManager");
|
|
26
28
|
/**
|
|
27
29
|
* @internal
|
|
28
30
|
*/
|
|
@@ -34,39 +36,27 @@ let OpenId4VcSiopVerifierService = class OpenId4VcSiopVerifierService {
|
|
|
34
36
|
this.config = config;
|
|
35
37
|
this.openId4VcVerificationSessionRepository = openId4VcVerificationSessionRepository;
|
|
36
38
|
}
|
|
37
|
-
getOpenid4vpVerifier(agentContext) {
|
|
38
|
-
const callbacks = (0, callbacks_1.getOid4vcCallbacks)(agentContext);
|
|
39
|
-
const openid4vpClient = new openid4vp_1.Openid4vpVerifier({ callbacks });
|
|
40
|
-
return openid4vpClient;
|
|
41
|
-
}
|
|
42
39
|
async createAuthorizationRequest(agentContext, options) {
|
|
43
40
|
const nonce = await agentContext.wallet.generateNonce();
|
|
44
41
|
const state = await agentContext.wallet.generateNonce();
|
|
45
|
-
|
|
46
|
-
const
|
|
47
|
-
// No response url for DC API
|
|
42
|
+
// Correlation id will be the id of the verification session record
|
|
43
|
+
const correlationId = core_1.utils.uuid();
|
|
48
44
|
let authorizationResponseUrl = (0, core_1.joinUriParts)(this.config.baseUrl, [
|
|
49
45
|
options.verifier.verifierId,
|
|
50
46
|
this.config.authorizationEndpoint.endpointPath,
|
|
51
47
|
]);
|
|
52
|
-
const jwtIssuer = options.requestSigner.method === '
|
|
53
|
-
?
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
})
|
|
59
|
-
: await (0, utils_1.requestSignerToJwtIssuer)(agentContext, options.requestSigner);
|
|
48
|
+
const jwtIssuer = options.requestSigner.method === 'x5c'
|
|
49
|
+
? await (0, utils_1.openIdTokenIssuerToJwtIssuer)(agentContext, {
|
|
50
|
+
...options.requestSigner,
|
|
51
|
+
issuer: authorizationResponseUrl,
|
|
52
|
+
})
|
|
53
|
+
: await (0, utils_1.openIdTokenIssuerToJwtIssuer)(agentContext, options.requestSigner);
|
|
60
54
|
let clientIdScheme;
|
|
61
55
|
let clientId;
|
|
62
|
-
if (
|
|
63
|
-
if (
|
|
64
|
-
throw new
|
|
56
|
+
if (jwtIssuer.method === 'x5c') {
|
|
57
|
+
if (jwtIssuer.issuer !== authorizationResponseUrl) {
|
|
58
|
+
throw new core_1.CredoError(`The jwtIssuer's issuer field must match the verifier's authorizationResponseUrl '${authorizationResponseUrl}'.`);
|
|
65
59
|
}
|
|
66
|
-
clientIdScheme = 'web-origin';
|
|
67
|
-
clientId = undefined;
|
|
68
|
-
}
|
|
69
|
-
else if (jwtIssuer?.method === 'x5c') {
|
|
70
60
|
const leafCertificate = core_1.X509Service.getLeafCertificate(agentContext, { certificateChain: jwtIssuer.x5c });
|
|
71
61
|
if (leafCertificate.sanDnsNames.includes((0, core_1.getDomainFromUrl)(jwtIssuer.issuer))) {
|
|
72
62
|
clientIdScheme = 'x509_san_dns';
|
|
@@ -82,361 +72,170 @@ let OpenId4VcSiopVerifierService = class OpenId4VcSiopVerifierService {
|
|
|
82
72
|
throw new core_1.CredoError(`With jwtIssuer 'method' 'x5c' the jwtIssuer's 'issuer' field must either match the match a sanDnsName (FQDN) or sanUriName in the leaf x509 chain's leaf certificate.`);
|
|
83
73
|
}
|
|
84
74
|
}
|
|
85
|
-
else if (jwtIssuer
|
|
75
|
+
else if (jwtIssuer.method === 'did') {
|
|
86
76
|
clientId = jwtIssuer.didUrl.split('#')[0];
|
|
87
77
|
clientIdScheme = 'did';
|
|
88
78
|
}
|
|
89
79
|
else {
|
|
90
80
|
throw new core_1.CredoError(`Unsupported jwt issuer method '${options.requestSigner.method}'. Only 'did' and 'x5c' are supported.`);
|
|
91
81
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
? (0, core_1.joinUriParts)(this.config.baseUrl, [
|
|
95
|
-
options.verifier.verifierId,
|
|
96
|
-
this.config.authorizationRequestEndpoint.endpointPath,
|
|
97
|
-
// It doesn't really matter what the url is, as long as it's unique
|
|
98
|
-
core_1.utils.uuid(),
|
|
99
|
-
])
|
|
100
|
-
: // No hosted request needed when using DC API
|
|
101
|
-
undefined;
|
|
102
|
-
const client_id = clientIdScheme === 'did' || clientIdScheme === 'https' ? clientId : `${clientIdScheme}:${clientId}`;
|
|
103
|
-
const client_metadata = await this.getClientMetadata(agentContext, {
|
|
104
|
-
responseMode,
|
|
105
|
-
verifier: options.verifier,
|
|
82
|
+
const relyingParty = await this.getRelyingParty(agentContext, options.verifier, {
|
|
83
|
+
presentationDefinition: options.presentationExchange?.definition,
|
|
106
84
|
authorizationResponseUrl,
|
|
85
|
+
clientId,
|
|
86
|
+
clientIdScheme,
|
|
87
|
+
responseMode: options.responseMode,
|
|
107
88
|
});
|
|
108
|
-
|
|
89
|
+
// We always use shortened URIs currently
|
|
90
|
+
const hostedAuthorizationRequestUri = (0, core_1.joinUriParts)(this.config.baseUrl, [
|
|
91
|
+
options.verifier.verifierId,
|
|
92
|
+
this.config.authorizationRequestEndpoint.endpointPath,
|
|
93
|
+
// It doesn't really matter what the url is, as long as it's unique
|
|
94
|
+
core_1.utils.uuid(),
|
|
95
|
+
]);
|
|
96
|
+
// This is very unfortunate, but storing state in sphereon's SiOP-OID4VP library
|
|
97
|
+
// is done async, so we can't be certain yet that the verification session record
|
|
98
|
+
// is created already when we have created the authorization request. So we need to
|
|
99
|
+
// wait for a short while before we can be certain that the verification session record
|
|
100
|
+
// is created. To not use arbitrary timeouts, we wait for the specific RecordSavedEvent
|
|
101
|
+
// that is emitted when the verification session record is created.
|
|
102
|
+
const eventEmitter = agentContext.dependencyManager.resolve(core_1.EventEmitter);
|
|
103
|
+
const verificationSessionCreatedPromise = (0, rxjs_1.firstValueFrom)(eventEmitter
|
|
104
|
+
.observable(core_1.RepositoryEventTypes.RecordSaved)
|
|
105
|
+
.pipe((0, rxjs_1.filter)((e) => e.metadata.contextCorrelationId === agentContext.contextCorrelationId), (0, rxjs_1.filter)((e) => e.payload.record.id === correlationId && e.payload.record.verifierId === options.verifier.verifierId), (0, rxjs_1.first)(), (0, rxjs_1.timeout)({
|
|
106
|
+
first: 10000,
|
|
107
|
+
meta: 'OpenId4VcSiopVerifierService.createAuthorizationRequest',
|
|
108
|
+
}), (0, rxjs_1.map)((e) => e.payload.record)));
|
|
109
|
+
const authorizationRequest = await relyingParty.createAuthorizationRequest({
|
|
110
|
+
correlationId,
|
|
109
111
|
nonce,
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
response_mode: responseMode,
|
|
114
|
-
response_type: 'vp_token',
|
|
115
|
-
client_metadata,
|
|
116
|
-
};
|
|
117
|
-
const authorizationRequestPayload = requestParamsBase.response_mode === 'dc_api.jwt' || requestParamsBase.response_mode === 'dc_api'
|
|
118
|
-
? {
|
|
119
|
-
...requestParamsBase,
|
|
120
|
-
// No client_id for unsigned requests
|
|
121
|
-
client_id: jwtIssuer ? client_id : undefined,
|
|
122
|
-
response_mode: requestParamsBase.response_mode,
|
|
123
|
-
expected_origins: options.expectedOrigins,
|
|
124
|
-
}
|
|
125
|
-
: {
|
|
126
|
-
...requestParamsBase,
|
|
127
|
-
client_id: client_id,
|
|
128
|
-
state,
|
|
129
|
-
response_uri: authorizationResponseUrl,
|
|
130
|
-
};
|
|
131
|
-
const openid4vpVerifier = this.getOpenid4vpVerifier(agentContext);
|
|
132
|
-
const authorizationRequest = await openid4vpVerifier.createOpenId4vpAuthorizationRequest({
|
|
133
|
-
jar: jwtIssuer
|
|
134
|
-
? {
|
|
135
|
-
jwtSigner: jwtIssuer,
|
|
136
|
-
// FIXME: cast can be removed when PR 41 is merged in oid4vc-ts
|
|
137
|
-
requestUri: hostedAuthorizationRequestUri,
|
|
138
|
-
}
|
|
139
|
-
: undefined,
|
|
140
|
-
requestParams: authorizationRequestPayload,
|
|
141
|
-
});
|
|
142
|
-
const verificationSession = new repository_1.OpenId4VcVerificationSessionRecord({
|
|
143
|
-
// Only store payload for unsiged requests
|
|
144
|
-
authorizationRequestPayload: authorizationRequest.jar ? undefined : authorizationRequestPayload,
|
|
145
|
-
authorizationRequestJwt: authorizationRequest.jar?.requestObjectJwt,
|
|
146
|
-
authorizationRequestUri: authorizationRequest.jar?.requestUri,
|
|
147
|
-
state: OpenId4VcVerificationSessionState_1.OpenId4VcVerificationSessionState.RequestCreated,
|
|
148
|
-
verifierId: options.verifier.verifierId,
|
|
112
|
+
state,
|
|
113
|
+
requestByReferenceURI: hostedAuthorizationRequestUri,
|
|
114
|
+
jwtIssuer,
|
|
149
115
|
});
|
|
150
|
-
|
|
151
|
-
this.
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
authorizationRequestObject: authorizationRequest.authRequestObject,
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
getDcqlVerifiedResponse(agentContext, _dcqlQuery, presentation) {
|
|
159
|
-
const dcqlService = agentContext.dependencyManager.resolve(core_1.DcqlService);
|
|
160
|
-
const dcqlQuery = dcqlService.validateDcqlQuery(_dcqlQuery);
|
|
161
|
-
const dcqlPresentationEntries = Object.entries(presentation);
|
|
162
|
-
const dcqlPresentation = Object.fromEntries(dcqlPresentationEntries.map((presentation) => {
|
|
163
|
-
const [credentialId, vpTokenPresentationParseResult] = presentation;
|
|
164
|
-
return [credentialId, this.decodePresentation(agentContext, { vpTokenPresentationParseResult })];
|
|
165
|
-
}));
|
|
166
|
-
const dcqlPresentationResult = dcqlService.assertValidDcqlPresentation(dcqlPresentation, dcqlQuery);
|
|
167
|
-
return {
|
|
168
|
-
query: dcqlQuery,
|
|
169
|
-
presentation: dcqlPresentation,
|
|
170
|
-
presentationResult: dcqlPresentationResult,
|
|
171
|
-
};
|
|
172
|
-
}
|
|
173
|
-
async parseAuthorizationResponse(agentContext, options) {
|
|
174
|
-
const { verifierId, responsePayload } = options;
|
|
175
|
-
if (!options.verificationSession && !options.verifierId) {
|
|
176
|
-
throw new core_1.CredoError('Either verificationSession or verifierId needs to be provided');
|
|
177
|
-
}
|
|
178
|
-
let verificationSession = options.verificationSession;
|
|
179
|
-
let parsedAuthResponse;
|
|
180
|
-
let rawResponsePayload = responsePayload;
|
|
181
|
-
try {
|
|
182
|
-
parsedAuthResponse = await (0, openid4vp_1.parseOpenid4vpAuthorizationResponse)({
|
|
183
|
-
responsePayload,
|
|
184
|
-
callbacks: {
|
|
185
|
-
...(0, callbacks_1.getOid4vcCallbacks)(agentContext),
|
|
186
|
-
getOpenid4vpAuthorizationRequest: async (responsePayload) => {
|
|
187
|
-
if (!verificationSession) {
|
|
188
|
-
const { state, nonce } = responsePayload;
|
|
189
|
-
rawResponsePayload = responsePayload;
|
|
190
|
-
const session = await this.findVerificationSessionForAuthorizationResponse(agentContext, {
|
|
191
|
-
authorizationResponseParams: { state, nonce },
|
|
192
|
-
verifierId,
|
|
193
|
-
});
|
|
194
|
-
if (!session) {
|
|
195
|
-
agentContext.config.logger.warn(`No verification session found for incoming authorization response for verifier ${verifierId}`);
|
|
196
|
-
throw new core_1.CredoError(`No state or nonce provided in authorization response for verifier ${verifierId}`);
|
|
197
|
-
}
|
|
198
|
-
verificationSession = session;
|
|
199
|
-
}
|
|
200
|
-
const authorizationRequest = (0, openid4vp_1.parseOpenid4vpAuthorizationRequestPayload)({
|
|
201
|
-
authorizationRequest: verificationSession.request,
|
|
202
|
-
});
|
|
203
|
-
if (authorizationRequest.type !== 'openid4vp' && authorizationRequest.type !== 'openid4vp_dc_api') {
|
|
204
|
-
throw new core_1.CredoError(`Invalid authorization request jwt. Expected 'openid4vp' or 'openid4vp_dc_api' request, received '${authorizationRequest.type}'.`);
|
|
205
|
-
}
|
|
206
|
-
if (authorizationRequest.params.client_id) {
|
|
207
|
-
return {
|
|
208
|
-
authorizationRequest: {
|
|
209
|
-
...authorizationRequest.params,
|
|
210
|
-
client_id: authorizationRequest.params.client_id,
|
|
211
|
-
},
|
|
212
|
-
};
|
|
213
|
-
}
|
|
214
|
-
if (!options.origin) {
|
|
215
|
-
throw new core_1.CredoError('Origin must be provided when client id is not set.');
|
|
216
|
-
}
|
|
217
|
-
return {
|
|
218
|
-
authorizationRequest: {
|
|
219
|
-
...authorizationRequest.params,
|
|
220
|
-
client_id: authorizationRequest.params.client_id ?? `web-origin:${options.origin}`,
|
|
221
|
-
},
|
|
222
|
-
};
|
|
223
|
-
},
|
|
224
|
-
},
|
|
225
|
-
});
|
|
226
|
-
}
|
|
227
|
-
catch (error) {
|
|
228
|
-
if (verificationSession?.state === OpenId4VcVerificationSessionState_1.OpenId4VcVerificationSessionState.RequestUriRetrieved ||
|
|
229
|
-
verificationSession?.state === OpenId4VcVerificationSessionState_1.OpenId4VcVerificationSessionState.RequestCreated) {
|
|
230
|
-
const parsed = openid4vp_1.zOpenid4vpAuthorizationResponse.safeParse(rawResponsePayload);
|
|
231
|
-
verificationSession.authorizationResponsePayload = parsed.success ? parsed.data : undefined;
|
|
232
|
-
verificationSession.errorMessage = error.message;
|
|
233
|
-
await this.updateState(agentContext, verificationSession, OpenId4VcVerificationSessionState_1.OpenId4VcVerificationSessionState.Error);
|
|
234
|
-
}
|
|
235
|
-
throw error;
|
|
116
|
+
// NOTE: it's not possible to set the uri scheme when using the RP to create an auth request, only lower level
|
|
117
|
+
// functions allow this. So we need to replace the uri scheme manually.
|
|
118
|
+
let authorizationRequestUri = (await authorizationRequest.uri()).encodedUri;
|
|
119
|
+
if (options.presentationExchange && !options.idToken) {
|
|
120
|
+
authorizationRequestUri = authorizationRequestUri.replace('openid://', 'openid4vp://');
|
|
236
121
|
}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
const decoded = decodeURIComponent(parsedAuthResponse.authResponsePayload.presentation_submission);
|
|
240
|
-
const parsed = JSON.parse(decoded);
|
|
241
|
-
parsedAuthResponse.authResponsePayload.presentation_submission = parsed;
|
|
242
|
-
if (parsedAuthResponse.type === 'pex') {
|
|
243
|
-
parsedAuthResponse.pex.presentationSubmission = parsed;
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
if (!verificationSession) {
|
|
247
|
-
throw new core_1.CredoError('Missing verification session, cannot verify authorization response.');
|
|
248
|
-
}
|
|
249
|
-
// FIXME: export JarmMode from openid4vp
|
|
250
|
-
if (parsedAuthResponse.jarm && `${parsedAuthResponse.jarm.type}` !== 'Encrypted') {
|
|
251
|
-
throw new oauth2_1.Oauth2ServerErrorResponseError({
|
|
252
|
-
error: oauth2_1.Oauth2ErrorCodes.InvalidRequest,
|
|
253
|
-
error_description: `Only encrypted JARM responses are supported, received '${parsedAuthResponse.jarm.type}'.`,
|
|
254
|
-
});
|
|
122
|
+
else {
|
|
123
|
+
authorizationRequestUri = authorizationRequestUri.replace('openid4vp://', 'openid://');
|
|
255
124
|
}
|
|
125
|
+
const verificationSession = await verificationSessionCreatedPromise;
|
|
256
126
|
return {
|
|
257
|
-
|
|
127
|
+
authorizationRequest: authorizationRequestUri,
|
|
258
128
|
verificationSession,
|
|
259
129
|
};
|
|
260
130
|
}
|
|
261
131
|
async verifyAuthorizationResponse(agentContext, options) {
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
verifierId: options.verifierId,
|
|
265
|
-
verificationSession: options.verificationSession,
|
|
266
|
-
responsePayload: options.authorizationResponse,
|
|
267
|
-
origin: options.origin,
|
|
268
|
-
});
|
|
269
|
-
result.verificationSession.assertState([
|
|
132
|
+
// Assert state
|
|
133
|
+
options.verificationSession.assertState([
|
|
270
134
|
OpenId4VcVerificationSessionState_1.OpenId4VcVerificationSessionState.RequestUriRetrieved,
|
|
271
135
|
OpenId4VcVerificationSessionState_1.OpenId4VcVerificationSessionState.RequestCreated,
|
|
272
136
|
]);
|
|
273
|
-
const authorizationRequest =
|
|
274
|
-
|
|
275
|
-
const
|
|
276
|
-
const
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
const
|
|
280
|
-
if (
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
//
|
|
293
|
-
//
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
pex.validatePresentationDefinition(result.pex.presentationDefinition);
|
|
318
|
-
pex.validatePresentationSubmission(result.pex.presentationSubmission);
|
|
319
|
-
const presentationsArray = Array.isArray(presentations) ? presentations : [presentations];
|
|
320
|
-
const presentationVerificationPromises = presentationsArray.map((presentation) => {
|
|
321
|
-
const inputDescriptor = result.pex.presentationSubmission.descriptor_map.find((descriptorMapEntry) => descriptorMapEntry.path === presentation.path);
|
|
322
|
-
if (!inputDescriptor) {
|
|
323
|
-
throw new core_1.CredoError(`Could not map transaction data entry to input descriptor.`);
|
|
324
|
-
}
|
|
325
|
-
return this.verifyPresentations(agentContext, {
|
|
326
|
-
correlationId: result.verificationSession.id,
|
|
327
|
-
transactionData,
|
|
328
|
-
nonce: authorizationRequest.nonce,
|
|
137
|
+
const authorizationRequest = await did_auth_siop_1.AuthorizationRequest.fromUriOrJwt(options.verificationSession.authorizationRequestJwt);
|
|
138
|
+
const verifier = await this.getVerifierByVerifierId(agentContext, options.verificationSession.verifierId);
|
|
139
|
+
const requestClientId = await authorizationRequest.getMergedProperty('client_id');
|
|
140
|
+
const requestNonce = await authorizationRequest.getMergedProperty('nonce');
|
|
141
|
+
const requestState = await authorizationRequest.getMergedProperty('state');
|
|
142
|
+
const responseUri = await authorizationRequest.getMergedProperty('response_uri');
|
|
143
|
+
const presentationDefinitionsWithLocation = await authorizationRequest.getPresentationDefinitions();
|
|
144
|
+
if (!requestNonce || !requestClientId || !requestState) {
|
|
145
|
+
throw new core_1.CredoError(`Unable to find nonce, state, or client_id in authorization request for verification session '${options.verificationSession.id}'`);
|
|
146
|
+
}
|
|
147
|
+
const authorizationResponseUrl = (0, core_1.joinUriParts)(this.config.baseUrl, [
|
|
148
|
+
options.verificationSession.verifierId,
|
|
149
|
+
this.config.authorizationEndpoint.endpointPath,
|
|
150
|
+
]);
|
|
151
|
+
const relyingParty = await this.getRelyingParty(agentContext, verifier, {
|
|
152
|
+
presentationDefinition: presentationDefinitionsWithLocation?.[0]?.definition,
|
|
153
|
+
authorizationResponseUrl,
|
|
154
|
+
clientId: requestClientId,
|
|
155
|
+
});
|
|
156
|
+
// This is very unfortunate, but storing state in sphereon's SiOP-OID4VP library
|
|
157
|
+
// is done async, so we can't be certain yet that the verification session record
|
|
158
|
+
// is updated already when we have verified the authorization response. So we need to
|
|
159
|
+
// wait for a short while before we can be certain that the verification session record
|
|
160
|
+
// is updated. To not use arbitrary timeouts, we wait for the specific RecordUpdatedEvent
|
|
161
|
+
// that is emitted when the verification session record is updated.
|
|
162
|
+
const eventEmitter = agentContext.dependencyManager.resolve(core_1.EventEmitter);
|
|
163
|
+
const verificationSessionUpdatedPromise = (0, rxjs_1.firstValueFrom)(eventEmitter
|
|
164
|
+
.observable(core_1.RepositoryEventTypes.RecordUpdated)
|
|
165
|
+
.pipe((0, rxjs_1.filter)((e) => e.metadata.contextCorrelationId === agentContext.contextCorrelationId), (0, rxjs_1.filter)((e) => e.payload.record.id === options.verificationSession.id &&
|
|
166
|
+
e.payload.record.verifierId === options.verificationSession.verifierId &&
|
|
167
|
+
(e.payload.record.state === OpenId4VcVerificationSessionState_1.OpenId4VcVerificationSessionState.ResponseVerified ||
|
|
168
|
+
e.payload.record.state === OpenId4VcVerificationSessionState_1.OpenId4VcVerificationSessionState.Error)), (0, rxjs_1.first)(), (0, rxjs_1.timeout)({
|
|
169
|
+
first: 10000,
|
|
170
|
+
meta: 'OpenId4VcSiopVerifierService.verifyAuthorizationResponse',
|
|
171
|
+
}), (0, rxjs_1.map)((e) => e.payload.record)));
|
|
172
|
+
await relyingParty.verifyAuthorizationResponse(options.authorizationResponse, {
|
|
173
|
+
audience: requestClientId,
|
|
174
|
+
correlationId: options.verificationSession.id,
|
|
175
|
+
state: requestState,
|
|
176
|
+
presentationDefinitions: presentationDefinitionsWithLocation,
|
|
177
|
+
verification: {
|
|
178
|
+
presentationVerificationCallback: this.getPresentationVerificationCallback(agentContext, {
|
|
179
|
+
correlationId: options.verificationSession.id,
|
|
180
|
+
nonce: requestNonce,
|
|
329
181
|
audience: requestClientId,
|
|
330
182
|
responseUri,
|
|
331
|
-
mdocGeneratedNonce:
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
})
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
throw new core_1.CredoError(`One or more presentations failed verification. \n\t${errorMessages.join('\n')}`);
|
|
345
|
-
}
|
|
346
|
-
// Validate the presentations against the query
|
|
347
|
-
if (result.type === 'pex') {
|
|
348
|
-
const pex = agentContext.dependencyManager.resolve(core_1.DifPresentationExchangeService);
|
|
349
|
-
const presentations = presentationVerificationResults
|
|
350
|
-
.map((p) => (p.verified ? p.presentation : undefined))
|
|
351
|
-
.filter((p) => p !== undefined);
|
|
352
|
-
pex.validatePresentation(
|
|
353
|
-
// FIXME: type. it should always be an object as we created it
|
|
354
|
-
result.pex.presentationDefinition, presentations, result.pex.presentationSubmission);
|
|
355
|
-
}
|
|
356
|
-
else {
|
|
357
|
-
const dcql = agentContext.dependencyManager.resolve(core_1.DcqlService);
|
|
358
|
-
const presentations = presentationVerificationResults.reduce((all, p) => (p.verified ? { ...all, [p.credentialId]: p.presentation } : all), {});
|
|
359
|
-
// FIXME: type for this parameter
|
|
360
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
361
|
-
dcql.assertValidDcqlPresentation(presentations, result.dcql.query);
|
|
362
|
-
}
|
|
363
|
-
const transactionDataMeta = [];
|
|
364
|
-
for (const result of presentationVerificationResults) {
|
|
365
|
-
if (result.verified && result.transactionDataMeta) {
|
|
366
|
-
transactionDataMeta.push([result.transactionDataMeta.credentialId, result.transactionDataMeta]);
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
if (transactionData) {
|
|
370
|
-
const inputDescriptorToTransactionDataMeta = Object.fromEntries(transactionDataMeta);
|
|
371
|
-
if (!transactionData.every((tdEntry) => {
|
|
372
|
-
return tdEntry.credential_ids.some((credentialId) => inputDescriptorToTransactionDataMeta[credentialId]);
|
|
373
|
-
})) {
|
|
374
|
-
throw new core_1.CredoError('One ore more required transaction data entries were not found in the signed transaction data.');
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
catch (error) {
|
|
379
|
-
result.verificationSession.errorMessage = error.message;
|
|
380
|
-
await this.updateState(agentContext, result.verificationSession, OpenId4VcVerificationSessionState_1.OpenId4VcVerificationSessionState.Error);
|
|
381
|
-
throw error;
|
|
382
|
-
}
|
|
383
|
-
result.verificationSession.authorizationResponsePayload = result.authResponsePayload;
|
|
384
|
-
await this.updateState(agentContext, result.verificationSession, OpenId4VcVerificationSessionState_1.OpenId4VcVerificationSessionState.ResponseVerified);
|
|
385
|
-
const verifiedAuthorizationResponse = await this.getVerifiedAuthorizationResponse(agentContext, result.verificationSession);
|
|
386
|
-
return { ...verifiedAuthorizationResponse, verificationSession: result.verificationSession };
|
|
183
|
+
mdocGeneratedNonce: options.jarmHeader?.apu
|
|
184
|
+
? core_1.TypedArrayEncoder.toUtf8String(core_1.TypedArrayEncoder.fromBase64(options.jarmHeader.apu))
|
|
185
|
+
: undefined,
|
|
186
|
+
verificationSessionRecordId: options.verificationSession.id,
|
|
187
|
+
}),
|
|
188
|
+
},
|
|
189
|
+
});
|
|
190
|
+
const verificationSession = await verificationSessionUpdatedPromise;
|
|
191
|
+
const verifiedAuthorizationResponse = await this.getVerifiedAuthorizationResponse(verificationSession);
|
|
192
|
+
return {
|
|
193
|
+
...verifiedAuthorizationResponse,
|
|
194
|
+
verificationSession: await verificationSessionUpdatedPromise,
|
|
195
|
+
};
|
|
387
196
|
}
|
|
388
|
-
async getVerifiedAuthorizationResponse(
|
|
197
|
+
async getVerifiedAuthorizationResponse(verificationSession) {
|
|
389
198
|
verificationSession.assertState(OpenId4VcVerificationSessionState_1.OpenId4VcVerificationSessionState.ResponseVerified);
|
|
390
199
|
if (!verificationSession.authorizationResponsePayload) {
|
|
391
200
|
throw new core_1.CredoError('No authorization response payload found in the verification session.');
|
|
392
201
|
}
|
|
393
|
-
const
|
|
394
|
-
const
|
|
395
|
-
const
|
|
396
|
-
|
|
397
|
-
});
|
|
398
|
-
if ((authorizationRequest.provided !== 'jwt' && authorizationRequest.provided !== 'params') ||
|
|
399
|
-
authorizationRequest.type === 'jar') {
|
|
400
|
-
throw new core_1.CredoError('Invalid authorization request');
|
|
401
|
-
}
|
|
402
|
-
const result = openid4vpVerifier.validateOpenid4vpAuthorizationResponse({
|
|
403
|
-
authorizationRequest: authorizationRequest.params,
|
|
404
|
-
authorizationResponse: openid4vpAuthorizationResponsePayload,
|
|
405
|
-
});
|
|
406
|
-
const transactionData = authorizationRequest.params.transaction_data
|
|
407
|
-
? openid4vpVerifier.parseTransactionData({ transactionData: authorizationRequest.params.transaction_data })
|
|
202
|
+
const authorizationResponse = await did_auth_siop_1.AuthorizationResponse.fromPayload(verificationSession.authorizationResponsePayload);
|
|
203
|
+
const authorizationRequest = await did_auth_siop_1.AuthorizationRequest.fromUriOrJwt(verificationSession.authorizationRequestJwt);
|
|
204
|
+
const idToken = authorizationResponse.idToken
|
|
205
|
+
? { payload: await authorizationResponse.idToken?.payload() }
|
|
408
206
|
: undefined;
|
|
409
207
|
let presentationExchange = undefined;
|
|
410
|
-
const
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
}
|
|
420
|
-
const rawPresentations = openid4vpVerifier.parsePresentationsFromVpToken({ vpToken });
|
|
421
|
-
const submission = openid4vpAuthorizationResponsePayload.presentation_submission;
|
|
208
|
+
const presentationDefinitions = await authorizationRequest.getPresentationDefinitions();
|
|
209
|
+
if (presentationDefinitions && presentationDefinitions.length > 0) {
|
|
210
|
+
const rawPresentations = authorizationResponse.payload.vp_token
|
|
211
|
+
? await (0, OpenID4VP_1.extractPresentationsFromVpToken)(authorizationResponse.payload.vp_token, {
|
|
212
|
+
hasher: core_1.Hasher.hash,
|
|
213
|
+
})
|
|
214
|
+
: [];
|
|
215
|
+
// TODO: Probably wise to check against request for the location of the submission_data
|
|
216
|
+
const submission = idToken?.payload?._vp_token?.presentation_submission ?? authorizationResponse.payload.presentation_submission;
|
|
422
217
|
if (!submission) {
|
|
423
218
|
throw new core_1.CredoError('Unable to extract submission from the response.');
|
|
424
219
|
}
|
|
425
|
-
|
|
220
|
+
// FIXME: should return type be an array? As now it doesn't always match the submission
|
|
221
|
+
const verifiablePresentations = Array.isArray(rawPresentations)
|
|
222
|
+
? rawPresentations.map(transform_1.getVerifiablePresentationFromSphereonWrapped)
|
|
223
|
+
: (0, transform_1.getVerifiablePresentationFromSphereonWrapped)(rawPresentations);
|
|
224
|
+
const definition = presentationDefinitions[0].definition;
|
|
426
225
|
presentationExchange = {
|
|
427
|
-
definition
|
|
226
|
+
definition,
|
|
428
227
|
submission,
|
|
429
|
-
|
|
430
|
-
|
|
228
|
+
// We always return this as an array
|
|
229
|
+
presentations: Array.isArray(verifiablePresentations) ? verifiablePresentations : [verifiablePresentations],
|
|
230
|
+
descriptors: (0, core_1.extractPresentationsWithDescriptorsFromSubmission)(verifiablePresentations, submission, definition),
|
|
431
231
|
};
|
|
432
232
|
}
|
|
433
|
-
if (!
|
|
434
|
-
throw new core_1.CredoError('No
|
|
233
|
+
if (!idToken && !presentationExchange) {
|
|
234
|
+
throw new core_1.CredoError('No idToken or presentationExchange found in the response.');
|
|
435
235
|
}
|
|
436
236
|
return {
|
|
237
|
+
idToken,
|
|
437
238
|
presentationExchange,
|
|
438
|
-
dcql,
|
|
439
|
-
transactionData,
|
|
440
239
|
};
|
|
441
240
|
}
|
|
442
241
|
/**
|
|
@@ -447,13 +246,21 @@ let OpenId4VcSiopVerifierService = class OpenId4VcSiopVerifierService {
|
|
|
447
246
|
let nonce;
|
|
448
247
|
let state;
|
|
449
248
|
if (authorizationResponse) {
|
|
450
|
-
const
|
|
451
|
-
|
|
249
|
+
const authorizationResponseInstance = await did_auth_siop_1.AuthorizationResponse.fromPayload(authorizationResponse).catch(() => {
|
|
250
|
+
throw new core_1.CredoError(`Unable to parse authorization response payload. ${JSON.stringify(authorizationResponse)}`);
|
|
251
|
+
});
|
|
252
|
+
nonce = await authorizationResponseInstance.getMergedProperty('nonce', {
|
|
253
|
+
hasher: core_1.Hasher.hash,
|
|
254
|
+
});
|
|
255
|
+
state = await authorizationResponseInstance.getMergedProperty('state', {
|
|
256
|
+
hasher: core_1.Hasher.hash,
|
|
257
|
+
});
|
|
258
|
+
if (!nonce && !state) {
|
|
452
259
|
throw new core_1.CredoError('Could not extract nonce or state from authorization response. Unable to find OpenId4VcVerificationSession.');
|
|
453
260
|
}
|
|
454
261
|
}
|
|
455
262
|
else {
|
|
456
|
-
if (
|
|
263
|
+
if (authorizationResponseParams?.nonce && !authorizationResponseParams?.state) {
|
|
457
264
|
throw new core_1.CredoError('Either nonce or state must be provided if no authorization response is provided. Unable to find OpenId4VcVerificationSession.');
|
|
458
265
|
}
|
|
459
266
|
nonce = authorizationResponseParams?.nonce;
|
|
@@ -490,18 +297,37 @@ let OpenId4VcSiopVerifierService = class OpenId4VcSiopVerifierService {
|
|
|
490
297
|
async getVerificationSessionById(agentContext, verificationSessionId) {
|
|
491
298
|
return this.openId4VcVerificationSessionRepository.getById(agentContext, verificationSessionId);
|
|
492
299
|
}
|
|
493
|
-
async
|
|
494
|
-
const { responseMode, verifier } = options;
|
|
300
|
+
async getRelyingParty(agentContext, verifier, { idToken, presentationDefinition, clientId, clientIdScheme, authorizationResponseUrl, responseMode, }) {
|
|
495
301
|
const signatureSuiteRegistry = agentContext.dependencyManager.resolve(core_1.SignatureSuiteRegistry);
|
|
496
302
|
const supportedAlgs = (0, utils_1.getSupportedJwaSignatureAlgorithms)(agentContext);
|
|
497
303
|
const supportedMdocAlgs = supportedAlgs.filter(core_1.isMdocSupportedSignatureAlgorithm);
|
|
498
304
|
const supportedProofTypes = signatureSuiteRegistry.supportedProofTypes;
|
|
305
|
+
// Check: audience must be set to the issuer with dynamic disc otherwise self-issued.me/v2.
|
|
306
|
+
const builder = did_auth_siop_1.RP.builder();
|
|
307
|
+
const responseTypes = [];
|
|
308
|
+
if (!presentationDefinition && idToken === false) {
|
|
309
|
+
throw new core_1.CredoError('Either `presentationExchange` or `idToken` must be enabled');
|
|
310
|
+
}
|
|
311
|
+
if (presentationDefinition) {
|
|
312
|
+
responseTypes.push(did_auth_siop_1.ResponseType.VP_TOKEN);
|
|
313
|
+
}
|
|
314
|
+
if (idToken === true || !presentationDefinition) {
|
|
315
|
+
responseTypes.push(did_auth_siop_1.ResponseType.ID_TOKEN);
|
|
316
|
+
}
|
|
499
317
|
// FIXME: we now manually remove did:peer, we should probably allow the user to configure this
|
|
500
318
|
const supportedDidMethods = agentContext.dependencyManager
|
|
501
319
|
.resolve(core_1.DidsApi)
|
|
502
320
|
.supportedResolverMethods.filter((m) => m !== 'peer');
|
|
321
|
+
// The OpenId4VcRelyingPartyEventHandler is a global event handler that makes sure that
|
|
322
|
+
// all the events are handled, and that the correct context is used for the events.
|
|
323
|
+
const sphereonEventEmitter = agentContext.dependencyManager
|
|
324
|
+
.resolve(OpenId4VcRelyingPartyEventEmitter_1.OpenId4VcRelyingPartyEventHandler)
|
|
325
|
+
.getEventEmitterForVerifier(agentContext.contextCorrelationId, verifier.verifierId);
|
|
326
|
+
const mode = !responseMode || responseMode === 'direct_post'
|
|
327
|
+
? did_auth_siop_1.ResponseMode.DIRECT_POST
|
|
328
|
+
: did_auth_siop_1.ResponseMode.DIRECT_POST_JWT;
|
|
503
329
|
let jarmEncryptionJwk;
|
|
504
|
-
if (
|
|
330
|
+
if (mode === did_auth_siop_1.ResponseMode.DIRECT_POST_JWT) {
|
|
505
331
|
const key = await agentContext.wallet.createKey({ keyType: core_1.KeyType.P256 });
|
|
506
332
|
jarmEncryptionJwk = { ...(0, core_1.getJwkFromKey)(key).toJson(), kid: key.fingerprint, use: 'enc' };
|
|
507
333
|
}
|
|
@@ -509,20 +335,44 @@ let OpenId4VcSiopVerifierService = class OpenId4VcSiopVerifierService {
|
|
|
509
335
|
? {
|
|
510
336
|
jwks: { keys: [jarmEncryptionJwk] },
|
|
511
337
|
authorization_encrypted_response_alg: 'ECDH-ES',
|
|
512
|
-
|
|
513
|
-
// `request_uri_method`
|
|
514
|
-
authorization_encrypted_response_enc: 'A128GCM',
|
|
338
|
+
authorization_encrypted_response_enc: 'A256GCM',
|
|
515
339
|
}
|
|
516
340
|
: undefined;
|
|
517
|
-
|
|
341
|
+
builder
|
|
342
|
+
.withClientId(clientId)
|
|
343
|
+
.withResponseUri(authorizationResponseUrl)
|
|
344
|
+
.withIssuer(did_auth_siop_1.ResponseIss.SELF_ISSUED_V2)
|
|
345
|
+
.withAudience(did_auth_siop_1.RequestAud.SELF_ISSUED_V2)
|
|
346
|
+
.withIssuer(did_auth_siop_1.ResponseIss.SELF_ISSUED_V2)
|
|
347
|
+
.withSupportedVersions([
|
|
348
|
+
did_auth_siop_1.SupportedVersion.SIOPv2_D11,
|
|
349
|
+
did_auth_siop_1.SupportedVersion.SIOPv2_D12_OID4VP_D18,
|
|
350
|
+
did_auth_siop_1.SupportedVersion.SIOPv2_D12_OID4VP_D20,
|
|
351
|
+
])
|
|
352
|
+
.withResponseMode(mode)
|
|
353
|
+
.withHasher(core_1.Hasher.hash)
|
|
354
|
+
// FIXME: should allow verification of revocation
|
|
355
|
+
// .withRevocationVerificationCallback()
|
|
356
|
+
.withRevocationVerification(did_auth_siop_1.RevocationVerification.NEVER)
|
|
357
|
+
.withSessionManager(new OpenId4VcRelyingPartySessionManager_1.OpenId4VcRelyingPartySessionManager(agentContext, verifier.verifierId))
|
|
358
|
+
.withEventEmitter(sphereonEventEmitter)
|
|
359
|
+
.withResponseType(responseTypes)
|
|
360
|
+
.withCreateJwtCallback((0, utils_1.getCreateJwtCallback)(agentContext))
|
|
361
|
+
.withVerifyJwtCallback((0, utils_1.getVerifyJwtCallback)(agentContext))
|
|
362
|
+
// TODO: we should probably allow some dynamic values here
|
|
363
|
+
.withClientMetadata({
|
|
518
364
|
...jarmClientMetadata,
|
|
519
365
|
...verifier.clientMetadata,
|
|
520
|
-
|
|
366
|
+
// FIXME: not passing client_id here means it will not be added
|
|
367
|
+
// to the authorization request url (not the signed payload). Need
|
|
368
|
+
// to fix that in Sphereon lib
|
|
369
|
+
client_id: clientId,
|
|
370
|
+
passBy: did_auth_siop_1.PassBy.VALUE,
|
|
371
|
+
response_types_supported: [did_auth_siop_1.ResponseType.VP_TOKEN],
|
|
521
372
|
subject_syntax_types_supported: [
|
|
522
373
|
'urn:ietf:params:oauth:jwk-thumbprint',
|
|
523
374
|
...supportedDidMethods.map((m) => `did:${m}`),
|
|
524
375
|
],
|
|
525
|
-
authorization_signed_response_alg: 'RS256',
|
|
526
376
|
vp_formats: {
|
|
527
377
|
mso_mdoc: {
|
|
528
378
|
alg: supportedMdocAlgs,
|
|
@@ -549,249 +399,146 @@ let OpenId4VcSiopVerifierService = class OpenId4VcSiopVerifierService {
|
|
|
549
399
|
'kb-jwt_alg_values': supportedAlgs,
|
|
550
400
|
'sd-jwt_alg_values': supportedAlgs,
|
|
551
401
|
},
|
|
552
|
-
'dc+sd-jwt': {
|
|
553
|
-
'kb-jwt_alg_values': supportedAlgs,
|
|
554
|
-
'sd-jwt_alg_values': supportedAlgs,
|
|
555
|
-
},
|
|
556
402
|
},
|
|
557
|
-
};
|
|
558
|
-
}
|
|
559
|
-
getPresentationFromVpTokenParseResult(agentContext, vpTokenPresentationParseResult) {
|
|
560
|
-
if (vpTokenPresentationParseResult.format === 'dc+sd-jwt') {
|
|
561
|
-
const sdJwtVcApi = agentContext.dependencyManager.resolve(core_1.SdJwtVcApi);
|
|
562
|
-
return sdJwtVcApi.fromCompact(vpTokenPresentationParseResult.presentation);
|
|
563
|
-
}
|
|
564
|
-
else if (vpTokenPresentationParseResult.format === 'mso_mdoc') {
|
|
565
|
-
return core_1.MdocDeviceResponse.fromBase64Url(vpTokenPresentationParseResult.presentation);
|
|
566
|
-
}
|
|
567
|
-
else if (vpTokenPresentationParseResult.format === 'jwt_vp_json') {
|
|
568
|
-
return core_1.W3cJwtVerifiablePresentation.fromSerializedJwt(vpTokenPresentationParseResult.presentation);
|
|
569
|
-
}
|
|
570
|
-
else if (vpTokenPresentationParseResult.format === 'ldp_vp') {
|
|
571
|
-
return core_1.JsonTransformer.fromJSON(vpTokenPresentationParseResult.presentation, core_1.W3cJsonLdVerifiablePresentation);
|
|
572
|
-
}
|
|
573
|
-
throw new core_1.CredoError(`Unsupported presentation format. ${vpTokenPresentationParseResult.format}`);
|
|
574
|
-
}
|
|
575
|
-
getTransactionDataMeta(options) {
|
|
576
|
-
const { vpTokenPresentationParseResult, transactionData, transactionDataResult, credentialId } = options;
|
|
577
|
-
if (!transactionData) {
|
|
578
|
-
throw new core_1.CredoError('Could not map transaction data result to the request');
|
|
579
|
-
}
|
|
580
|
-
const hashName = transactionDataResult.hashes_alg ?? 'sha-256';
|
|
581
|
-
const presentationHashes = transactionDataResult.hashes;
|
|
582
|
-
const transactionDataEntriesWithHash = transactionData.map((tdEntry) => {
|
|
583
|
-
const hash = core_1.TypedArrayEncoder.toBase64URL(core_1.Hasher.hash(core_1.JsonEncoder.toBase64URL(tdEntry), hashName));
|
|
584
|
-
return hash;
|
|
585
403
|
});
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
throw new core_1.CredoError(`Transaction data entry ${idx} does not match hash ${hash}`);
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
return {
|
|
592
|
-
credentialId,
|
|
593
|
-
transactionData,
|
|
594
|
-
transactionDataResult,
|
|
595
|
-
path: vpTokenPresentationParseResult.path,
|
|
596
|
-
};
|
|
597
|
-
}
|
|
598
|
-
decodePresentation(agentContext, options) {
|
|
599
|
-
const { vpTokenPresentationParseResult } = options;
|
|
600
|
-
if (vpTokenPresentationParseResult.format === 'dc+sd-jwt') {
|
|
601
|
-
// TODO: it might be better here to look at the presentation submission to know
|
|
602
|
-
// If presentation includes a ~, we assume it's an SD-JWT-VC
|
|
603
|
-
const sdJwtVcApi = agentContext.dependencyManager.resolve(core_1.SdJwtVcApi);
|
|
604
|
-
const sdJwtVc = sdJwtVcApi.fromCompact(vpTokenPresentationParseResult.presentation);
|
|
605
|
-
return sdJwtVc;
|
|
404
|
+
if (clientIdScheme) {
|
|
405
|
+
builder.withClientIdScheme(clientIdScheme);
|
|
606
406
|
}
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
return mdocDeviceResponse;
|
|
407
|
+
if (presentationDefinition) {
|
|
408
|
+
builder.withPresentationDefinition({ definition: presentationDefinition }, [did_auth_siop_1.PropertyTarget.REQUEST_OBJECT]);
|
|
610
409
|
}
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
}
|
|
614
|
-
else {
|
|
615
|
-
return core_1.JsonTransformer.fromJSON(vpTokenPresentationParseResult.presentation, core_1.W3cJsonLdVerifiablePresentation);
|
|
410
|
+
if (responseTypes.includes(did_auth_siop_1.ResponseType.ID_TOKEN)) {
|
|
411
|
+
builder.withScope('openid');
|
|
616
412
|
}
|
|
413
|
+
return builder.build();
|
|
617
414
|
}
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
415
|
+
getPresentationVerificationCallback(agentContext, options) {
|
|
416
|
+
return async (encodedPresentation, presentationSubmission) => {
|
|
417
|
+
try {
|
|
418
|
+
this.logger.debug('Presentation response', core_1.JsonTransformer.toJSON(encodedPresentation));
|
|
419
|
+
this.logger.debug('Presentation submission', presentationSubmission);
|
|
420
|
+
if (!encodedPresentation)
|
|
421
|
+
throw new core_1.CredoError('Did not receive a presentation for verification.');
|
|
422
|
+
const x509Config = agentContext.dependencyManager.resolve(core_1.X509ModuleConfig);
|
|
423
|
+
let isValid;
|
|
424
|
+
let reason = undefined;
|
|
425
|
+
if (typeof encodedPresentation === 'string' && encodedPresentation.includes('~')) {
|
|
426
|
+
// TODO: it might be better here to look at the presentation submission to know
|
|
427
|
+
// If presentation includes a ~, we assume it's an SD-JWT-VC
|
|
428
|
+
const sdJwtVcApi = agentContext.dependencyManager.resolve(core_1.SdJwtVcApi);
|
|
429
|
+
const jwt = core_1.Jwt.fromSerializedJwt(encodedPresentation.split('~')[0]);
|
|
430
|
+
const sdJwtVc = sdJwtVcApi.fromCompact(encodedPresentation);
|
|
431
|
+
const certificateChain = (0, core_1.extractX509CertificatesFromJwt)(jwt);
|
|
432
|
+
let trustedCertificates = undefined;
|
|
433
|
+
if (certificateChain && x509Config.getTrustedCertificatesForVerification) {
|
|
434
|
+
trustedCertificates = await x509Config.getTrustedCertificatesForVerification(agentContext, {
|
|
435
|
+
certificateChain,
|
|
436
|
+
verification: {
|
|
437
|
+
type: 'credential',
|
|
438
|
+
credential: sdJwtVc,
|
|
439
|
+
openId4VcVerificationSessionId: options.verificationSessionRecordId,
|
|
440
|
+
},
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
if (!trustedCertificates) {
|
|
444
|
+
// We also take from the config here to avoid the callback being called again
|
|
445
|
+
trustedCertificates = x509Config.trustedCertificates ?? [];
|
|
446
|
+
}
|
|
447
|
+
const verificationResult = await sdJwtVcApi.verify({
|
|
448
|
+
compactSdJwtVc: encodedPresentation,
|
|
449
|
+
keyBinding: {
|
|
450
|
+
audience: options.audience,
|
|
451
|
+
nonce: options.nonce,
|
|
644
452
|
},
|
|
453
|
+
trustedCertificates,
|
|
645
454
|
});
|
|
455
|
+
isValid = verificationResult.verification.isValid;
|
|
456
|
+
reason = verificationResult.isValid ? undefined : verificationResult.error.message;
|
|
646
457
|
}
|
|
647
|
-
if (!
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
458
|
+
else if (typeof encodedPresentation === 'string' && !core_1.Jwt.format.test(encodedPresentation)) {
|
|
459
|
+
if (!options.responseUri || !options.mdocGeneratedNonce) {
|
|
460
|
+
isValid = false;
|
|
461
|
+
reason = 'Mdoc device response verification failed. Response uri and the mdocGeneratedNonce are not set';
|
|
462
|
+
}
|
|
463
|
+
else {
|
|
464
|
+
const mdocDeviceResponse = core_1.MdocDeviceResponse.fromBase64Url(encodedPresentation);
|
|
465
|
+
if (mdocDeviceResponse.documents.length !== 1) {
|
|
466
|
+
throw new core_1.CredoError('Only a single mdoc is supported per device response for OpenID4VP verification');
|
|
467
|
+
}
|
|
468
|
+
const document = mdocDeviceResponse.documents[0];
|
|
469
|
+
const certificateChain = document.issuerSignedCertificateChain.map((cert) => core_1.X509Certificate.fromRawCertificate(cert));
|
|
470
|
+
const trustedCertificates = await x509Config.getTrustedCertificatesForVerification?.(agentContext, {
|
|
471
|
+
certificateChain,
|
|
472
|
+
verification: {
|
|
473
|
+
type: 'credential',
|
|
474
|
+
credential: document,
|
|
475
|
+
openId4VcVerificationSessionId: options.verificationSessionRecordId,
|
|
476
|
+
},
|
|
477
|
+
});
|
|
478
|
+
await mdocDeviceResponse.verify(agentContext, {
|
|
479
|
+
sessionTranscriptOptions: {
|
|
480
|
+
clientId: options.audience,
|
|
481
|
+
mdocGeneratedNonce: options.mdocGeneratedNonce,
|
|
482
|
+
responseUri: options.responseUri,
|
|
483
|
+
verifierGeneratedNonce: options.nonce,
|
|
484
|
+
},
|
|
485
|
+
trustedCertificates,
|
|
486
|
+
});
|
|
487
|
+
isValid = true;
|
|
488
|
+
}
|
|
666
489
|
}
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
490
|
+
else if (typeof encodedPresentation === 'string' && core_1.Jwt.format.test(encodedPresentation)) {
|
|
491
|
+
const presentation = core_1.W3cJwtVerifiablePresentation.fromSerializedJwt(encodedPresentation);
|
|
492
|
+
const certificateChain = (0, core_1.extractX509CertificatesFromJwt)(presentation.jwt);
|
|
493
|
+
let trustedCertificates = undefined;
|
|
494
|
+
if (certificateChain && x509Config.getTrustedCertificatesForVerification) {
|
|
495
|
+
trustedCertificates = await x509Config.getTrustedCertificatesForVerification?.(agentContext, {
|
|
496
|
+
certificateChain,
|
|
497
|
+
verification: {
|
|
498
|
+
type: 'credential',
|
|
499
|
+
credential: presentation,
|
|
500
|
+
openId4VcVerificationSessionId: options.verificationSessionRecordId,
|
|
501
|
+
},
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
if (!trustedCertificates) {
|
|
505
|
+
trustedCertificates = x509Config.trustedCertificates ?? [];
|
|
506
|
+
}
|
|
507
|
+
const verificationResult = await this.w3cCredentialService.verifyPresentation(agentContext, {
|
|
508
|
+
presentation: encodedPresentation,
|
|
509
|
+
challenge: options.nonce,
|
|
510
|
+
domain: options.audience,
|
|
511
|
+
trustedCertificates,
|
|
682
512
|
});
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
})))
|
|
686
|
-
.filter((c) => c !== undefined)
|
|
687
|
-
.flatMap((c) => c);
|
|
688
|
-
let sessionTranscriptOptions;
|
|
689
|
-
if (options.origin) {
|
|
690
|
-
sessionTranscriptOptions = {
|
|
691
|
-
type: 'openId4VpDcApi',
|
|
692
|
-
clientId: options.audience,
|
|
693
|
-
verifierGeneratedNonce: options.nonce,
|
|
694
|
-
origin: options.origin,
|
|
695
|
-
};
|
|
513
|
+
isValid = verificationResult.isValid;
|
|
514
|
+
reason = verificationResult.error?.message;
|
|
696
515
|
}
|
|
697
516
|
else {
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
type: 'openId4Vp',
|
|
703
|
-
clientId: options.audience,
|
|
704
|
-
mdocGeneratedNonce: options.mdocGeneratedNonce,
|
|
705
|
-
responseUri: options.responseUri,
|
|
706
|
-
verifierGeneratedNonce: options.nonce,
|
|
707
|
-
};
|
|
708
|
-
}
|
|
709
|
-
await mdocDeviceResponse.verify(agentContext, {
|
|
710
|
-
sessionTranscriptOptions,
|
|
711
|
-
trustedCertificates,
|
|
712
|
-
});
|
|
713
|
-
isValid = true;
|
|
714
|
-
verifiablePresentation = mdocDeviceResponse;
|
|
715
|
-
}
|
|
716
|
-
else if (vpTokenPresentationParseResult.format === 'jwt_vp_json') {
|
|
717
|
-
const sdJwtPresentation = core_1.W3cJwtVerifiablePresentation.fromSerializedJwt(vpTokenPresentationParseResult.presentation);
|
|
718
|
-
const certificateChain = (0, core_1.extractX509CertificatesFromJwt)(sdJwtPresentation.jwt);
|
|
719
|
-
let trustedCertificates = undefined;
|
|
720
|
-
if (certificateChain && x509Config.getTrustedCertificatesForVerification) {
|
|
721
|
-
trustedCertificates = await x509Config.getTrustedCertificatesForVerification?.(agentContext, {
|
|
722
|
-
certificateChain,
|
|
723
|
-
verification: {
|
|
724
|
-
type: 'credential',
|
|
725
|
-
credential: sdJwtPresentation,
|
|
726
|
-
openId4VcVerificationSessionId: options.verificationSessionRecordId,
|
|
727
|
-
},
|
|
517
|
+
const verificationResult = await this.w3cCredentialService.verifyPresentation(agentContext, {
|
|
518
|
+
presentation: core_1.JsonTransformer.fromJSON(encodedPresentation, core_1.W3cJsonLdVerifiablePresentation),
|
|
519
|
+
challenge: options.nonce,
|
|
520
|
+
domain: options.audience,
|
|
728
521
|
});
|
|
522
|
+
isValid = verificationResult.isValid;
|
|
523
|
+
reason = verificationResult.error?.message;
|
|
729
524
|
}
|
|
730
|
-
if (!
|
|
731
|
-
|
|
525
|
+
if (!isValid) {
|
|
526
|
+
throw new Error(reason);
|
|
732
527
|
}
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
domain: options.audience,
|
|
737
|
-
trustedCertificates,
|
|
738
|
-
});
|
|
739
|
-
isValid = verificationResult.isValid;
|
|
740
|
-
reason = verificationResult.error?.message;
|
|
741
|
-
verifiablePresentation = core_1.W3cJwtVerifiablePresentation.fromSerializedJwt(vpTokenPresentationParseResult.presentation);
|
|
528
|
+
return {
|
|
529
|
+
verified: true,
|
|
530
|
+
};
|
|
742
531
|
}
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
presentation: w3cJsonLdVerifiablePresentation,
|
|
747
|
-
challenge: options.nonce,
|
|
748
|
-
domain: options.audience,
|
|
532
|
+
catch (error) {
|
|
533
|
+
agentContext.config.logger.warn('Error occurred during verification of presentation', {
|
|
534
|
+
error,
|
|
749
535
|
});
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
if (!isValid) {
|
|
755
|
-
throw new Error(reason);
|
|
536
|
+
return {
|
|
537
|
+
verified: false,
|
|
538
|
+
reason: error.message,
|
|
539
|
+
};
|
|
756
540
|
}
|
|
757
|
-
|
|
758
|
-
verified: true,
|
|
759
|
-
transactionDataMeta,
|
|
760
|
-
presentation: verifiablePresentation,
|
|
761
|
-
credentialId: options.credentialId,
|
|
762
|
-
};
|
|
763
|
-
}
|
|
764
|
-
catch (error) {
|
|
765
|
-
agentContext.config.logger.warn('Error occurred during verification of presentation', {
|
|
766
|
-
error,
|
|
767
|
-
});
|
|
768
|
-
return {
|
|
769
|
-
verified: false,
|
|
770
|
-
reason: error.message,
|
|
771
|
-
credentialId: options.credentialId,
|
|
772
|
-
};
|
|
773
|
-
}
|
|
774
|
-
}
|
|
775
|
-
/**
|
|
776
|
-
* Update the record to a new state and emit an state changed event. Also updates the record
|
|
777
|
-
* in storage.
|
|
778
|
-
*/
|
|
779
|
-
async updateState(agentContext, verificationSession, newState) {
|
|
780
|
-
agentContext.config.logger.debug(`Updating openid4vc verification session record ${verificationSession.id} to state ${newState} (previous=${verificationSession.state})`);
|
|
781
|
-
const previousState = verificationSession.state;
|
|
782
|
-
verificationSession.state = newState;
|
|
783
|
-
await this.openId4VcVerificationSessionRepository.update(agentContext, verificationSession);
|
|
784
|
-
this.emitStateChangedEvent(agentContext, verificationSession, previousState);
|
|
785
|
-
}
|
|
786
|
-
emitStateChangedEvent(agentContext, verificationSession, previousState) {
|
|
787
|
-
const eventEmitter = agentContext.dependencyManager.resolve(core_1.EventEmitter);
|
|
788
|
-
eventEmitter.emit(agentContext, {
|
|
789
|
-
type: OpenId4VcVerifierEvents_1.OpenId4VcVerifierEvents.VerificationSessionStateChanged,
|
|
790
|
-
payload: {
|
|
791
|
-
verificationSession: verificationSession.clone(),
|
|
792
|
-
previousState,
|
|
793
|
-
},
|
|
794
|
-
});
|
|
541
|
+
};
|
|
795
542
|
}
|
|
796
543
|
};
|
|
797
544
|
exports.OpenId4VcSiopVerifierService = OpenId4VcSiopVerifierService;
|