@sphereon/ssi-sdk.siopv2-oid4vp-op-auth 0.34.1-feature.SSISDK.78.306 → 0.34.1-feature.SSISDK.82.linkedVP.325

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sphereon/ssi-sdk.siopv2-oid4vp-op-auth",
3
- "version": "0.34.1-feature.SSISDK.78.306+9aff176a",
3
+ "version": "0.34.1-feature.SSISDK.82.linkedVP.325+9de5d4ff",
4
4
  "source": "src/index.ts",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -26,26 +26,26 @@
26
26
  "build": "tsup --config ../../tsup.config.ts --tsconfig ../../tsconfig.tsup.json"
27
27
  },
28
28
  "dependencies": {
29
- "@sphereon/did-auth-siop": "0.19.1-next.220",
30
- "@sphereon/did-auth-siop-adapter": "0.19.1-next.220",
31
- "@sphereon/oid4vc-common": "0.19.1-next.220",
29
+ "@sphereon/did-auth-siop": "0.19.1-next.226",
30
+ "@sphereon/did-auth-siop-adapter": "0.19.1-next.226",
31
+ "@sphereon/oid4vc-common": "0.19.1-next.226",
32
32
  "@sphereon/pex": "5.0.0-unstable.28",
33
33
  "@sphereon/pex-models": "^2.3.2",
34
- "@sphereon/ssi-sdk-ext.did-utils": "0.34.1-feature.SSISDK.78.306+9aff176a",
35
- "@sphereon/ssi-sdk-ext.identifier-resolution": "0.34.1-feature.SSISDK.78.306+9aff176a",
36
- "@sphereon/ssi-sdk-ext.jwt-service": "0.34.1-feature.SSISDK.78.306+9aff176a",
37
- "@sphereon/ssi-sdk.contact-manager": "0.34.1-feature.SSISDK.78.306+9aff176a",
38
- "@sphereon/ssi-sdk.core": "0.34.1-feature.SSISDK.78.306+9aff176a",
39
- "@sphereon/ssi-sdk.credential-store": "0.34.1-feature.SSISDK.78.306+9aff176a",
40
- "@sphereon/ssi-sdk.credential-validation": "0.34.1-feature.SSISDK.78.306+9aff176a",
41
- "@sphereon/ssi-sdk.data-store-types": "0.34.1-feature.SSISDK.78.306+9aff176a",
42
- "@sphereon/ssi-sdk.issuance-branding": "0.34.1-feature.SSISDK.78.306+9aff176a",
43
- "@sphereon/ssi-sdk.pd-manager": "0.34.1-feature.SSISDK.78.306+9aff176a",
44
- "@sphereon/ssi-sdk.presentation-exchange": "0.34.1-feature.SSISDK.78.306+9aff176a",
45
- "@sphereon/ssi-sdk.sd-jwt": "0.34.1-feature.SSISDK.78.306+9aff176a",
46
- "@sphereon/ssi-sdk.siopv2-oid4vp-common": "0.34.1-feature.SSISDK.78.306+9aff176a",
47
- "@sphereon/ssi-sdk.xstate-machine-persistence": "0.34.1-feature.SSISDK.78.306+9aff176a",
48
- "@sphereon/ssi-types": "0.34.1-feature.SSISDK.78.306+9aff176a",
34
+ "@sphereon/ssi-sdk-ext.did-utils": "0.34.1-feature.SSISDK.82.linkedVP.325+9de5d4ff",
35
+ "@sphereon/ssi-sdk-ext.identifier-resolution": "0.34.1-feature.SSISDK.82.linkedVP.325+9de5d4ff",
36
+ "@sphereon/ssi-sdk-ext.jwt-service": "0.34.1-feature.SSISDK.82.linkedVP.325+9de5d4ff",
37
+ "@sphereon/ssi-sdk.contact-manager": "0.34.1-feature.SSISDK.82.linkedVP.325+9de5d4ff",
38
+ "@sphereon/ssi-sdk.core": "0.34.1-feature.SSISDK.82.linkedVP.325+9de5d4ff",
39
+ "@sphereon/ssi-sdk.credential-store": "0.34.1-feature.SSISDK.82.linkedVP.325+9de5d4ff",
40
+ "@sphereon/ssi-sdk.credential-validation": "0.34.1-feature.SSISDK.82.linkedVP.325+9de5d4ff",
41
+ "@sphereon/ssi-sdk.data-store-types": "0.34.1-feature.SSISDK.82.linkedVP.325+9de5d4ff",
42
+ "@sphereon/ssi-sdk.issuance-branding": "0.34.1-feature.SSISDK.82.linkedVP.325+9de5d4ff",
43
+ "@sphereon/ssi-sdk.pd-manager": "0.34.1-feature.SSISDK.82.linkedVP.325+9de5d4ff",
44
+ "@sphereon/ssi-sdk.presentation-exchange": "0.34.1-feature.SSISDK.82.linkedVP.325+9de5d4ff",
45
+ "@sphereon/ssi-sdk.sd-jwt": "0.34.1-feature.SSISDK.82.linkedVP.325+9de5d4ff",
46
+ "@sphereon/ssi-sdk.siopv2-oid4vp-common": "0.34.1-feature.SSISDK.82.linkedVP.325+9de5d4ff",
47
+ "@sphereon/ssi-sdk.xstate-machine-persistence": "0.34.1-feature.SSISDK.82.linkedVP.325+9de5d4ff",
48
+ "@sphereon/ssi-types": "0.34.1-feature.SSISDK.82.linkedVP.325+9de5d4ff",
49
49
  "@sphereon/wellknown-dids-client": "^0.1.3",
50
50
  "@veramo/core": "4.2.0",
51
51
  "@veramo/credential-w3c": "4.2.0",
@@ -59,8 +59,8 @@
59
59
  },
