@sphereon/ssi-sdk.siopv2-oid4vp-rp-auth 0.34.1-feat.SSISDK.35.64 → 0.34.1-feat.SSISDK.55.244

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.
@@ -3,10 +3,15 @@ import {
3
3
  AuthorizationResponsePayload,
4
4
  AuthorizationResponseState,
5
5
  AuthorizationResponseStateStatus,
6
+ AuthorizationResponseStateWithVerifiedData,
6
7
  decodeUriAsJson,
7
- VerifiedAuthorizationResponse,
8
+ EncodedDcqlPresentationVpToken,
9
+ VerifiedAuthorizationResponse
8
10
  } from '@sphereon/did-auth-siop'
9
11
  import { getAgentResolver } from '@sphereon/ssi-sdk-ext.did-utils'
12
+ import { shaHasher as defaultHasher } from '@sphereon/ssi-sdk.core'
13
+ import { validate as isValidUUID } from 'uuid'
14
+ import type { ImportDcqlQueryItem } from '@sphereon/ssi-sdk.pd-manager'
10
15
  import {
11
16
  AdditionalClaims,
12
17
  CredentialMapper,
@@ -19,11 +24,11 @@ import {
19
24
  MdocDeviceResponse,
20
25
  MdocOid4vpMdocVpToken,
21
26
  OriginalVerifiablePresentation,
22
- SdJwtDecodedVerifiableCredential,
27
+ SdJwtDecodedVerifiableCredential
23
28
  } from '@sphereon/ssi-types'
24
29
  import { IAgentPlugin } from '@veramo/core'
30
+ import { DcqlQuery } from 'dcql'
25
31
  import {
26
- AuthorizationResponseStateWithVerifiedData,
27
32
  IAuthorizationRequestPayloads,
28
33
  ICreateAuthRequestArgs,
29
34
  IGetAuthRequestStateArgs,
@@ -38,14 +43,10 @@ import {
38
43
  ISiopv2RPOpts,
39
44
  IUpdateRequestStateArgs,
40
45
  IVerifyAuthResponseStateArgs,
41
- schema,
42
- VerifiedDataMode,
46
+ schema
43
47
  } from '../index'
44
48
  import { RPInstance } from '../RPInstance'
45
-
46
49
  import { ISIOPv2RP } from '../types/ISIOPv2RP'
47
- import { shaHasher as defaultHasher } from '@sphereon/ssi-sdk.core'
48
- import { DcqlQuery } from 'dcql'
49
50
 
50
51
  export class SIOPv2RP implements IAgentPlugin {
51
52
  private readonly opts: ISiopv2RPOpts
@@ -85,7 +86,14 @@ export class SIOPv2RP implements IAgentPlugin {
85
86
  }
86
87
 
87
88
  private async createAuthorizationRequestURI(createArgs: ICreateAuthRequestArgs, context: IRequiredContext): Promise<string> {
88
- return await this.getRPInstance({ definitionId: createArgs.definitionId, responseRedirectURI: createArgs.responseRedirectURI }, context)
89
+ return await this.getRPInstance(
90
+ {
91
+ createWhenNotPresent: true,
92
+ responseRedirectURI: createArgs.responseRedirectURI,
93
+ ...(createArgs.useQueryIdInstance === true && { queryId: createArgs.queryId } ),
94
+ },
95
+ context,
96
+ )
89
97
  .then((rp) => rp.createAuthorizationRequestURI(createArgs, context))
90
98
  .then((URI) => URI.encodedUri)
91
99
  }
@@ -94,21 +102,23 @@ export class SIOPv2RP implements IAgentPlugin {
94
102
  createArgs: ICreateAuthRequestArgs,
95
103
  context: IRequiredContext,
96
104
  ): Promise<IAuthorizationRequestPayloads> {
97
- return await this.getRPInstance({ definitionId: createArgs.definitionId }, context)
105
+ return await this.getRPInstance({ createWhenNotPresent: true, queryId: createArgs.queryId }, context)
98
106
  .then((rp) => rp.createAuthorizationRequest(createArgs, context))
99
107
  .then(async (request) => {
100
108
  const authRequest: IAuthorizationRequestPayloads = {
101
109
  authorizationRequest: request.payload,
102
110
  requestObject: await request.requestObjectJwt(),
103
- requestObjectDecoded: await request.requestObject?.getPayload(),
111
+ requestObjectDecoded: request.requestObject?.getPayload(),
104
112
  }
105
113
  return authRequest
106
114
  })
107
115
  }
108
116
 
109
117
  private async siopGetRequestState(args: IGetAuthRequestStateArgs, context: IRequiredContext): Promise<AuthorizationRequestState | undefined> {
110
- return await this.getRPInstance({ definitionId: args.definitionId }, context).then((rp) =>
111
- rp.get(context).then((rp) => rp.sessionManager.getRequestStateByCorrelationId(args.correlationId, args.errorOnNotFound)),
118
+ return await this.getRPInstance({ createWhenNotPresent: false, queryId: args.queryId }, context).then((rp) =>
119
+ rp.get(context).then((rp) =>
120
+ rp.sessionManager.getRequestStateByCorrelationId(args.correlationId, args.errorOnNotFound)
121
+ ),
112
122
  )
113
123
  }
114
124
 
@@ -116,7 +126,7 @@ export class SIOPv2RP implements IAgentPlugin {
116
126
  args: IGetAuthResponseStateArgs,
117
127
  context: IRequiredContext,
118
128
  ): Promise<AuthorizationResponseStateWithVerifiedData | undefined> {
119
- const rpInstance: RPInstance = await this.getRPInstance({ definitionId: args.definitionId }, context)
129
+ const rpInstance: RPInstance = await this.getRPInstance({ createWhenNotPresent: false, queryId: args.queryId }, context)
120
130
  const authorizationResponseState: AuthorizationResponseState | undefined = await rpInstance
121
131
  .get(context)
122
132
  .then((rp) => rp.sessionManager.getResponseStateByCorrelationId(args.correlationId, args.errorOnNotFound))
@@ -125,11 +135,7 @@ export class SIOPv2RP implements IAgentPlugin {
125
135
  }
126
136
 
127
137
  const responseState = authorizationResponseState as AuthorizationResponseStateWithVerifiedData
128
- if (
129
- responseState.status === AuthorizationResponseStateStatus.VERIFIED &&
130
- args.includeVerifiedData &&
131
- args.includeVerifiedData !== VerifiedDataMode.NONE
132
- ) {
138
+ if (responseState.status === AuthorizationResponseStateStatus.VERIFIED) {
133
139
  let hasher: HasherSync | undefined
134
140
  if (
135
141
  CredentialMapper.isSdJwtEncoded(responseState.response.payload.vp_token as OriginalVerifiablePresentation) &&
@@ -137,19 +143,23 @@ export class SIOPv2RP implements IAgentPlugin {
137
143
  ) {
138
144
  hasher = defaultHasher
139
145
  }
140
- // todo this should also include mdl-mdoc
141
- const presentationDecoded = CredentialMapper.decodeVerifiablePresentation(
142
- responseState.response.payload.vp_token as OriginalVerifiablePresentation,
143
- //todo: later we want to conditionally pass in options for mdl-mdoc here
144
- hasher,
145
- )
146
- switch (args.includeVerifiedData) {
147
- case VerifiedDataMode.VERIFIED_PRESENTATION:
148
- responseState.response.payload.verifiedData = this.presentationOrClaimsFrom(presentationDecoded)
149
- break
150
- case VerifiedDataMode.CREDENTIAL_SUBJECT_FLATTENED: // TODO debug cs-flat for SD-JWT
151
- const allClaims: AdditionalClaims = {}
152
- for (const credential of this.presentationOrClaimsFrom(presentationDecoded).verifiableCredential || []) {
146
+
147
+ // FIXME SSISDK-64 currently assuming that all vp tokens are or type EncodedDcqlPresentationVpToken as we only work with DCQL now. But the types still indicate it can be another type of vp token
148
+ const vpToken = responseState.response.payload.vp_token && JSON.parse(responseState.response.payload.vp_token as EncodedDcqlPresentationVpToken)
149
+ const claims = []
150
+ for (const [key, value] of Object.entries(vpToken)) {
151
+ // todo this should also include mdl-mdoc
152
+ const presentationDecoded = CredentialMapper.decodeVerifiablePresentation(
153
+ value as OriginalVerifiablePresentation,
154
+ //todo: later we want to conditionally pass in options for mdl-mdoc here
155
+ hasher,
156
+ )
157
+ console.log(`presentationDecoded: ${JSON.stringify(presentationDecoded)}`)
158
+
159
+ const allClaims: AdditionalClaims = {}
160
+ const presentationOrClaims = this.presentationOrClaimsFrom(presentationDecoded)
161
+ if ('verifiableCredential' in presentationOrClaims) {
162
+ for (const credential of presentationOrClaims.verifiableCredential) {
153
163
  const vc = credential as IVerifiableCredential
154
164
  const schemaValidationResult = await context.agent.cvVerifySchema({
155
165
  credential,
@@ -172,11 +182,34 @@ export class SIOPv2RP implements IAgentPlugin {
172
182
  allClaims[key] = value
173
183
  }
174
184
  })
185
+
186
+ claims.push({
187
+ id: key,
188
+ type: vc.type[0],
189
+ claims: allClaims
190
+ })
191
+ }
192
+ } else {
193
+ claims.push({
194
+ id: key,
195
+ type: (presentationDecoded as SdJwtDecodedVerifiableCredential).decodedPayload.vct,
196
+ claims: presentationOrClaims
197
+ })
198
+ }
199
+ }
200
+
201
+ responseState.verifiedData = {
202
+ ...(responseState.response.payload.vp_token && {
203
+ authorization_response: {
204
+ vp_token: typeof responseState.response.payload.vp_token === 'string'
205
+ ? JSON.parse(responseState.response.payload.vp_token)
206
+ : responseState.response.payload.vp_token
175
207
  }
176
- responseState.verifiedData = allClaims
177
- break
208
+ }),
209
+ ...(claims.length > 0 && { credential_claims: claims })
178
210
  }
179
211
  }
212
+
180
213
  return responseState
181
214
  }
182
215
 
@@ -186,17 +219,18 @@ export class SIOPv2RP implements IAgentPlugin {
186
219
  | IVerifiablePresentation
187
220
  | SdJwtDecodedVerifiableCredential
188
221
  | MdocOid4vpMdocVpToken
189
- | MdocDeviceResponse,
190
- ): AdditionalClaims | IPresentation =>
191
- CredentialMapper.isSdJwtDecodedCredential(presentationDecoded)
222
+ | MdocDeviceResponse
223
+ ): AdditionalClaims | IPresentation => {
224
+ return CredentialMapper.isSdJwtDecodedCredential(presentationDecoded)
192
225
  ? presentationDecoded.decodedPayload
193
226
  : CredentialMapper.toUniformPresentation(presentationDecoded as OriginalVerifiablePresentation)
227
+ }
194
228
 
195
229
  private async siopUpdateRequestState(args: IUpdateRequestStateArgs, context: IRequiredContext): Promise<AuthorizationRequestState> {
196
- if (args.state !== 'sent') {
197
- throw Error(`Only 'sent' status is supported for this method at this point`)
230
+ if (args.state !== 'authorization_request_created') {
231
+ throw Error(`Only 'authorization_request_created' status is supported for this method at this point`)
198
232
  }
199
- return await this.getRPInstance({ definitionId: args.definitionId }, context)
233
+ return await this.getRPInstance({ createWhenNotPresent: false, queryId: args.queryId }, context)
200
234
  // todo: In the SIOP library we need to update the signal method to be more like this method
201
235
  .then((rp) =>
202
236
  rp.get(context).then(async (rp) => {
@@ -210,7 +244,7 @@ export class SIOPv2RP implements IAgentPlugin {
210
244
  }
211
245
 
212
246
  private async siopDeleteState(args: IGetAuthResponseStateArgs, context: IRequiredContext): Promise<boolean> {
213
- return await this.getRPInstance({ definitionId: args.definitionId }, context)
247
+ return await this.getRPInstance({ createWhenNotPresent: false, queryId: args.queryId }, context)
214
248
  .then((rp) => rp.get(context).then((rp) => rp.sessionManager.deleteStateForCorrelationId(args.correlationId)))
215
249
  .then(() => true)
216
250
  }
@@ -223,32 +257,30 @@ export class SIOPv2RP implements IAgentPlugin {
223
257
  typeof args.authorizationResponse === 'string'
224
258
  ? (decodeUriAsJson(args.authorizationResponse) as AuthorizationResponsePayload)
225
259
  : args.authorizationResponse
226
- return await this.getRPInstance({ definitionId: args.definitionId }, context).then((rp) =>
260
+ return await this.getRPInstance({ createWhenNotPresent: false, queryId: args.queryId }, context).then((rp) =>
227
261
  rp.get(context).then((rp) =>
228
262
  rp.verifyAuthorizationResponse(authResponse, {
229
263
  correlationId: args.correlationId,
230
- ...(args.presentationDefinitions && !args.dcqlQuery ? { presentationDefinitions: args.presentationDefinitions } : {}),
231
- ...(args.dcqlQuery ? { dcqlQuery: args.dcqlQuery as DcqlQuery } : {}), // TODO BEFORE PR, check compatibility and whether we can remove local type
232
- audience: args.audience,
264
+ ...(args.dcqlQuery && { dcqlQuery: args.dcqlQuery }),
265
+ audience: args.audience,
233
266
  }),
234
267
  ),
235
268
  )
236
269
  }
237
270
 
238
271
  private async siopImportDefinitions(args: ImportDefinitionsArgs, context: IRequiredContext): Promise<void> {
239
- const { definitions, tenantId, version, versionControlMode } = args
272
+ const { importItems, tenantId, version, versionControlMode } = args
240
273
  await Promise.all(
241
- definitions.map(async (definitionPair) => {
242
- const definitionPayload = definitionPair.definitionPayload
243
- await context.agent.pexValidateDefinition({ definition: definitionPayload })
274
+ importItems.map(async (importItem: ImportDcqlQueryItem) => {
275
+ DcqlQuery.validate(importItem.query)
276
+ console.log(`persisting DCQL definition ${importItem.queryId} with versionControlMode ${versionControlMode}`)
244
277
 
245
- console.log(`persisting definition ${definitionPayload.id} / ${definitionPayload.name} with versionControlMode ${versionControlMode}`)
246
278
  return context.agent.pdmPersistDefinition({
247
279
  definitionItem: {
280
+ queryId: importItem.queryId!,
248
281
  tenantId: tenantId,
249
282
  version: version,
250
- definitionPayload,
251
- dcqlPayload: definitionPair.dcqlPayload,
283
+ query: importItem.query,
252
284
  },
253
285
  opts: { versionControlMode: versionControlMode },
254
286
  })
@@ -257,7 +289,7 @@ export class SIOPv2RP implements IAgentPlugin {
257
289
  }
258
290
 
259
291
  private async siopGetRedirectURI(args: IGetRedirectUriArgs, context: IRequiredContext): Promise<string | undefined> {
260
- const instanceId = args.definitionId ?? SIOPv2RP._DEFAULT_OPTS_KEY
292
+ const instanceId = args.queryId ?? SIOPv2RP._DEFAULT_OPTS_KEY
261
293
  if (this.instances.has(instanceId)) {
262
294
  const rpInstance = this.instances.get(instanceId)
263
295
  if (rpInstance !== undefined) {
@@ -272,37 +304,64 @@ export class SIOPv2RP implements IAgentPlugin {
272
304
  return undefined
273
305
  }
274
306
 
275
- async getRPInstance({ definitionId, responseRedirectURI }: ISiopRPInstanceArgs, context: IRequiredContext): Promise<RPInstance> {
276
- const instanceId = definitionId ?? SIOPv2RP._DEFAULT_OPTS_KEY
277
- if (!this.instances.has(instanceId)) {
278
- const instanceOpts = this.getInstanceOpts(definitionId)
279
- const rpOpts = await this.getRPOptions(context, { definitionId, responseRedirectURI: responseRedirectURI })
307
+ async getRPInstance({ createWhenNotPresent, queryId, responseRedirectURI }: ISiopRPInstanceArgs, context: IRequiredContext): Promise<RPInstance> {
308
+ let rpInstanceId: string = SIOPv2RP._DEFAULT_OPTS_KEY
309
+ let rpInstance: RPInstance | undefined
310
+ if (queryId) {
311
+ if (this.instances.has(queryId)) {
312
+ rpInstanceId = queryId
313
+ rpInstance = this.instances.get(rpInstanceId)!
314
+ } else if (isValidUUID(queryId)) {
315
+ try {
316
+ // Check whether queryId is actually the PD item id
317
+ const pd = await context.agent.pdmGetDefinition({ itemId: queryId })
318
+ if (this.instances.has(pd.queryId)) {
319
+ rpInstanceId = pd.queryId
320
+ rpInstance = this.instances.get(rpInstanceId)!
321
+ }
322
+ } catch (ignore) {}
323
+ }
324
+ if (createWhenNotPresent) {
325
+ rpInstanceId = queryId
326
+ } else {
327
+ rpInstance = this.instances.get(rpInstanceId)
328
+ }
329
+ } else {
330
+ rpInstance = this.instances.get(rpInstanceId)
331
+ }
332
+
333
+ if (!rpInstance) {
334
+ if (!createWhenNotPresent) {
335
+ return Promise.reject(`No RP instance found for key ${rpInstanceId}`)
336
+ }
337
+ const instanceOpts = this.getInstanceOpts(queryId)
338
+ const rpOpts = await this.getRPOptions(context, { queryId, responseRedirectURI: responseRedirectURI })
280
339
  if (!rpOpts.identifierOpts.resolveOpts?.resolver || typeof rpOpts.identifierOpts.resolveOpts.resolver.resolve !== 'function') {
281
340
  if (!rpOpts.identifierOpts?.resolveOpts) {
282
341
  rpOpts.identifierOpts = { ...rpOpts.identifierOpts }
283
342
  rpOpts.identifierOpts.resolveOpts = { ...rpOpts.identifierOpts.resolveOpts }
284
343
  }
285
- console.log('Using agent DID resolver for RP instance with definition id ' + definitionId)
344
+ console.log('Using agent DID resolver for RP instance with definition id ' + queryId)
286
345
  rpOpts.identifierOpts.resolveOpts.resolver = getAgentResolver(context, {
287
346
  uniresolverResolution: true,
288
347
  localResolution: true,
289
348
  resolverResolution: true,
290
349
  })
291
350
  }
292
- this.instances.set(instanceId, new RPInstance({ rpOpts, pexOpts: instanceOpts }))
351
+ rpInstance = new RPInstance({ rpOpts, pexOpts: instanceOpts })
352
+ this.instances.set(rpInstanceId, rpInstance)
293
353
  }
294
- const rpInstance = this.instances.get(instanceId)!
295
354
  if (responseRedirectURI) {
296
355
  rpInstance.rpOptions.responseRedirectUri = responseRedirectURI
297
356
  }
298
357
  return rpInstance
299
358
  }
300
359
 
301
- async getRPOptions(context: IRequiredContext, opts: { definitionId?: string; responseRedirectURI?: string }): Promise<IRPOptions> {
302
- const { definitionId, responseRedirectURI: responseRedirectURI } = opts
303
- const options = this.getInstanceOpts(definitionId)?.rpOpts ?? this.opts.defaultOpts
360
+ async getRPOptions(context: IRequiredContext, opts: { queryId?: string; responseRedirectURI?: string }): Promise<IRPOptions> {
361
+ const { queryId, responseRedirectURI: responseRedirectURI } = opts
362
+ const options = this.getInstanceOpts(queryId)?.rpOpts ?? this.opts.defaultOpts
304
363
  if (!options) {
305
- throw Error(`Could not get specific nor default options for definition ${definitionId}`)
364
+ throw Error(`Could not get specific nor default options for definition ${queryId}`)
306
365
  }
307
366
  if (this.opts.defaultOpts) {
308
367
  if (!options.identifierOpts) {
@@ -333,22 +392,22 @@ export class SIOPv2RP implements IAgentPlugin {
333
392
  return options
334
393
  }
335
394
 
336
- getInstanceOpts(definitionId?: string): IPEXInstanceOptions | undefined {
395
+ getInstanceOpts(queryId?: string): IPEXInstanceOptions | undefined {
337
396
  if (!this.opts.instanceOpts) return undefined
338
397
 
339
- const instanceOpt = definitionId ? this.opts.instanceOpts.find((i) => i.definitionId === definitionId) : undefined
398
+ const instanceOpt = queryId ? this.opts.instanceOpts.find((i) => i.queryId === queryId) : undefined
340
399
 
341
- return instanceOpt ?? this.getDefaultOptions(definitionId)
400
+ return instanceOpt ?? this.getDefaultOptions(queryId)
342
401
  }
343
402
 
344
- private getDefaultOptions(definitionId: string | undefined) {
403
+ private getDefaultOptions(queryId: string | undefined) {
345
404
  if (!this.opts.instanceOpts) return undefined
346
405
 
347
- const defaultOptions = this.opts.instanceOpts.find((i) => i.definitionId === 'default')
406
+ const defaultOptions = this.opts.instanceOpts.find((i) => i.queryId === 'default')
348
407
  if (defaultOptions) {
349
408
  const clonedOptions = { ...defaultOptions }
350
- if (definitionId !== undefined) {
351
- clonedOptions.definitionId = definitionId
409
+ if (queryId !== undefined) {
410
+ clonedOptions.queryId = queryId
352
411
  }
353
412
  return clonedOptions
354
413
  }
package/src/functions.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import {
2
- ClientIdScheme,
2
+ ClientIdentifierPrefix,
3
3
  ClientMetadataOpts,
4
+ DcqlQueryLookupCallback,
4
5
  InMemoryRPSessionManager,
5
6
  PassBy,
6
7
  PresentationVerificationCallback,
@@ -28,14 +29,13 @@ import {
28
29
  } from '@sphereon/ssi-sdk-ext.identifier-resolution'
29
30
  import { JwtCompactResult } from '@sphereon/ssi-sdk-ext.jwt-service'
30
31
  import { IVerifySdJwtPresentationResult } from '@sphereon/ssi-sdk.sd-jwt'
31
- import { CredentialMapper, Hasher, OriginalVerifiableCredential, PresentationSubmission } from '@sphereon/ssi-types'
32
+ import { CredentialMapper, HasherSync, OriginalVerifiableCredential, PresentationSubmission } from '@sphereon/ssi-types'
32
33
  import { IVerifyCallbackArgs, IVerifyCredentialResult, VerifyCallback } from '@sphereon/wellknown-dids-client'
33
- // import { KeyAlgo, SuppliedSigner } from '@sphereon/ssi-sdk.core'
34
34
  import { TKeyType } from '@veramo/core'
35
35
  import { JWTVerifyOptions } from 'did-jwt'
36
36
  import { Resolvable } from 'did-resolver'
37
37
  import { EventEmitter } from 'events'
38
- import { IPEXOptions, IRequiredContext, IRPOptions, ISIOPIdentifierOptions } from './types/ISIOPv2RP'
38
+ import { IRequiredContext, IRPOptions, ISIOPIdentifierOptions } from './types/ISIOPv2RP'
39
39
  import { DcqlQuery } from 'dcql'
40
40
  import { defaultHasher } from '@sphereon/ssi-sdk.core'
41
41
 
@@ -43,7 +43,7 @@ export function getRequestVersion(rpOptions: IRPOptions): SupportedVersion {
43
43
  if (Array.isArray(rpOptions.supportedVersions) && rpOptions.supportedVersions.length > 0) {
44
44
  return rpOptions.supportedVersions[0]
45
45
  }
46
- return SupportedVersion.JWT_VC_PRESENTATION_PROFILE_v1
46
+ return SupportedVersion.OID4VP_v1
47
47
  }
48
48
 
49
49
  function getWellKnownDIDVerifyCallback(siopIdentifierOpts: ISIOPIdentifierOptions, context: IRequiredContext) {
@@ -58,6 +58,31 @@ function getWellKnownDIDVerifyCallback(siopIdentifierOpts: ISIOPIdentifierOption
58
58
  }
59
59
  }
60
60
 
61
+ export function getDcqlQueryLookupCallback(context: IRequiredContext): DcqlQueryLookupCallback {
62
+ async function dcqlQueryLookup(queryId: string, version?: string, tenantId?: string): Promise<DcqlQuery> {
63
+ // TODO Add caching?
64
+ const result = await context.agent.pdmGetDefinitions({
65
+ filter: [
66
+ {
67
+ queryId,
68
+ ...(tenantId && { tenantId }),
69
+ ...(version && { version }),
70
+ },
71
+ {
72
+ id: queryId,
73
+ },
74
+ ],
75
+ })
76
+ if (result && result.length > 0) {
77
+ return result[0].query
78
+ }
79
+
80
+ return Promise.reject(Error(`No dcql query found for queryId ${queryId}`))
81
+ }
82
+
83
+ return dcqlQueryLookup
84
+ }
85
+
61
86
  export function getPresentationVerificationCallback(
62
87
  idOpts: ManagedIdentifierOptsOrResult,
63
88
  context: IRequiredContext,
@@ -69,7 +94,6 @@ export function getPresentationVerificationCallback(
69
94
  if (CredentialMapper.isSdJwtEncoded(args)) {
70
95
  const result: IVerifySdJwtPresentationResult = await context.agent.verifySdJwtPresentation({
71
96
  presentation: args,
72
- kb: true,
73
97
  })
74
98
  // fixme: investigate the correct way to handle this
75
99
  return { verified: !!result.payload }
@@ -103,35 +127,11 @@ export function getPresentationVerificationCallback(
103
127
 
104
128
  export async function createRPBuilder(args: {
105
129
  rpOpts: IRPOptions
106
- pexOpts?: IPEXOptions | undefined
107
130
  definition?: IPresentationDefinition
108
- dcql?: DcqlQuery
109
131
  context: IRequiredContext
110
132
  }): Promise<RPBuilder> {
111
- const { rpOpts, pexOpts, context } = args
133
+ const { rpOpts, context } = args
112
134
  const { identifierOpts } = rpOpts
113
- let definition: IPresentationDefinition | undefined = args.definition
114
- let dcqlQuery: DcqlQuery | undefined = args.dcql
115
-
116
- if (!definition && pexOpts && pexOpts.definitionId) {
117
- const presentationDefinitionItems = await context.agent.pdmGetDefinitions({
118
- filter: [
119
- {
120
- definitionId: pexOpts.definitionId,
121
- version: pexOpts.version,
122
- tenantId: pexOpts.tenantId,
123
- },
124
- ],
125
- })
126
-
127
- if (presentationDefinitionItems.length > 0) {
128
- const presentationDefinitionItem = presentationDefinitionItems[0]
129
- definition = presentationDefinitionItem.definitionPayload
130
- if (!dcqlQuery && presentationDefinitionItem.dcqlPayload) {
131
- dcqlQuery = presentationDefinitionItem.dcqlPayload as DcqlQuery // cast from DcqlQueryREST back to valibot DcqlQuery
132
- }
133
- }
134
- }
135
135
 
136
136
  const didMethods = identifierOpts.supportedDIDMethods ?? (await getAgentDIDMethods(context))
137
137
  const eventEmitter = rpOpts.eventEmitter ?? new EventEmitter()
@@ -161,7 +161,7 @@ export async function createRPBuilder(args: {
161
161
  uniresolverResolution: rpOpts.identifierOpts.resolveOpts?.noUniversalResolverFallback !== true,
162
162
  })
163
163
  //todo: probably wise to first look and see if we actually need the hasher to begin with
164
- let hasher: Hasher | undefined = rpOpts.credentialOpts?.hasher
164
+ let hasher: HasherSync | undefined = rpOpts.credentialOpts?.hasher
165
165
  if (!rpOpts.credentialOpts?.hasher || typeof rpOpts.credentialOpts?.hasher !== 'function') {
166
166
  hasher = defaultHasher
167
167
  }
@@ -171,9 +171,7 @@ export async function createRPBuilder(args: {
171
171
  .withResponseMode(rpOpts.responseMode ?? ResponseMode.POST)
172
172
  .withResponseType(ResponseType.VP_TOKEN, PropertyTarget.REQUEST_OBJECT)
173
173
  // todo: move to options fill/correct method
174
- .withSupportedVersions(
175
- rpOpts.supportedVersions ?? [SupportedVersion.JWT_VC_PRESENTATION_PROFILE_v1, SupportedVersion.SIOPv2_ID1, SupportedVersion.SIOPv2_D11],
176
- )
174
+ .withSupportedVersions(rpOpts.supportedVersions ?? [SupportedVersion.OID4VP_v1, SupportedVersion.SIOPv2_OID4VP_D28])
177
175
 
178
176
  .withEventEmitter(eventEmitter)
179
177
  .withSessionManager(rpOpts.sessionManager ?? new InMemoryRPSessionManager(eventEmitter))
@@ -192,23 +190,21 @@ export async function createRPBuilder(args: {
192
190
  context,
193
191
  ),
194
192
  )
193
+ .withDcqlQueryLookup(getDcqlQueryLookupCallback(context))
195
194
  .withRevocationVerification(RevocationVerification.NEVER)
196
195
  .withPresentationVerification(getPresentationVerificationCallback(identifierOpts.idOpts, context))
197
196
 
198
197
  const oidfOpts = identifierOpts.oidfOpts
199
198
  if (oidfOpts && isExternalIdentifierOIDFEntityIdOpts(oidfOpts)) {
200
- builder.withEntityId(oidfOpts.identifier, PropertyTarget.REQUEST_OBJECT).withClientIdScheme('entity_id', PropertyTarget.REQUEST_OBJECT)
199
+ builder.withEntityId(oidfOpts.identifier, PropertyTarget.REQUEST_OBJECT)
201
200
  } else {
202
201
  const resolution = await context.agent.identifierManagedGet(identifierOpts.idOpts)
203
- builder
204
- .withClientId(
205
- resolution.issuer ?? (isManagedIdentifierDidResult(resolution) ? resolution.did : resolution.jwkThumbprint),
206
- PropertyTarget.REQUEST_OBJECT,
207
- )
208
- .withClientIdScheme(
209
- (resolution.clientIdScheme as ClientIdScheme) ?? (identifierOpts.idOpts.clientIdScheme as ClientIdScheme),
210
- PropertyTarget.REQUEST_OBJECT,
211
- )
202
+ const clientId: string =
203
+ rpOpts.clientMetadataOpts?.client_id ??
204
+ resolution.issuer ??
205
+ (isManagedIdentifierDidResult(resolution) ? resolution.did : resolution.jwkThumbprint)
206
+ const clientIdPrefixed = prefixClientId(clientId)
207
+ builder.withClientId(clientIdPrefixed, PropertyTarget.REQUEST_OBJECT)
212
208
  }
213
209
 
214
210
  if (hasher) {
@@ -222,13 +218,6 @@ export async function createRPBuilder(args: {
222
218
  //fixme: this has been removed in the new version of did-auth-siop
223
219
  // builder.withWellknownDIDVerifyCallback(getWellKnownDIDVerifyCallback(didOpts, context))
224
220
 
225
- if (definition) {
226
- builder.withPresentationDefinition({ definition }, PropertyTarget.REQUEST_OBJECT)
227
- }
228
- if (dcqlQuery) {
229
- builder.withDcqlQuery(dcqlQuery)
230
- }
231
-
232
221
  if (rpOpts.responseRedirectUri) {
233
222
  builder.withResponseRedirectUri(rpOpts.responseRedirectUri)
234
223
  }
@@ -309,3 +298,12 @@ export function getSigningAlgo(type: TKeyType): SigningAlgo {
309
298
  throw Error('Key type not yet supported')
310
299
  }
311
300
  }
301
+
302
+ export function prefixClientId(clientId: string): string {
303
+ // FIXME SSISDK-60
304
+ if (clientId.startsWith('did:')) {
305
+ return `${ClientIdentifierPrefix.DECENTRALIZED_IDENTIFIER}:${clientId}`
306
+ }
307
+
308
+ return clientId
309
+ }
package/src/index.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @public
3
3
  */
4
- const schema = require('../plugin.schema.json')
4
+ import schema from '../plugin.schema.json'
5
5
  export { schema }
6
6
  export { SIOPv2RP } from './agent/SIOPv2RP'
7
7
  export * from './types/ISIOPv2RP'