@sphereon/ssi-sdk.siopv2-oid4vp-op-auth 0.34.1-feature.SSISDK.45.94 → 0.34.1-feature.SSISDK.46.41
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/index.cjs +1095 -573
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +111 -709
- package/dist/index.d.ts +111 -709
- package/dist/index.js +1043 -521
- package/dist/index.js.map +1 -1
- package/package.json +25 -24
- package/src/agent/DidAuthSiopOpAuthenticator.ts +144 -9
- package/src/index.ts +1 -2
- package/src/machine/Siopv2Machine.ts +4 -4
- package/src/services/Siopv2MachineService.ts +265 -133
- package/src/session/OID4VP.ts +299 -310
- package/src/session/OpSession.ts +114 -22
- package/src/types/IDidAuthSiopOpAuthenticator.ts +58 -5
- package/src/types/identifier/index.ts +4 -0
- package/src/types/siop-service/index.ts +3 -1
- package/src/utils/CredentialUtils.ts +39 -1
- package/src/utils/dcql.ts +19 -21
package/src/session/OpSession.ts
CHANGED
|
@@ -2,30 +2,36 @@ import {
|
|
|
2
2
|
AuthorizationResponsePayload,
|
|
3
3
|
JwksMetadataParams,
|
|
4
4
|
OP,
|
|
5
|
+
PresentationDefinitionWithLocation,
|
|
6
|
+
PresentationExchangeResponseOpts,
|
|
7
|
+
PresentationVerificationResult,
|
|
5
8
|
RequestObjectPayload,
|
|
6
9
|
ResponseIss,
|
|
7
10
|
SupportedVersion,
|
|
8
11
|
URI,
|
|
9
12
|
Verification,
|
|
10
|
-
VerifiedAuthorizationRequest
|
|
13
|
+
VerifiedAuthorizationRequest,
|
|
11
14
|
} from '@sphereon/did-auth-siop'
|
|
12
15
|
import { ResolveOpts } from '@sphereon/did-auth-siop-adapter'
|
|
13
16
|
import { JwtIssuer } from '@sphereon/oid4vc-common'
|
|
14
17
|
import { getAgentDIDMethods, getAgentResolver } from '@sphereon/ssi-sdk-ext.did-utils'
|
|
15
18
|
import { JweAlg, JweEnc } from '@sphereon/ssi-sdk-ext.jwt-service'
|
|
16
19
|
import { encodeBase64url } from '@sphereon/ssi-sdk.core'
|
|
17
|
-
import { parseDid } from '@sphereon/ssi-types'
|
|
18
|
-
import { IIdentifier, TKeyType } from '@veramo/core'
|
|
19
|
-
import { v4 } from 'uuid'
|
|
20
20
|
import {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
CompactSdJwtVc,
|
|
22
|
+
CredentialMapper,
|
|
23
|
+
HasherSync,
|
|
24
|
+
OriginalVerifiableCredential,
|
|
25
|
+
parseDid,
|
|
26
|
+
PresentationSubmission,
|
|
27
|
+
W3CVerifiablePresentation,
|
|
28
|
+
} from '@sphereon/ssi-types'
|
|
29
|
+
import { IIdentifier, IVerifyResult, TKeyType } from '@veramo/core'
|
|
30
|
+
import { v4 } from 'uuid'
|
|
31
|
+
import { IOPOptions, IOpSessionArgs, IOpSessionGetOID4VPArgs, IOpsSendSiopAuthorizationResponseArgs, IRequiredContext } from '../types'
|
|
27
32
|
import { createOP } from './functions'
|
|
28
33
|
import { OID4VP } from './OID4VP'
|
|
34
|
+
import { PEX } from '@sphereon/pex'
|
|
29
35
|
import { Loggers } from '@sphereon/ssi-types'
|
|
30
36
|
|
|
31
37
|
const logger = Loggers.DEFAULT.get('sphereon:oid4vp:OpSession')
|
|
@@ -39,12 +45,14 @@ export class OpSession {
|
|
|
39
45
|
private verifiedAuthorizationRequest?: VerifiedAuthorizationRequest | undefined
|
|
40
46
|
private _nonce?: string
|
|
41
47
|
private _state?: string
|
|
48
|
+
private readonly _providedPresentationDefinitions?: PresentationDefinitionWithLocation[]
|
|
42
49
|
|
|
43
50
|
private constructor(options: Required<IOpSessionArgs>) {
|
|
44
51
|
this.id = options.sessionId
|
|
45
52
|
this.options = options.op
|
|
46
53
|
this.context = options.context
|
|
47
54
|
this.requestJwtOrUri = options.requestJwtOrUri
|
|
55
|
+
this._providedPresentationDefinitions = options.providedPresentationDefinitions
|
|
48
56
|
}
|
|
49
57
|
|
|
50
58
|
public static async init(options: Required<IOpSessionArgs>): Promise<OpSession> {
|
|
@@ -161,7 +169,7 @@ export class OpSession {
|
|
|
161
169
|
}
|
|
162
170
|
const isEBSI =
|
|
163
171
|
rpMethods.length === 0 &&
|
|
164
|
-
(authReq.issuer?.includes('.ebsi.eu') || authReq.authorizationRequest.getMergedProperty<string>('client_id')?.includes('.ebsi.eu'))
|
|
172
|
+
(authReq.issuer?.includes('.ebsi.eu') || (await authReq.authorizationRequest.getMergedProperty<string>('client_id'))?.includes('.ebsi.eu'))
|
|
165
173
|
let codecName: string | undefined = undefined
|
|
166
174
|
if (isEBSI && (!aud || !aud.startsWith('http'))) {
|
|
167
175
|
logger.debug(`EBSI detected, adding did:key to supported DID methods for RP`)
|
|
@@ -213,10 +221,51 @@ export class OpSession {
|
|
|
213
221
|
return Promise.resolve(this.verifiedAuthorizationRequest!.responseURI!)
|
|
214
222
|
}
|
|
215
223
|
|
|
224
|
+
public async hasPresentationDefinitions(): Promise<boolean> {
|
|
225
|
+
const defs = this._providedPresentationDefinitions ?? (await this.getAuthorizationRequest()).presentationDefinitions
|
|
226
|
+
return defs !== undefined && defs.length > 0
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
public async getPresentationDefinitions(): Promise<Array<PresentationDefinitionWithLocation> | undefined> {
|
|
230
|
+
if (!(await this.hasPresentationDefinitions())) {
|
|
231
|
+
throw Error(`No presentation definitions found`)
|
|
232
|
+
}
|
|
233
|
+
return this._providedPresentationDefinitions ?? (await this.getAuthorizationRequest()).presentationDefinitions
|
|
234
|
+
}
|
|
235
|
+
|
|
216
236
|
public async getOID4VP(args: IOpSessionGetOID4VPArgs): Promise<OID4VP> {
|
|
217
237
|
return await OID4VP.init(this, args.allIdentifiers ?? [], args.hasher)
|
|
218
238
|
}
|
|
219
239
|
|
|
240
|
+
private createPresentationVerificationCallback(context: IRequiredContext) {
|
|
241
|
+
async function presentationVerificationCallback(
|
|
242
|
+
args: W3CVerifiablePresentation | CompactSdJwtVc,
|
|
243
|
+
presentationSubmission?: PresentationSubmission,
|
|
244
|
+
): Promise<PresentationVerificationResult> {
|
|
245
|
+
let result: IVerifyResult
|
|
246
|
+
if (CredentialMapper.isSdJwtEncoded(args)) {
|
|
247
|
+
try {
|
|
248
|
+
const sdJwtResult = await context.agent.verifySdJwtPresentation({ presentation: args })
|
|
249
|
+
result = {
|
|
250
|
+
verified: 'header' in sdJwtResult,
|
|
251
|
+
error: 'header' in sdJwtResult ? undefined : { message: 'could not verify SD JWT presentation' },
|
|
252
|
+
}
|
|
253
|
+
} catch (error: any) {
|
|
254
|
+
result = {
|
|
255
|
+
verified: false,
|
|
256
|
+
error: { message: error.message },
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
} else {
|
|
260
|
+
// @ts-ignore TODO IVerifiablePresentation has too many union types for Veramo
|
|
261
|
+
result = await context.agent.verifyPresentation({ presentation: args })
|
|
262
|
+
}
|
|
263
|
+
return result
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
return presentationVerificationCallback
|
|
267
|
+
}
|
|
268
|
+
|
|
220
269
|
private async createJarmResponseCallback({
|
|
221
270
|
responseOpts,
|
|
222
271
|
}: {
|
|
@@ -259,12 +308,6 @@ export class OpSession {
|
|
|
259
308
|
}
|
|
260
309
|
|
|
261
310
|
public async sendAuthorizationResponse(args: IOpsSendSiopAuthorizationResponseArgs): Promise<Response> {
|
|
262
|
-
const {
|
|
263
|
-
responseSignerOpts,
|
|
264
|
-
dcqlResponse,
|
|
265
|
-
isFirstParty,
|
|
266
|
-
} = args
|
|
267
|
-
|
|
268
311
|
const resolveOpts: ResolveOpts = this.options.resolveOpts ?? {
|
|
269
312
|
resolver: getAgentResolver(this.context, {
|
|
270
313
|
uniresolverResolution: true,
|
|
@@ -275,9 +318,30 @@ export class OpSession {
|
|
|
275
318
|
if (!resolveOpts.subjectSyntaxTypesSupported || resolveOpts.subjectSyntaxTypesSupported.length === 0) {
|
|
276
319
|
resolveOpts.subjectSyntaxTypesSupported = await this.getSupportedDIDMethods(true)
|
|
277
320
|
}
|
|
278
|
-
|
|
321
|
+
//todo: populate with the right verification params. In did-auth-siop we don't have any test that actually passes this parameter
|
|
322
|
+
const verification: Verification = {
|
|
323
|
+
presentationVerificationCallback: this.createPresentationVerificationCallback(this.context),
|
|
324
|
+
}
|
|
279
325
|
const request = await this.getAuthorizationRequest()
|
|
326
|
+
const hasDefinitions = await this.hasPresentationDefinitions()
|
|
327
|
+
if (hasDefinitions) {
|
|
328
|
+
const totalInputDescriptors = request.presentationDefinitions?.reduce((sum, pd) => {
|
|
329
|
+
return sum + pd.definition.input_descriptors.length
|
|
330
|
+
}, 0)
|
|
331
|
+
const totalVCs = args.verifiablePresentations ? this.countVCsInAllVPs(args.verifiablePresentations, args.hasher) : 0
|
|
332
|
+
|
|
333
|
+
if (!request.presentationDefinitions || !args.verifiablePresentations || totalVCs !== totalInputDescriptors) {
|
|
334
|
+
throw Error(
|
|
335
|
+
`Amount of presentations ${args.verifiablePresentations?.length}, doesn't match expected ${request.presentationDefinitions?.length}`,
|
|
336
|
+
)
|
|
337
|
+
} else if (!args.presentationSubmission) {
|
|
338
|
+
throw Error(`Presentation submission is required when verifiable presentations are required`)
|
|
339
|
+
}
|
|
340
|
+
}
|
|
280
341
|
|
|
342
|
+
const verifiablePresentations = args.verifiablePresentations
|
|
343
|
+
? args.verifiablePresentations.map((vp) => CredentialMapper.storedPresentationToOriginalFormat(vp))
|
|
344
|
+
: []
|
|
281
345
|
const op = await createOP({
|
|
282
346
|
opOptions: {
|
|
283
347
|
...this.options,
|
|
@@ -287,16 +351,23 @@ export class OpSession {
|
|
|
287
351
|
wellknownDIDVerifyCallback: this.options.wellknownDIDVerifyCallback,
|
|
288
352
|
supportedVersions: request.versions,
|
|
289
353
|
},
|
|
290
|
-
idOpts: responseSignerOpts,
|
|
354
|
+
idOpts: args.responseSignerOpts,
|
|
291
355
|
context: this.context,
|
|
292
356
|
})
|
|
293
357
|
|
|
294
358
|
//TODO change this to use the new functionalities by identifier-resolver and get the jwkIssuer for the responseOpts
|
|
295
|
-
let issuer = responseSignerOpts.issuer
|
|
359
|
+
let issuer = args.responseSignerOpts.issuer
|
|
296
360
|
const responseOpts = {
|
|
361
|
+
verification,
|
|
297
362
|
issuer,
|
|
298
|
-
...(isFirstParty && { isFirstParty }),
|
|
299
|
-
|
|
363
|
+
...(args.isFirstParty && { isFirstParty: args.isFirstParty }),
|
|
364
|
+
...(args.verifiablePresentations && {
|
|
365
|
+
presentationExchange: {
|
|
366
|
+
verifiablePresentations,
|
|
367
|
+
presentationSubmission: args.presentationSubmission,
|
|
368
|
+
} as PresentationExchangeResponseOpts,
|
|
369
|
+
}),
|
|
370
|
+
dcqlQuery: args.dcqlResponse,
|
|
300
371
|
}
|
|
301
372
|
|
|
302
373
|
const authResponse = await op.createAuthorizationResponse(request, responseOpts)
|
|
@@ -308,6 +379,27 @@ export class OpSession {
|
|
|
308
379
|
return response
|
|
309
380
|
}
|
|
310
381
|
}
|
|
382
|
+
|
|
383
|
+
private countVCsInAllVPs(verifiablePresentations: W3CVerifiablePresentation[], hasher?: HasherSync) {
|
|
384
|
+
return verifiablePresentations.reduce((sum, vp) => {
|
|
385
|
+
if (CredentialMapper.isMsoMdocDecodedPresentation(vp) || CredentialMapper.isMsoMdocOid4VPEncoded(vp)) {
|
|
386
|
+
return sum + 1
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
const uvp = CredentialMapper.toUniformPresentation(vp, { hasher: hasher ?? this.options.hasher })
|
|
390
|
+
if (uvp.verifiableCredential?.length) {
|
|
391
|
+
return sum + uvp.verifiableCredential?.length
|
|
392
|
+
}
|
|
393
|
+
const isSdJWT = CredentialMapper.isSdJwtDecodedCredential(uvp)
|
|
394
|
+
if (
|
|
395
|
+
isSdJWT ||
|
|
396
|
+
(uvp.verifiableCredential && !PEX.allowMultipleVCsPerPresentation(uvp.verifiableCredential as Array<OriginalVerifiableCredential>))
|
|
397
|
+
) {
|
|
398
|
+
return sum + 1
|
|
399
|
+
}
|
|
400
|
+
return sum
|
|
401
|
+
}, 0)
|
|
402
|
+
}
|
|
311
403
|
}
|
|
312
404
|
|
|
313
405
|
function convertDidMethod(didMethod: string, didPrefix?: boolean): string {
|
|
@@ -1,21 +1,25 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DcqlResponseOpts,
|
|
3
|
+
PresentationDefinitionWithLocation,
|
|
3
4
|
PresentationSignCallback,
|
|
4
5
|
ResponseMode,
|
|
5
6
|
SupportedVersion,
|
|
6
7
|
URI,
|
|
8
|
+
VerifiablePresentationTypeFormat,
|
|
7
9
|
VerifiedAuthorizationRequest,
|
|
8
10
|
VerifyJwtCallback,
|
|
11
|
+
VPTokenLocation,
|
|
9
12
|
} from '@sphereon/did-auth-siop'
|
|
10
13
|
import { CheckLinkedDomain, ResolveOpts } from '@sphereon/did-auth-siop-adapter'
|
|
11
14
|
import { DIDDocument } from '@sphereon/did-uni-client'
|
|
15
|
+
import { VerifiablePresentationResult } from '@sphereon/pex'
|
|
12
16
|
import { IIdentifierResolution, ManagedIdentifierOptsOrResult } from '@sphereon/ssi-sdk-ext.identifier-resolution'
|
|
13
17
|
import { IJwtService } from '@sphereon/ssi-sdk-ext.jwt-service'
|
|
14
|
-
import { ICredentialStore } from '@sphereon/ssi-sdk.credential-store'
|
|
18
|
+
import { ICredentialStore, UniqueDigitalCredential } from '@sphereon/ssi-sdk.credential-store'
|
|
15
19
|
import { Party } from '@sphereon/ssi-sdk.data-store'
|
|
16
20
|
import { IPDManager } from '@sphereon/ssi-sdk.pd-manager'
|
|
17
21
|
import { ISDJwtPlugin } from '@sphereon/ssi-sdk.sd-jwt'
|
|
18
|
-
import { HasherSync, PresentationSubmission, W3CVerifiablePresentation } from '@sphereon/ssi-types'
|
|
22
|
+
import { HasherSync, OriginalVerifiableCredential, PresentationSubmission, W3CVerifiablePresentation } from '@sphereon/ssi-types'
|
|
19
23
|
import { VerifyCallback } from '@sphereon/wellknown-dids-client'
|
|
20
24
|
import {
|
|
21
25
|
IAgentContext,
|
|
@@ -45,7 +49,6 @@ import {
|
|
|
45
49
|
Siopv2AuthorizationResponseData,
|
|
46
50
|
} from './siop-service'
|
|
47
51
|
import { ICredentialValidation } from '@sphereon/ssi-sdk.credential-validation'
|
|
48
|
-
import { DcqlPresentation, DcqlQuery } from 'dcql'
|
|
49
52
|
|
|
50
53
|
export const LOGGER_NAMESPACE = 'sphereon:siopv2-oid4vp:op-auth'
|
|
51
54
|
|
|
@@ -78,7 +81,7 @@ export interface IDidAuthSiopOpAuthenticator extends IPluginMethodMap {
|
|
|
78
81
|
export interface IOpSessionArgs {
|
|
79
82
|
sessionId?: string
|
|
80
83
|
requestJwtOrUri: string | URI
|
|
81
|
-
|
|
84
|
+
providedPresentationDefinitions?: Array<PresentationDefinitionWithLocation>
|
|
82
85
|
identifierOptions?: ManagedIdentifierOptsOrResult
|
|
83
86
|
context: IRequiredContext
|
|
84
87
|
op?: IOPOptions
|
|
@@ -87,10 +90,17 @@ export interface IOpSessionArgs {
|
|
|
87
90
|
export interface IAuthRequestDetails {
|
|
88
91
|
rpDIDDocument?: DIDDocument
|
|
89
92
|
id: string
|
|
90
|
-
verifiablePresentationMatches:
|
|
93
|
+
verifiablePresentationMatches: IPresentationWithDefinition[]
|
|
91
94
|
alsoKnownAs?: string[]
|
|
92
95
|
}
|
|
93
96
|
|
|
97
|
+
export interface IPresentationWithDefinition {
|
|
98
|
+
location: VPTokenLocation
|
|
99
|
+
definition: PresentationDefinitionWithLocation
|
|
100
|
+
format: VerifiablePresentationTypeFormat
|
|
101
|
+
presentation: W3CVerifiablePresentation
|
|
102
|
+
}
|
|
103
|
+
|
|
94
104
|
export interface IGetSiopSessionArgs {
|
|
95
105
|
sessionId: string
|
|
96
106
|
}
|
|
@@ -110,6 +120,7 @@ export interface IRemoveCustomApprovalForSiopArgs {
|
|
|
110
120
|
|
|
111
121
|
export interface IOpsSendSiopAuthorizationResponseArgs {
|
|
112
122
|
responseSignerOpts: ManagedIdentifierOptsOrResult
|
|
123
|
+
// verifiedAuthorizationRequest: VerifiedAuthorizationRequest
|
|
113
124
|
presentationSubmission?: PresentationSubmission
|
|
114
125
|
verifiablePresentations?: W3CVerifiablePresentation[]
|
|
115
126
|
dcqlResponse?: DcqlResponseOpts
|
|
@@ -117,6 +128,10 @@ export interface IOpsSendSiopAuthorizationResponseArgs {
|
|
|
117
128
|
isFirstParty?: boolean
|
|
118
129
|
}
|
|
119
130
|
|
|
131
|
+
export enum events {
|
|
132
|
+
DID_SIOP_AUTHENTICATED = 'didSiopAuthenticated',
|
|
133
|
+
}
|
|
134
|
+
|
|
120
135
|
export type IRequiredContext = IAgentContext<
|
|
121
136
|
IDataStoreORM &
|
|
122
137
|
IResolver &
|
|
@@ -140,13 +155,34 @@ export interface IOPOptions {
|
|
|
140
155
|
skipDidResolution?: boolean
|
|
141
156
|
eventEmitter?: EventEmitter
|
|
142
157
|
supportedDIDMethods?: string[]
|
|
158
|
+
|
|
143
159
|
verifyJwtCallback?: VerifyJwtCallback
|
|
144
160
|
wellknownDIDVerifyCallback?: VerifyCallback
|
|
161
|
+
|
|
145
162
|
presentationSignCallback?: PresentationSignCallback
|
|
163
|
+
|
|
146
164
|
resolveOpts?: ResolveOpts
|
|
147
165
|
hasher?: HasherSync
|
|
148
166
|
}
|
|
149
167
|
|
|
168
|
+
/*
|
|
169
|
+
export interface IIdentifierOpts {
|
|
170
|
+
identifier: IIdentifier
|
|
171
|
+
verificationMethodSection?: DIDDocumentSection
|
|
172
|
+
kid?: string
|
|
173
|
+
}*/
|
|
174
|
+
|
|
175
|
+
export interface VerifiableCredentialsWithDefinition {
|
|
176
|
+
definition: PresentationDefinitionWithLocation
|
|
177
|
+
credentials: (UniqueDigitalCredential | OriginalVerifiableCredential)[]
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export interface VerifiablePresentationWithDefinition extends VerifiablePresentationResult {
|
|
181
|
+
definition: PresentationDefinitionWithLocation
|
|
182
|
+
verifiableCredentials: OriginalVerifiableCredential[]
|
|
183
|
+
idOpts: ManagedIdentifierOptsOrResult
|
|
184
|
+
}
|
|
185
|
+
|
|
150
186
|
export interface IOpSessionGetOID4VPArgs {
|
|
151
187
|
allIdentifiers?: string[]
|
|
152
188
|
hasher?: HasherSync
|
|
@@ -158,4 +194,21 @@ export interface IOID4VPArgs {
|
|
|
158
194
|
hasher?: HasherSync
|
|
159
195
|
}
|
|
160
196
|
|
|
197
|
+
export interface IGetPresentationExchangeArgs {
|
|
198
|
+
verifiableCredentials: OriginalVerifiableCredential[]
|
|
199
|
+
allIdentifiers?: string[]
|
|
200
|
+
hasher?: HasherSync
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// It was added here because it's not exported from DCQL anymore
|
|
204
|
+
export type Json =
|
|
205
|
+
| string
|
|
206
|
+
| number
|
|
207
|
+
| boolean
|
|
208
|
+
| null
|
|
209
|
+
| {
|
|
210
|
+
[key: string]: Json
|
|
211
|
+
}
|
|
212
|
+
| Json[]
|
|
213
|
+
|
|
161
214
|
export const DEFAULT_JWT_PROOF_TYPE = 'JwtProof2020'
|
|
@@ -2,6 +2,9 @@ import { IDIDManager, IIdentifier, IResolver, TAgent, TKeyType } from '@veramo/c
|
|
|
2
2
|
import { _ExtendedIKey } from '@veramo/utils'
|
|
3
3
|
import { RequiredContext } from '../siop-service'
|
|
4
4
|
import { SupportedDidMethodEnum } from '@sphereon/ssi-sdk-ext.did-utils'
|
|
5
|
+
import { IContactManager } from '@sphereon/ssi-sdk.contact-manager'
|
|
6
|
+
import { IIssuanceBranding } from '@sphereon/ssi-sdk.issuance-branding'
|
|
7
|
+
import { ICredentialStore } from '@sphereon/ssi-sdk.credential-store'
|
|
5
8
|
|
|
6
9
|
export const DID_PREFIX = 'did'
|
|
7
10
|
|
|
@@ -57,3 +60,4 @@ export type CreateIdentifierOpts = {
|
|
|
57
60
|
}
|
|
58
61
|
|
|
59
62
|
export type DidAgents = TAgent<IResolver & IDIDManager>
|
|
63
|
+
export type SuitableCredentialAgents = TAgent<IContactManager & ICredentialStore & IIssuanceBranding>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
PresentationDefinitionWithLocation,
|
|
2
3
|
PresentationSignCallback,
|
|
3
4
|
RPRegistrationMetadataPayload,
|
|
4
5
|
VerifiedAuthorizationRequest,
|
|
@@ -68,7 +69,8 @@ export type Siopv2AuthorizationRequestData = {
|
|
|
68
69
|
name?: string
|
|
69
70
|
uri?: URL
|
|
70
71
|
clientId?: string
|
|
71
|
-
|
|
72
|
+
presentationDefinitions?: PresentationDefinitionWithLocation[]
|
|
73
|
+
dcqlQuery?: DcqlQuery
|
|
72
74
|
}
|
|
73
75
|
|
|
74
76
|
export type SelectableCredentialsMap = Map<string, Array<SelectableCredential>>
|
|
@@ -1,7 +1,45 @@
|
|
|
1
|
-
import { CredentialMapper, HasherSync, ICredential, OriginalVerifiableCredential } from '@sphereon/ssi-types'
|
|
1
|
+
import { CredentialMapper, HasherSync, ICredential, IVerifiableCredential, OriginalVerifiableCredential } from '@sphereon/ssi-types'
|
|
2
2
|
import { VerifiableCredential } from '@veramo/core'
|
|
3
3
|
import { UniqueDigitalCredential } from '@sphereon/ssi-sdk.credential-store'
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Return the type(s) of a VC minus the VerifiableCredential type which should always be present
|
|
7
|
+
* @param credential The input credential
|
|
8
|
+
*/
|
|
9
|
+
export const getCredentialTypeAsString = (credential: ICredential | VerifiableCredential): string => {
|
|
10
|
+
if (!credential.type) {
|
|
11
|
+
return 'Verifiable Credential'
|
|
12
|
+
} else if (typeof credential.type === 'string') {
|
|
13
|
+
return credential.type
|
|
14
|
+
}
|
|
15
|
+
return credential.type.filter((type: string): boolean => type !== 'VerifiableCredential').join(', ')
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Returns a Unique Verifiable Credential (with hash) as stored in Veramo, based upon matching the id of the input VC or the proof value of the input VC
|
|
20
|
+
* @param uniqueVCs The Unique VCs to search in
|
|
21
|
+
* @param searchVC The VC to search for in the unique VCs array
|
|
22
|
+
*/
|
|
23
|
+
export const getMatchingUniqueDigitalCredential = (
|
|
24
|
+
uniqueVCs: UniqueDigitalCredential[],
|
|
25
|
+
searchVC: OriginalVerifiableCredential,
|
|
26
|
+
): UniqueDigitalCredential | undefined => {
|
|
27
|
+
// Since an ID is optional in a VC according to VCDM, and we really need the matches, we have a fallback match on something which is guaranteed to be unique for any VC (the proof(s))
|
|
28
|
+
return uniqueVCs.find(
|
|
29
|
+
(uniqueVC: UniqueDigitalCredential) =>
|
|
30
|
+
(typeof searchVC !== 'string' &&
|
|
31
|
+
(uniqueVC.id === (<IVerifiableCredential>searchVC).id ||
|
|
32
|
+
(uniqueVC.originalVerifiableCredential as VerifiableCredential).proof === (<IVerifiableCredential>searchVC).proof)) ||
|
|
33
|
+
(typeof searchVC === 'string' && (uniqueVC.uniformVerifiableCredential as VerifiableCredential)?.proof?.jwt === searchVC) ||
|
|
34
|
+
// We are ignoring the signature of the sd-jwt as PEX signs the vc again and it will not match anymore with the jwt in the proof of the stored jsonld vc
|
|
35
|
+
(typeof searchVC === 'string' &&
|
|
36
|
+
CredentialMapper.isSdJwtEncoded(searchVC) &&
|
|
37
|
+
uniqueVC.uniformVerifiableCredential?.proof &&
|
|
38
|
+
'jwt' in uniqueVC.uniformVerifiableCredential.proof &&
|
|
39
|
+
uniqueVC.uniformVerifiableCredential.proof.jwt?.split('.')?.slice(0, 2)?.join('.') === searchVC.split('.')?.slice(0, 2)?.join('.')),
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
|
|
5
43
|
type InputCredential = UniqueDigitalCredential | VerifiableCredential | ICredential | OriginalVerifiableCredential
|
|
6
44
|
|
|
7
45
|
/**
|
package/src/utils/dcql.ts
CHANGED
|
@@ -1,38 +1,36 @@
|
|
|
1
1
|
import { UniqueDigitalCredential } from '@sphereon/ssi-sdk.credential-store'
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
HasherSync,
|
|
5
|
-
OriginalVerifiableCredential, WrappedMdocCredential,
|
|
6
|
-
type WrappedSdJwtVerifiableCredential, type WrappedW3CVerifiableCredential
|
|
7
|
-
} from '@sphereon/ssi-types'
|
|
8
|
-
import { Dcql } from '@sphereon/did-auth-siop'
|
|
9
|
-
import { DcqlCredential } from 'dcql'
|
|
2
|
+
import { DcqlCredential, DcqlSdJwtVcCredential, DcqlW3cVcCredential } from 'dcql'
|
|
3
|
+
import { CredentialMapper, HasherSync, OriginalVerifiableCredential } from '@sphereon/ssi-types'
|
|
10
4
|
import { isUniqueDigitalCredential } from './CredentialUtils'
|
|
11
5
|
|
|
12
6
|
export function convertToDcqlCredentials(credential: UniqueDigitalCredential | OriginalVerifiableCredential, hasher?: HasherSync): DcqlCredential {
|
|
13
|
-
let
|
|
7
|
+
let payload
|
|
14
8
|
if (isUniqueDigitalCredential(credential)) {
|
|
15
9
|
if (!credential.originalVerifiableCredential) {
|
|
16
10
|
throw new Error('originalVerifiableCredential is not defined in UniqueDigitalCredential')
|
|
17
11
|
}
|
|
18
|
-
|
|
12
|
+
payload = CredentialMapper.decodeVerifiableCredential(credential.originalVerifiableCredential, hasher)
|
|
19
13
|
} else {
|
|
20
|
-
|
|
14
|
+
payload = CredentialMapper.decodeVerifiableCredential(credential as OriginalVerifiableCredential, hasher)
|
|
21
15
|
}
|
|
22
16
|
|
|
23
|
-
if (!
|
|
17
|
+
if (!payload) {
|
|
24
18
|
throw new Error('No payload found')
|
|
25
19
|
}
|
|
26
20
|
|
|
27
|
-
if (
|
|
28
|
-
|
|
29
|
-
} else if (CredentialMapper.isSdJwtDecodedCredential(originalVerifiableCredential)) {
|
|
30
|
-
return Dcql.toDcqlSdJwtCredential(CredentialMapper.toWrappedVerifiableCredential(originalVerifiableCredential) as WrappedSdJwtVerifiableCredential)
|
|
31
|
-
} else if (CredentialMapper.isMsoMdocDecodedCredential(originalVerifiableCredential)) {
|
|
32
|
-
return Dcql.toDcqlMdocCredential(CredentialMapper.toWrappedVerifiableCredential(originalVerifiableCredential) as WrappedMdocCredential)
|
|
33
|
-
} else if (CredentialMapper.isW3cCredential(originalVerifiableCredential)) {
|
|
34
|
-
return Dcql.toDcqlJsonLdCredential(CredentialMapper.toWrappedVerifiableCredential(originalVerifiableCredential) as WrappedW3CVerifiableCredential)
|
|
21
|
+
if ('decodedPayload' in payload && payload.decodedPayload) {
|
|
22
|
+
payload = payload.decodedPayload
|
|
35
23
|
}
|
|
36
24
|
|
|
37
|
-
|
|
25
|
+
if ('vct' in payload!) {
|
|
26
|
+
return { vct: payload.vct, claims: payload, credential_format: 'vc+sd-jwt' } satisfies DcqlSdJwtVcCredential // TODO dc+sd-jwt support?
|
|
27
|
+
} else if ('docType' in payload! && 'namespaces' in payload) {
|
|
28
|
+
// mdoc
|
|
29
|
+
return { docType: payload.docType, namespaces: payload.namespaces, claims: payload }
|
|
30
|
+
} else {
|
|
31
|
+
return {
|
|
32
|
+
claims: payload,
|
|
33
|
+
credential_format: 'jwt_vc_json', // TODO jwt_vc_json-ld support
|
|
34
|
+
} as DcqlW3cVcCredential
|
|
35
|
+
}
|
|
38
36
|
}
|