60
60
  "devDependencies": {
61
61
  "@sphereon/did-uni-client": "^0.6.3",
62
- "@sphereon/ssi-sdk-ext.did-resolver-jwk": "0.34.1-feature.SSISDK.78.306+9aff176a",
63
- "@sphereon/ssi-sdk.agent-config": "0.34.1-feature.SSISDK.78.306+9aff176a",
62
+ "@sphereon/ssi-sdk-ext.did-resolver-jwk": "0.34.1-feature.SSISDK.82.linkedVP.325+9de5d4ff",
63
+ "@sphereon/ssi-sdk.agent-config": "0.34.1-feature.SSISDK.82.linkedVP.325+9de5d4ff",
64
64
  "@types/i18n-js": "^3.8.9",
65
65
  "@types/lodash.memoize": "^4.1.9",
66
66
  "@types/sha.js": "^2.4.4",
@@ -102,5 +102,5 @@
102
102
  "OpenID Connect",
103
103
  "Authenticator"
104
104
  ],
105
- "gitHead": "9aff176afa613d6f69fb1ff33d4f6c8c7b811ffd"
105
+ "gitHead": "9de5d4ff0d17685351d63a9685ec853f6add2d6c"
106
106
  }
@@ -1,23 +1,13 @@
1
1
  import { AuthorizationRequest } from '@sphereon/did-auth-siop'
2
- import type { PartialSdJwtDecodedVerifiableCredential, PartialSdJwtKbJwt } from '@sphereon/pex/dist/main/lib/index.js'
3
- import { calculateSdHash } from '@sphereon/pex/dist/main/lib/utils/index.js'
4
2
  import { getOrCreatePrimaryIdentifier, SupportedDidMethodEnum } from '@sphereon/ssi-sdk-ext.did-utils'
5
3
  import { isOID4VCIssuerIdentifier, ManagedIdentifierOptsOrResult } from '@sphereon/ssi-sdk-ext.identifier-resolution'
6
4
  import { encodeJoseBlob } from '@sphereon/ssi-sdk.core'
7
5
  import { UniqueDigitalCredential, verifiableCredentialForRoleFilter } from '@sphereon/ssi-sdk.credential-store'
8
6
  import { ConnectionType } from '@sphereon/ssi-sdk.data-store-types'
