@sphereon/ssi-sdk.siopv2-oid4vp-op-auth 0.34.1-feature.SSISDK.26.RP.58 → 0.34.1-feature.SSISDK.44.finish.dcql.309
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 +667 -1065
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +723 -118
- package/dist/index.d.ts +723 -118
- package/dist/index.js +627 -1025
- package/dist/index.js.map +1 -1
- package/package.json +23 -23
- package/src/agent/DidAuthSiopOpAuthenticator.ts +10 -145
- package/src/index.ts +2 -1
- package/src/machine/Siopv2Machine.ts +5 -5
- package/src/services/Siopv2MachineService.ts +140 -267
- package/src/session/OID4VP.ts +180 -286
- package/src/session/OpSession.ts +11 -119
- package/src/session/functions.ts +1 -8
- package/src/types/IDidAuthSiopOpAuthenticator.ts +6 -59
- package/src/types/identifier/index.ts +0 -4
- package/src/types/machine/index.ts +1 -1
- package/src/types/siop-service/index.ts +12 -10
- package/src/utils/CredentialUtils.ts +2 -40
- package/src/utils/dcql.ts +22 -19
package/src/session/OID4VP.ts
CHANGED
|
@@ -1,322 +1,216 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import type { PartialSdJwtKbJwt } from '@sphereon/pex/dist/main/lib/index.js'
|
|
2
|
+
import { calculateSdHash } from '@sphereon/pex/dist/main/lib/utils/index.js'
|
|
3
|
+
import { isManagedIdentifierDidResult, ManagedIdentifierOptsOrResult } from '@sphereon/ssi-sdk-ext.identifier-resolution'
|
|
4
|
+
import { UniqueDigitalCredential } from '@sphereon/ssi-sdk.credential-store'
|
|
5
|
+
import { defaultGenerateDigest } from '@sphereon/ssi-sdk.sd-jwt'
|
|
4
6
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
export class OID4VP {
|
|
25
|
-
private readonly session: OpSession
|
|
26
|
-
private readonly allIdentifiers: string[]
|
|
27
|
-
private readonly hasher?: HasherSync
|
|
28
|
-
|
|
29
|
-
private constructor(args: IOID4VPArgs) {
|
|
30
|
-
const { session, allIdentifiers, hasher = defaultHasher } = args
|
|
31
|
-
|
|
32
|
-
this.session = session
|
|
33
|
-
this.allIdentifiers = allIdentifiers ?? []
|
|
34
|
-
this.hasher = hasher
|
|
35
|
-
}
|
|
7
|
+
CredentialMapper,
|
|
8
|
+
HasherSync,
|
|
9
|
+
Loggers,
|
|
10
|
+
OriginalVerifiableCredential,
|
|
11
|
+
SdJwtDecodedVerifiableCredential,
|
|
12
|
+
WrappedVerifiableCredential,
|
|
13
|
+
} from '@sphereon/ssi-types'
|
|
14
|
+
import { LOGGER_NAMESPACE, RequiredContext } from '../types'
|
|
15
|
+
|
|
16
|
+
const CLOCK_SKEW = 120
|
|
17
|
+
const logger = Loggers.DEFAULT.get(LOGGER_NAMESPACE)
|
|
18
|
+
|
|
19
|
+
export interface PresentationBuilderContext {
|
|
20
|
+
nonce: string
|
|
21
|
+
audience: string // clientId or origin
|
|
22
|
+
agent: RequiredContext['agent']
|
|
23
|
+
clockSkew?: number
|
|
24
|
+
hasher?: HasherSync
|
|
25
|
+
}
|
|
36
26
|
|
|
37
|
-
|
|
38
|
-
|
|
27
|
+
/**
|
|
28
|
+
* Extracts the original credential from a UniqueDigitalCredential or WrappedVerifiableCredential
|
|
29
|
+
*/
|
|
30
|
+
function extractOriginalCredential(
|
|
31
|
+
credential: UniqueDigitalCredential | WrappedVerifiableCredential | OriginalVerifiableCredential,
|
|
32
|
+
): OriginalVerifiableCredential {
|
|
33
|
+
if (typeof credential === 'string') {
|
|
34
|
+
return credential
|
|
39
35
|
}
|
|
40
36
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
37
|
+
if ('digitalCredential' in credential) {
|
|
38
|
+
// UniqueDigitalCredential
|
|
39
|
+
const udc = credential as UniqueDigitalCredential
|
|
40
|
+
if (udc.originalVerifiableCredential) {
|
|
41
|
+
return udc.originalVerifiableCredential
|
|
45
42
|
}
|
|
46
|
-
return
|
|
43
|
+
return udc.uniformVerifiableCredential as OriginalVerifiableCredential
|
|
47
44
|
}
|
|
48
45
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
return new PresentationExchange({
|
|
53
|
-
allDIDs: allIdentifiers ?? this.allIdentifiers,
|
|
54
|
-
allVerifiableCredentials: verifiableCredentials,
|
|
55
|
-
hasher: hasher ?? this.hasher,
|
|
56
|
-
})
|
|
46
|
+
if ('original' in credential) {
|
|
47
|
+
// WrappedVerifiableCredential
|
|
48
|
+
return credential.original
|
|
57
49
|
}
|
|
58
50
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
opts?: {
|
|
63
|
-
forceNoCredentialsInVP?: boolean // Allow to create a VP without credentials, like EBSI is using it. Defaults to false
|
|
64
|
-
restrictToFormats?: Format
|
|
65
|
-
restrictToDIDMethods?: string[]
|
|
66
|
-
proofOpts?: ProofOptions
|
|
67
|
-
idOpts?: ManagedIdentifierOptsOrResult
|
|
68
|
-
skipDidResolution?: boolean
|
|
69
|
-
holderDID?: string
|
|
70
|
-
subjectIsHolder?: boolean
|
|
71
|
-
hasher?: HasherSync
|
|
72
|
-
applyFilter?: boolean
|
|
73
|
-
},
|
|
74
|
-
): Promise<VerifiablePresentationWithDefinition[]> {
|
|
75
|
-
return await Promise.all(credentialsWithDefinitions.map((cred) => this.createVerifiablePresentation(credentialRole, cred, opts)))
|
|
76
|
-
}
|
|
51
|
+
// Already an OriginalVerifiableCredential
|
|
52
|
+
return credential as OriginalVerifiableCredential
|
|
53
|
+
}
|
|
77
54
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
idOpts?: ManagedIdentifierOptsOrResult
|
|
87
|
-
skipDidResolution?: boolean
|
|
88
|
-
holder?: string
|
|
89
|
-
subjectIsHolder?: boolean
|
|
90
|
-
applyFilter?: boolean
|
|
91
|
-
hasher?: HasherSync
|
|
92
|
-
},
|
|
93
|
-
): Promise<VerifiablePresentationWithDefinition> {
|
|
94
|
-
const { subjectIsHolder, holder, forceNoCredentialsInVP = false } = { ...opts }
|
|
95
|
-
if (subjectIsHolder && holder) {
|
|
96
|
-
throw Error('Cannot both have subject is holder and a holderDID value at the same time (programming error)')
|
|
55
|
+
/**
|
|
56
|
+
* Determines the format of a credential
|
|
57
|
+
*/
|
|
58
|
+
function detectCredentialFormat(credential: OriginalVerifiableCredential): string {
|
|
59
|
+
if (typeof credential === 'string') {
|
|
60
|
+
// Could be JWT or SD-JWT
|
|
61
|
+
if (credential.includes('~')) {
|
|
62
|
+
return 'dc+sd-jwt'
|
|
97
63
|
}
|
|
98
|
-
if (
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
64
|
+
// Check if it's a compact JWT format (3 parts)
|
|
65
|
+
const parts = credential.split('.')
|
|
66
|
+
if (parts.length === 3) {
|
|
67
|
+
return 'jwt_vc_json'
|
|
102
68
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
69
|
+
} else if (typeof credential === 'object') {
|
|
70
|
+
// Check for SD-JWT decoded format
|
|
71
|
+
if ('compactSdJwtVc' in credential) {
|
|
72
|
+
return 'dc+sd-jwt'
|
|
73
|
+
}
|
|
74
|
+
// Check for JSON-LD
|
|
75
|
+
if ('@context' in credential || 'proof' in credential) {
|
|
76
|
+
return 'ldp_vc'
|
|
108
77
|
}
|
|
78
|
+
// Check for mdoc
|
|
79
|
+
if ('doctype' in credential || 'namespaces' in credential) {
|
|
80
|
+
return 'mso_mdoc'
|
|
81
|
+
}
|
|
82
|
+
}
|
|
109
83
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
if (forceNoCredentialsInVP) {
|
|
114
|
-
return Promise.reject(
|
|
115
|
-
Error(
|
|
116
|
-
`Cannot have subject is holder, when force no credentials is being used, as we could never determine the holder then. Please provide holderDID`,
|
|
117
|
-
),
|
|
118
|
-
)
|
|
119
|
-
}
|
|
120
|
-
const firstUniqueDC = selectedVerifiableCredentials.credentials[0]
|
|
121
|
-
// const firstVC = firstUniqueDC.uniformVerifiableCredential!
|
|
122
|
-
if (typeof firstUniqueDC !== 'object' || !('digitalCredential' in firstUniqueDC)) {
|
|
123
|
-
return Promise.reject(Error('If no opts provided, credentials should be of type UniqueDigitalCredential'))
|
|
124
|
-
}
|
|
84
|
+
// Default to JWT
|
|
85
|
+
return 'jwt_vc_json'
|
|
86
|
+
}
|
|
125
87
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
88
|
+
/**
|
|
89
|
+
* Gets the issuer/holder identifier from ManagedIdentifierOptsOrResult
|
|
90
|
+
*/
|
|
91
|
+
function getIdentifierString(identifier: ManagedIdentifierOptsOrResult): string {
|
|
92
|
+
// Check if it's a result type (has 'method' and 'opts' properties)
|
|
93
|
+
if ('opts' in identifier && 'method' in identifier) {
|
|
94
|
+
// It's a ManagedIdentifierResult
|
|
95
|
+
if (isManagedIdentifierDidResult(identifier)) {
|
|
96
|
+
return identifier.did
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// For opts types or other result types, use issuer if available, otherwise kid
|
|
100
|
+
return identifier.issuer ?? identifier.kid ?? ''
|
|
101
|
+
}
|
|
134
102
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
103
|
+
/**
|
|
104
|
+
* Creates a Verifiable Presentation for a given credential in the appropriate format
|
|
105
|
+
* Ensures nonce/aud (or challenge/domain) are set according to OID4VP draft 28
|
|
106
|
+
*/
|
|
107
|
+
export async function createVerifiablePresentationForFormat(
|
|
108
|
+
credential: UniqueDigitalCredential | WrappedVerifiableCredential | OriginalVerifiableCredential,
|
|
109
|
+
identifier: ManagedIdentifierOptsOrResult,
|
|
110
|
+
context: PresentationBuilderContext,
|
|
111
|
+
): Promise<string | object> {
|
|
112
|
+
// FIXME find proper types
|
|
113
|
+
const { nonce, audience, agent, clockSkew = CLOCK_SKEW } = context
|
|
114
|
+
|
|
115
|
+
const originalCredential = extractOriginalCredential(credential)
|
|
116
|
+
const format = detectCredentialFormat(originalCredential)
|
|
117
|
+
|
|
118
|
+
logger.debug(`Creating VP for format: ${format}`)
|
|
119
|
+
|
|
120
|
+
switch (format) {
|
|
121
|
+
case 'dc+sd-jwt': {
|
|
122
|
+
// SD-JWT with KB-JWT
|
|
123
|
+
const decodedSdJwt = await CredentialMapper.decodeSdJwtVcAsync(
|
|
124
|
+
typeof originalCredential === 'string' ? originalCredential : (originalCredential as SdJwtDecodedVerifiableCredential).compactSdJwtVc,
|
|
125
|
+
defaultGenerateDigest,
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
const hashAlg = decodedSdJwt.signedPayload._sd_alg ?? 'sha-256'
|
|
129
|
+
const sdHash = calculateSdHash(decodedSdJwt.compactSdJwtVc, hashAlg, defaultGenerateDigest)
|
|
130
|
+
|
|
131
|
+
const kbJwtPayload: PartialSdJwtKbJwt['payload'] = {
|
|
132
|
+
iat: Math.floor(Date.now() / 1000 - clockSkew),
|
|
133
|
+
sd_hash: sdHash,
|
|
134
|
+
nonce, // Always use the Authorization Request nonce
|
|
135
|
+
aud: audience, // Always use the Client Identifier or Origin
|
|
151
136
|
}
|
|
152
|
-
}
|
|
153
137
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
restrictToDIDMethods: opts?.restrictToDIDMethods,
|
|
161
|
-
filterOpts: {
|
|
162
|
-
verifiableCredentials: selectedVerifiableCredentials.credentials,
|
|
163
|
-
},
|
|
164
|
-
})
|
|
165
|
-
: {
|
|
166
|
-
definition: selectedVerifiableCredentials.definition,
|
|
167
|
-
credentials: selectedVerifiableCredentials.credentials,
|
|
168
|
-
}
|
|
138
|
+
const presentationResult = await agent.createSdJwtPresentation({
|
|
139
|
+
presentation: decodedSdJwt.compactSdJwtVc,
|
|
140
|
+
kb: {
|
|
141
|
+
payload: kbJwtPayload as any, // FIXME
|
|
142
|
+
},
|
|
143
|
+
})
|
|
169
144
|
|
|
170
|
-
|
|
171
|
-
return Promise.reject(Error(`No identifier options present at this point`))
|
|
145
|
+
return presentationResult.presentation
|
|
172
146
|
}
|
|
173
147
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
...(identifier && isManagedIdentifierDidResult(identifier) && { holderDID: identifier.did }),
|
|
195
|
-
})
|
|
148
|
+
case 'jwt_vc_json': {
|
|
149
|
+
// JWT VC - create JWT VP with nonce and aud in payload
|
|
150
|
+
const vcJwt = typeof originalCredential === 'string' ? originalCredential : JSON.stringify(originalCredential)
|
|
151
|
+
|
|
152
|
+
const identifierString = getIdentifierString(identifier)
|
|
153
|
+
|
|
154
|
+
// Create VP JWT using agent method
|
|
155
|
+
const vpPayload = {
|
|
156
|
+
iss: identifierString,
|
|
157
|
+
aud: audience, // Client Identifier or Origin
|
|
158
|
+
nonce, // Authorization Request nonce
|
|
159
|
+
vp: {
|
|
160
|
+
'@context': ['https://www.w3.org/2018/credentials/v1'],
|
|
161
|
+
type: ['VerifiablePresentation'],
|
|
162
|
+
holder: identifierString,
|
|
163
|
+
verifiableCredential: [vcJwt],
|
|
164
|
+
},
|
|
165
|
+
iat: Math.floor(Date.now() / 1000 - clockSkew),
|
|
166
|
+
exp: Math.floor(Date.now() / 1000 + 600), // 10 minutes
|
|
167
|
+
}
|
|
196
168
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
:
|
|
204
|
-
|
|
169
|
+
// Use the agent's JWT creation capability
|
|
170
|
+
const vpJwt = await agent.createVerifiablePresentation({
|
|
171
|
+
presentation: vpPayload.vp,
|
|
172
|
+
proofFormat: 'jwt',
|
|
173
|
+
domain: audience,
|
|
174
|
+
challenge: nonce,
|
|
175
|
+
keyRef: identifier.kmsKeyRef || identifier.kid,
|
|
176
|
+
})
|
|
205
177
|
|
|
206
|
-
|
|
207
|
-
...presentationResult,
|
|
208
|
-
verifiablePresentations,
|
|
209
|
-
verifiableCredentials: verifiableCredentials,
|
|
210
|
-
definition: selectedVerifiableCredentials.definition,
|
|
211
|
-
idOpts,
|
|
178
|
+
return vpJwt.proof?.jwt || vpJwt
|
|
212
179
|
}
|
|
213
|
-
}
|
|
214
180
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
filterOpts?: {
|
|
219
|
-
verifiableCredentials?: UniqueDigitalCredential[]
|
|
220
|
-
filter?: FindDigitalCredentialArgs
|
|
221
|
-
}
|
|
222
|
-
holderDIDs?: string[]
|
|
223
|
-
restrictToFormats?: Format
|
|
224
|
-
restrictToDIDMethods?: string[]
|
|
225
|
-
},
|
|
226
|
-
): Promise<VerifiableCredentialsWithDefinition[]> {
|
|
227
|
-
const defs = await this.getPresentationDefinitions()
|
|
228
|
-
const result: VerifiableCredentialsWithDefinition[] = []
|
|
229
|
-
if (defs) {
|
|
230
|
-
for (const definition of defs) {
|
|
231
|
-
result.push(await this.filterCredentials(credentialRole, definition, opts))
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
return result
|
|
235
|
-
}
|
|
181
|
+
case 'ldp_vc': {
|
|
182
|
+
// JSON-LD VC - create JSON-LD VP with challenge and domain in proof
|
|
183
|
+
const vcObject = typeof originalCredential === 'string' ? JSON.parse(originalCredential) : originalCredential
|
|
236
184
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
filterOpts?: { verifiableCredentials?: (UniqueDigitalCredential | OriginalVerifiableCredential)[]; filter?: FindDigitalCredentialArgs }
|
|
242
|
-
holderDIDs?: string[]
|
|
243
|
-
restrictToFormats?: Format
|
|
244
|
-
restrictToDIDMethods?: string[]
|
|
245
|
-
},
|
|
246
|
-
): Promise<VerifiableCredentialsWithDefinition> {
|
|
247
|
-
const udcMap = new Map<OriginalVerifiableCredential, UniqueDigitalCredential | OriginalVerifiableCredential>()
|
|
248
|
-
opts?.filterOpts?.verifiableCredentials?.forEach((credential) => {
|
|
249
|
-
if (typeof credential === 'object' && 'digitalCredential' in credential) {
|
|
250
|
-
udcMap.set(credential.originalVerifiableCredential!, credential)
|
|
251
|
-
} else {
|
|
252
|
-
udcMap.set(credential, credential)
|
|
185
|
+
const vpObject = {
|
|
186
|
+
'@context': ['https://www.w3.org/2018/credentials/v1'],
|
|
187
|
+
type: ['VerifiablePresentation'],
|
|
188
|
+
verifiableCredential: [vcObject],
|
|
253
189
|
}
|
|
254
|
-
})
|
|
255
190
|
|
|
256
|
-
|
|
257
|
-
await
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
} else {
|
|
264
|
-
return credential
|
|
265
|
-
}
|
|
266
|
-
}),
|
|
267
|
-
},
|
|
191
|
+
// Create JSON-LD VP with proof
|
|
192
|
+
return await agent.createVerifiablePresentation({
|
|
193
|
+
presentation: vpObject,
|
|
194
|
+
proofFormat: 'lds',
|
|
195
|
+
challenge: nonce, // Authorization Request nonce as challenge
|
|
196
|
+
domain: audience, // Client Identifier or Origin as domain
|
|
197
|
+
keyRef: identifier.kmsKeyRef || identifier.kid,
|
|
268
198
|
})
|
|
269
|
-
).verifiableCredential
|
|
270
|
-
return {
|
|
271
|
-
definition: presentationDefinition,
|
|
272
|
-
credentials: credentials?.map((vc) => udcMap.get(vc)!) ?? [],
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
public async filterCredentialsWithSelectionStatus(
|
|
277
|
-
credentialRole: CredentialRole,
|
|
278
|
-
presentationDefinition: PresentationDefinitionWithLocation,
|
|
279
|
-
opts?: {
|
|
280
|
-
filterOpts?: { verifiableCredentials?: OriginalVerifiableCredential[]; filter?: FindDigitalCredentialArgs }
|
|
281
|
-
holderDIDs?: string[]
|
|
282
|
-
restrictToFormats?: Format
|
|
283
|
-
restrictToDIDMethods?: string[]
|
|
284
|
-
},
|
|
285
|
-
): Promise<SelectResults> {
|
|
286
|
-
const selectionResults: SelectResults = await this.getPresentationExchange({
|
|
287
|
-
verifiableCredentials: await this.getCredentials(credentialRole, opts?.filterOpts),
|
|
288
|
-
}).selectVerifiableCredentialsForSubmission(presentationDefinition.definition, opts)
|
|
289
|
-
if (selectionResults.errors && selectionResults.errors.length > 0) {
|
|
290
|
-
throw Error(JSON.stringify(selectionResults.errors))
|
|
291
|
-
} else if (selectionResults.areRequiredCredentialsPresent === Status.ERROR) {
|
|
292
|
-
throw Error(`Not all required credentials are available to satisfy the relying party's request`)
|
|
293
199
|
}
|
|
294
200
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
201
|
+
case 'mso_mdoc': {
|
|
202
|
+
// ISO mdoc - create mdoc VP token
|
|
203
|
+
// This is a placeholder implementation
|
|
204
|
+
// Full implementation would require:
|
|
205
|
+
// 1. Decode the mdoc using CredentialMapper or mdoc utilities
|
|
206
|
+
// 2. Build proper mdoc VP token with session transcript
|
|
207
|
+
// 3. Include nonce/audience in the session transcript
|
|
208
|
+
logger.warning('mso_mdoc format has basic support - production use requires proper mdoc VP token implementation')
|
|
301
209
|
|
|
302
|
-
|
|
303
|
-
credentialRole: CredentialRole,
|
|
304
|
-
filterOpts?: {
|
|
305
|
-
verifiableCredentials?: OriginalVerifiableCredential[]
|
|
306
|
-
filter?: FindDigitalCredentialArgs
|
|
307
|
-
},
|
|
308
|
-
): Promise<OriginalVerifiableCredential[]> {
|
|
309
|
-
if (filterOpts?.verifiableCredentials && filterOpts.verifiableCredentials.length > 0) {
|
|
310
|
-
return filterOpts.verifiableCredentials
|
|
210
|
+
return originalCredential
|
|
311
211
|
}
|
|
312
212
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
return uniqueCredentials.map((uniqueVC: UniqueDigitalCredential) => {
|
|
316
|
-
const vc = uniqueVC.uniformVerifiableCredential!
|
|
317
|
-
const proof = Array.isArray(vc.proof) ? vc.proof : [vc.proof]
|
|
318
|
-
const jwtProof = proof.find((p: IProof) => p?.type === DEFAULT_JWT_PROOF_TYPE)
|
|
319
|
-
return jwtProof ? (jwtProof.jwt as CompactJWT) : vc
|
|
320
|
-
})
|
|
213
|
+
default:
|
|
214
|
+
return Promise.reject(Error(`Unsupported credential format: ${format}`))
|
|
321
215
|
}
|
|
322
216
|
}
|