Skip to content

Commit 8e9cb20

Browse files
committed
feat: Add JARM response support
1 parent 078276d commit 8e9cb20

File tree

14 files changed

+198
-136
lines changed

14 files changed

+198
-136
lines changed

packages/ebsi-support/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
},
1616
"dependencies": {
1717
"@ethersproject/random": "^5.7.0",
18-
"@sphereon/did-auth-siop": "0.16.1-unstable.105",
19-
"@sphereon/did-auth-siop-adapter": "0.16.1-unstable.105",
18+
"@sphereon/did-auth-siop": "0.16.1-unstable.122",
19+
"@sphereon/did-auth-siop-adapter": "0.16.1-unstable.122",
2020
"@sphereon/pex": "5.0.0-unstable.10",
2121
"@sphereon/pex-models": "^2.3.1",
2222
"@sphereon/ssi-sdk-ext.did-resolver-ebsi": "0.24.1-unstable.134",
@@ -44,8 +44,8 @@
4444
"xstate": "^4.38.3"
4545
},
4646
"devDependencies": {
47-
"@sphereon/oid4vci-client": "0.16.1-unstable.105",
48-
"@sphereon/oid4vci-common": "0.16.1-unstable.105",
47+
"@sphereon/oid4vci-client": "0.16.1-unstable.122",
48+
"@sphereon/oid4vci-common": "0.16.1-unstable.122",
4949
"@sphereon/ssi-express-support": "workspace:*",
5050
"@sphereon/ssi-sdk-ext.key-manager": "0.24.1-unstable.134",
5151
"@sphereon/ssi-sdk-ext.kms-local": "0.24.1-unstable.134",

packages/mdl-mdoc/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"build:clean": "tsc --build --clean && tsc --build"
1515
},
1616
"dependencies": {
17-
"@sphereon/did-auth-siop": "0.16.1-unstable.105",
17+
"@sphereon/did-auth-siop": "0.16.1-unstable.122",
1818
"@sphereon/kmp-mdl-mdoc": "0.2.0-SNAPSHOT.22",
1919
"@sphereon/pex": "5.0.0-unstable.10",
2020
"@sphereon/pex-models": "^2.3.1",
@@ -35,8 +35,8 @@
3535
"uuid": "^9.0.1"
3636
},
3737
"devDependencies": {
38-
"@sphereon/oid4vci-client": "0.16.1-unstable.105",
39-
"@sphereon/oid4vci-common": "0.16.1-unstable.105",
38+
"@sphereon/oid4vci-client": "0.16.1-unstable.122",
39+
"@sphereon/oid4vci-common": "0.16.1-unstable.122",
4040
"@sphereon/ssi-express-support": "workspace:*",
4141
"@sphereon/ssi-sdk-ext.key-manager": "0.24.1-unstable.134",
4242
"@sphereon/ssi-sdk-ext.kms-local": "0.24.1-unstable.134",

packages/oid4vci-holder/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
},
1616
"dependencies": {
1717
"@sphereon/kmp-mdl-mdoc": "0.2.0-SNAPSHOT.22",
18-
"@sphereon/oid4vci-client": "0.16.1-unstable.105",
19-
"@sphereon/oid4vci-common": "0.16.1-unstable.105",
18+
"@sphereon/oid4vci-client": "0.16.1-unstable.122",
19+
"@sphereon/oid4vci-common": "0.16.1-unstable.122",
2020
"@sphereon/ssi-sdk-ext.did-utils": "0.24.1-unstable.134",
2121
"@sphereon/ssi-sdk-ext.identifier-resolution": "0.24.1-unstable.134",
2222
"@sphereon/ssi-sdk-ext.jwt-service": "0.24.1-unstable.134",

packages/oid4vci-issuer-rest-api/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111
"start:dev": "ts-node __tests__/RestAPI.ts"
1212
},
1313
"dependencies": {
14-
"@sphereon/oid4vci-common": "0.16.1-unstable.105",
15-
"@sphereon/oid4vci-issuer": "0.16.1-unstable.105",
16-
"@sphereon/oid4vci-issuer-server": "0.16.1-unstable.105",
14+
"@sphereon/oid4vci-common": "0.16.1-unstable.122",
15+
"@sphereon/oid4vci-issuer": "0.16.1-unstable.122",
16+
"@sphereon/oid4vci-issuer-server": "0.16.1-unstable.122",
1717
"@sphereon/ssi-express-support": "workspace:*",
1818
"@sphereon/ssi-sdk-ext.identifier-resolution": "0.24.1-unstable.134",
1919
"@sphereon/ssi-sdk.kv-store-temp": "workspace:*",

packages/oid4vci-issuer-rest-client/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"generate-plugin-schema": "ts-node ../../packages/dev/bin/sphereon.js dev generate-plugin-schema"
1717
},
1818
"dependencies": {
19-
"@sphereon/oid4vci-common": "0.16.1-unstable.105",
19+
"@sphereon/oid4vci-common": "0.16.1-unstable.122",
2020
"@sphereon/ssi-types": "workspace:*",
2121
"@veramo/core": "4.2.0",
2222
"cross-fetch": "^3.1.8"

packages/oid4vci-issuer-store/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"build:clean": "tsc --build --clean && tsc --build"
1515
},
1616
"dependencies": {
17-
"@sphereon/oid4vci-common": "0.16.1-unstable.105",
17+
"@sphereon/oid4vci-common": "0.16.1-unstable.122",
1818
"@sphereon/ssi-sdk-ext.did-utils": "0.24.1-unstable.134",
1919
"@sphereon/ssi-sdk-ext.identifier-resolution": "0.24.1-unstable.134",
2020
"@sphereon/ssi-sdk.kv-store-temp": "workspace:*",

packages/oid4vci-issuer/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
"build:clean": "tsc --build --clean && tsc --build"
1515
},
1616
"dependencies": {
17-
"@sphereon/oid4vci-common": "0.16.1-unstable.105",
18-
"@sphereon/oid4vci-issuer": "0.16.1-unstable.105",
17+
"@sphereon/oid4vci-common": "0.16.1-unstable.122",
18+
"@sphereon/oid4vci-issuer": "0.16.1-unstable.122",
1919
"@sphereon/ssi-sdk-ext.did-utils": "0.24.1-unstable.134",
2020
"@sphereon/ssi-sdk-ext.identifier-resolution": "0.24.1-unstable.134",
2121
"@sphereon/ssi-sdk.agent-config": "workspace:*",

packages/siopv2-oid4vp-common/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"access": "public"
1313
},
1414
"dependencies": {
15-
"@sphereon/did-auth-siop": "0.16.1-unstable.105",
15+
"@sphereon/did-auth-siop": "0.16.1-unstable.122",
1616
"@sphereon/ssi-sdk.core": "workspace:*",
1717
"@sphereon/ssi-types": "workspace:*",
1818
"uint8arrays": "3.1.1"

packages/siopv2-oid4vp-op-auth/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
"build:clean": "tsc --build --clean && tsc --build"
1515
},
1616
"dependencies": {
17-
"@sphereon/did-auth-siop": "0.16.1-unstable.105",
18-
"@sphereon/did-auth-siop-adapter": "0.16.1-unstable.105",
19-
"@sphereon/oid4vc-common": "0.16.1-unstable.105",
17+
"@sphereon/did-auth-siop": "0.16.1-unstable.122",
18+
"@sphereon/did-auth-siop-adapter": "0.16.1-unstable.122",
19+
"@sphereon/oid4vc-common": "0.16.1-unstable.122",
2020
"@sphereon/pex": "5.0.0-unstable.10",
2121
"@sphereon/pex-models": "^2.3.1",
2222
"@sphereon/ssi-sdk-ext.did-utils": "0.24.1-unstable.134",

packages/siopv2-oid4vp-op-auth/src/session/OpSession.ts

Lines changed: 84 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,40 @@
11
import {
2+
AuthorizationResponsePayload,
3+
JwksMetadataParams,
4+
OP,
25
PresentationDefinitionWithLocation,
36
PresentationExchangeResponseOpts,
7+
PresentationVerificationResult,
8+
RequestObjectPayload,
9+
ResponseIss,
10+
SupportedVersion,
411
URI,
512
Verification,
6-
VerifiedAuthorizationRequest,
13+
VerifiedAuthorizationRequest
714
} from '@sphereon/did-auth-siop'
8-
import { PresentationVerificationResult } from '@sphereon/did-auth-siop'
15+
import { ResolveOpts } from '@sphereon/did-auth-siop-adapter'
16+
import { JwtIssuer } from '@sphereon/oid4vc-common'
917
import { getAgentDIDMethods, getAgentResolver } from '@sphereon/ssi-sdk-ext.did-utils'
10-
import { CompactSdJwtVc, W3CVerifiablePresentation, CredentialMapper, PresentationSubmission, parseDid } from '@sphereon/ssi-types'
18+
import { encodeBase64url } from '@sphereon/ssi-sdk.core'
19+
import {
20+
CompactSdJwtVc,
21+
CredentialMapper,
22+
parseDid,
23+
PresentationSubmission,
24+
W3CVerifiablePresentation
25+
} from '@sphereon/ssi-types'
1126
import { IIdentifier, IVerifyResult, TKeyType } from '@veramo/core'
1227
import Debug from 'debug'
13-
import { IOPOptions, IOpSessionArgs, IOpSessionGetOID4VPArgs, IOpsSendSiopAuthorizationResponseArgs, IRequiredContext } from '../types'
28+
import { v4 } from 'uuid'
29+
import {
30+
IOPOptions,
31+
IOpSessionArgs,
32+
IOpSessionGetOID4VPArgs,
33+
IOpsSendSiopAuthorizationResponseArgs,
34+
IRequiredContext
35+
} from '../types'
1436
import { createOP } from './functions'
1537
import { OID4VP } from './OID4VP'
16-
import { ResolveOpts } from '@sphereon/did-auth-siop-adapter'
1738

1839
const debug = Debug(`sphereon:sdk:siop:op-session`)
1940

@@ -112,7 +133,7 @@ export class OpSession {
112133
debug(`agent methods supported: ${JSON.stringify(agentMethods)}`)
113134
const authReq = await this.getAuthorizationRequest()
114135
const subjectSyntaxTypesSupported = authReq.registrationMetadataPayload?.subject_syntax_types_supported?.map((method) =>
115-
convertDidMethod(method, opts.didPrefix),
136+
convertDidMethod(method, opts.didPrefix)
116137
)
117138
debug(`subject syntax types supported in rp method supported: ${JSON.stringify(subjectSyntaxTypesSupported)}`)
118139
const aud = await authReq.authorizationRequest.getMergedProperty<string>('aud')
@@ -134,7 +155,7 @@ export class OpSession {
134155
rpMethods = [didMethod]
135156
} else if (subjectSyntaxTypesSupported) {
136157
rpMethods = (Array.isArray(subjectSyntaxTypesSupported) ? subjectSyntaxTypesSupported : [subjectSyntaxTypesSupported]).map((method) =>
137-
convertDidMethod(method, opts.didPrefix),
158+
convertDidMethod(method, opts.didPrefix)
138159
)
139160
}
140161
const isEBSI =
@@ -169,11 +190,11 @@ export class OpSession {
169190
if (opts?.createInCaseNoDIDFound !== false) {
170191
const { codecName, keyType } = await this.getRPDIDMethodsSupported({
171192
didPrefix: true,
172-
agentMethods: methods,
193+
agentMethods: methods
173194
})
174195
const identifier = await this.context.agent.didManagerCreate({
175196
provider: methods[0],
176-
options: { codecName, keyType, type: keyType }, // both keyType and type, because not every did provider has the same param
197+
options: { codecName, keyType, type: keyType } // both keyType and type, because not every did provider has the same param
177198
})
178199
debug(`Created a new identifier for the SIOP interaction: ${identifier.did}`)
179200
identifiers.push(identifier)
@@ -210,20 +231,20 @@ export class OpSession {
210231
private createPresentationVerificationCallback(context: IRequiredContext) {
211232
async function presentationVerificationCallback(
212233
args: W3CVerifiablePresentation | CompactSdJwtVc,
213-
presentationSubmission: PresentationSubmission,
234+
presentationSubmission: PresentationSubmission
214235
): Promise<PresentationVerificationResult> {
215236
let result: IVerifyResult
216237
if (CredentialMapper.isSdJwtEncoded(args)) {
217238
try {
218239
const sdJwtResult = await context.agent.verifySdJwtPresentation({ presentation: args })
219240
result = {
220241
verified: 'header' in sdJwtResult,
221-
error: 'header' in sdJwtResult ? undefined : { message: 'could not verify SD JWT presentation' },
242+
error: 'header' in sdJwtResult ? undefined : { message: 'could not verify SD JWT presentation' }
222243
}
223244
} catch (error: any) {
224245
result = {
225246
verified: false,
226-
error: { message: error.message },
247+
error: { message: error.message }
227248
}
228249
}
229250
} else {
@@ -236,20 +257,60 @@ export class OpSession {
236257
return presentationVerificationCallback
237258
}
238259

260+
private async createJarmResponseCallback({ responseOpts }: {
261+
responseOpts: {
262+
jwtIssuer?: JwtIssuer
263+
version?: SupportedVersion
264+
correlationId?: string
265+
audience?: string
266+
issuer?: ResponseIss | string
267+
verification?: Verification
268+
}
269+
}) {
270+
const agent = this.context.agent
271+
return async function jarmResponse(opts: {
272+
authorizationResponsePayload: AuthorizationResponsePayload
273+
requestObjectPayload: RequestObjectPayload
274+
clientMetadata: JwksMetadataParams
275+
}): Promise<{ response: string }> {
276+
const { clientMetadata, authorizationResponsePayload: authResponse } = opts
277+
const jwk = await OP.extractEncJwksFromClientMetadata(clientMetadata)
278+
// @ts-ignore // FIXME: Fix jwk inference
279+
const recipientKey = await agent.identifierExternalResolveByJwk({ identifier: jwk })
280+
281+
return await agent.jwtEncryptJweCompactJwt({
282+
recipientKey,
283+
protectedHeader: {},
284+
//FIXME. Get from metadata
285+
alg: 'ECDH-ES',
286+
enc: 'A256GCM',
287+
apv: encodeBase64url(opts.requestObjectPayload.nonce),
288+
apu: encodeBase64url(v4()),
289+
payload: authResponse,
290+
issuer: responseOpts.issuer,
291+
audience: responseOpts.audience
292+
}).then(result => {
293+
return { response: result.jwt }
294+
})
295+
296+
}
297+
}
298+
299+
239300
public async sendAuthorizationResponse(args: IOpsSendSiopAuthorizationResponseArgs): Promise<Response> {
240301
const resolveOpts: ResolveOpts = this.options.resolveOpts ?? {
241302
resolver: getAgentResolver(this.context, {
242303
uniresolverResolution: true,
243304
localResolution: true,
244-
resolverResolution: true,
245-
}),
305+
resolverResolution: true
306+
})
246307
}
247308
if (!resolveOpts.subjectSyntaxTypesSupported || resolveOpts.subjectSyntaxTypesSupported.length === 0) {
248309
resolveOpts.subjectSyntaxTypesSupported = await this.getSupportedDIDMethods(true)
249310
}
250311
//todo: populate with the right verification params. In did-auth-siop we don't have any test that actually passes this parameter
251312
const verification: Verification = {
252-
presentationVerificationCallback: this.createPresentationVerificationCallback(this.context),
313+
presentationVerificationCallback: this.createPresentationVerificationCallback(this.context)
253314
}
254315

255316
const request = await this.getAuthorizationRequest()
@@ -261,7 +322,7 @@ export class OpSession {
261322
args.verifiablePresentations.length !== request.presentationDefinitions.length
262323
) {
263324
throw Error(
264-
`Amount of presentations ${args.verifiablePresentations?.length}, doesn't match expected ${request.presentationDefinitions?.length}`,
325+
`Amount of presentations ${args.verifiablePresentations?.length}, doesn't match expected ${request.presentationDefinitions?.length}`
265326
)
266327
} else if (!args.presentationSubmission) {
267328
throw Error(`Presentation submission is required when verifiable presentations are required`)
@@ -278,10 +339,10 @@ export class OpSession {
278339
eventEmitter: this.options.eventEmitter,
279340
presentationSignCallback: this.options.presentationSignCallback,
280341
wellknownDIDVerifyCallback: this.options.wellknownDIDVerifyCallback,
281-
supportedVersions: request.versions,
342+
supportedVersions: request.versions
282343
},
283344
idOpts: args.responseSignerOpts,
284-
context: this.context,
345+
context: this.context
285346
})
286347

287348
//TODO change this to use the new functionalities by identifier-resolver and get the jwkIssuer for the responseOpts
@@ -292,13 +353,14 @@ export class OpSession {
292353
...(args.verifiablePresentations && {
293354
presentationExchange: {
294355
verifiablePresentations,
295-
presentationSubmission: args.presentationSubmission,
296-
} as PresentationExchangeResponseOpts,
297-
}),
356+
presentationSubmission: args.presentationSubmission
357+
} as PresentationExchangeResponseOpts
358+
})
298359
}
299360

300361
const authResponse = await op.createAuthorizationResponse(request, responseOpts)
301-
const response = await op.submitAuthorizationResponse(authResponse)
362+
const response = await op.submitAuthorizationResponse(authResponse, await this.createJarmResponseCallback({ responseOpts })
363+
)
302364

303365
if (response.status >= 400) {
304366
throw Error(`Error ${response.status}: ${response.statusText || (await response.text())}`)

0 commit comments

Comments
 (0)