9
- import { defaultGenerateDigest } from '@sphereon/ssi-sdk.sd-jwt'
10
- import {
11
- CredentialMapper,
12
- CredentialRole,
13
- HasherSync,
14
- Loggers,
15
- OriginalVerifiableCredential,
16
- SdJwtDecodedVerifiableCredential,
17
- } from '@sphereon/ssi-types'
7
+ import { CredentialMapper, CredentialRole, HasherSync, Loggers, OriginalVerifiableCredential } from '@sphereon/ssi-types'
18
8
  import { IAgentContext, IDIDManager } from '@veramo/core'
19
9
  import { DcqlPresentation, DcqlQuery } from 'dcql'
20
- import { OpSession } from '../session'
10
+ import { createVerifiablePresentationForFormat, OpSession, PresentationBuilderContext } from '../session'
21
11
  import { LOGGER_NAMESPACE, RequiredContext, SelectableCredential, SelectableCredentialsMap, Siopv2HolderEvent } from '../types'
22
12
  import { convertToDcqlCredentials } from '../utils/dcql'
23
13
 
@@ -81,15 +71,18 @@ export const siopSendAuthorizationResponse = async (
81
71
  let identifier: ManagedIdentifierOptsOrResult
82
72
  const digitalCredential = firstUniqueDC.digitalCredential
83
73
  const firstVC = firstUniqueDC.uniformVerifiableCredential
84
- const holder = CredentialMapper.isSdJwtDecodedCredential(firstVC)
85
- ? firstVC.decodedPayload.cnf?.jwk
86
- ? //TODO SDK-19: convert the JWK to hex and search for the appropriate key and associated DID
87
- //doesn't apply to did:jwk only, as you can represent any DID key as a JWK. So whenever you encounter a JWK it doesn't mean it had to come from a did:jwk in the system. It just can always be represented as a did:jwk
88
- `did:jwk:${encodeJoseBlob(firstVC.decodedPayload.cnf?.jwk)}#0`
89
- : firstVC.decodedPayload.sub
90
- : Array.isArray(firstVC.credentialSubject)
91
- ? firstVC.credentialSubject[0].id
92
- : firstVC.credentialSubject.id
74
+
75
+ // Determine holder DID for identifier resolution
76
+ let holder: string | undefined
77
+ if (CredentialMapper.isSdJwtDecodedCredential(firstVC)) {
78
+ // TODO SDK-19: convert the JWK to hex and search for the appropriate key and associated DID
79
+ // doesn't apply to did:jwk only, as you can represent any DID key as a
80
+ holder = firstVC.decodedPayload.cnf?.jwk ? `did:jwk:${encodeJoseBlob(firstVC.decodedPayload.cnf?.jwk)}#0` : firstVC.decodedPayload.sub
81
+ } else {
82
+ holder = Array.isArray(firstVC.credentialSubject) ? firstVC.credentialSubject[0].id : firstVC.credentialSubject.id
83
+ }
84
+
85
+ // Resolve identifier
93
86
  if (!digitalCredential.kmsKeyRef) {
94
87
  // In case the store does not have the kmsKeyRef lets search for the holder
95
88
 
@@ -132,39 +125,34 @@ export const siopSendAuthorizationResponse = async (
132
125
  return Promise.reject(Error('Credentials do not match required query request'))
133
126
  }
134
127
 
128
+ // Build presentation context for format-aware VP creation
129
+ const presentationContext: PresentationBuilderContext = {
130
+ nonce: request.requestObject?.getPayload()?.nonce ?? session.nonce,
131
+ audience: domain,
132
+ agent: context.agent,
133
+ clockSkew: CLOCK_SKEW,
134
+ hasher: args.hasher,
135
+ }
136
+
137
+ // Build DCQL presentation with format-aware VPs
135
138
  const presentation: DcqlPresentation.Output = {}
136
139
  const uniqueCredentials = Array.from(dcqlCredentialsWithCredentials.values())
137
140
  for (const [key, value] of Object.entries(queryResult.credential_matches)) {
138
141
  if (value.success) {
139
142
  const matchedCredentials = value.valid_credentials.map((cred) => uniqueCredentials[cred.input_credential_index])
140
- const vc = matchedCredentials[0] // taking the first match for now //uniqueCredentials[value.input_credential_index]
143
+ const vc = matchedCredentials[0] // taking the first match for now
144
+
141
145
  if (!vc) {
142
146
  continue
143
147
  }
144
- const originalVc = retrieveEncodedCredential(vc as UniqueDigitalCredential) // TODO this is not nice // also always a UniqueDigitalCredential
145
- if (!originalVc) {
146
- continue
147
- }
148
- // FIXME SSISDK-44
149
- const decodedSdJwt = await CredentialMapper.decodeSdJwtVcAsync(originalVc as string, defaultGenerateDigest)
150
- const updatedSdJwt = updateSdJwtCredential(decodedSdJwt, request.requestObject?.getPayload()?.nonce, domain)
151
-
152
- const presentationResult = await context.agent.createSdJwtPresentation({
153
- presentation: updatedSdJwt.compactSdJwtVc,
154
- kb: {
155
- payload: {
156
- ...updatedSdJwt.kbJwt?.payload,
157
- // FIXME SSISDK-44
158
- nonce: updatedSdJwt.kbJwt?.payload.nonce ?? request.requestObject!.getPayload()!.nonce,
159
- // FIXME SSISDK-44
160
- aud: updatedSdJwt.kbJwt?.payload.aud ?? domain,
161
- iat: updatedSdJwt.kbJwt?.payload?.iat ?? Math.floor(Date.now() / 1000 - CLOCK_SKEW),
162
- },
163
- },
164
- })
165
148
 
166
- if (originalVc) {
167
- presentation[key] = presentationResult.presentation
149
+ try {
150
+ // Use format-aware presentation builder
151
+ const vp = await createVerifiablePresentationForFormat(vc, identifier, presentationContext)
152
+ presentation[key] = vp as any
153
+ } catch (error) {
154
+ logger.error(`Failed to create VP for credential ${key}:`, error)
155
+ throw error
168
156
  }
169
157
  }
170
158
  }
@@ -182,15 +170,6 @@ export const siopSendAuthorizationResponse = async (
182
170
  return response
183
171
  }
184
172
 
185
- const retrieveEncodedCredential = (credential: UniqueDigitalCredential): OriginalVerifiableCredential | undefined => {
186
- return credential.originalVerifiableCredential !== undefined &&
187
- credential.originalVerifiableCredential !== null &&
188
- (credential?.originalVerifiableCredential as SdJwtDecodedVerifiableCredential)?.compactSdJwtVc !== undefined &&
189
- (credential?.originalVerifiableCredential as SdJwtDecodedVerifiableCredential)?.compactSdJwtVc !== null
190
- ? (credential.originalVerifiableCredential as SdJwtDecodedVerifiableCredential).compactSdJwtVc
191
- : credential.originalVerifiableCredential
192
- }
193
-
194
173
  export const getSelectableCredentials = async (dcqlQuery: DcqlQuery, context: RequiredContext): Promise<SelectableCredentialsMap> => {
195
174
  const agentContext = { ...context, agent: context.agent }
196
175
  const { agent } = agentContext
@@ -246,33 +225,3 @@ export const translateCorrelationIdToName = async (correlationId: string, contex
246
225
 
247
226
  return contacts[0].contact.displayName
248
227
  }
249
-
250
- const updateSdJwtCredential = (
251
- credential: SdJwtDecodedVerifiableCredential,
252
- nonce?: string,
253
- aud?: string,
254
- ): PartialSdJwtDecodedVerifiableCredential => {
255
- const sdJwtCredential = credential as SdJwtDecodedVerifiableCredential
256
-
257
- // extract sd_alg or default to sha-256
258
- const hashAlg = sdJwtCredential.signedPayload._sd_alg ?? 'sha-256'
259
- const sdHash = calculateSdHash(sdJwtCredential.compactSdJwtVc, hashAlg, defaultGenerateDigest)
260
-
261
- const kbJwt = {
262
- // alg MUST be set by the signer
263
- header: {
264
- typ: 'kb+jwt',
265
- },
266
- payload: {
267
- iat: Math.floor(new Date().getTime() / 1000),
268
- sd_hash: sdHash,
269
- ...(nonce && { nonce }),
270
- ...(aud && { aud }),
271
- },
272
- } satisfies PartialSdJwtKbJwt
273
-
274
- return {
275
- ...sdJwtCredential,
276
- kbJwt,
277
- } satisfies PartialSdJwtDecodedVerifiableCredential
278
- }