diff --git a/agent/src/endpoints.ts b/agent/src/endpoints.ts index 8b97e7c..bf52cb0 100644 --- a/agent/src/endpoints.ts +++ b/agent/src/endpoints.ts @@ -12,7 +12,7 @@ import { getJwkFromKey, } from '@credo-ts/core' import { OpenId4VcVerificationSessionState } from '@credo-ts/openid4vc' -import express, { type NextFunction, type Request, type Response } from 'express' +import express, { query, type NextFunction, type Request, type Response } from 'express' import z from 'zod' import { agent } from './agent' import { validateVerificationRequest, zValidateVerificationRequestSchema } from './ai' @@ -248,10 +248,11 @@ const zCreatePresentationRequestBody = z.object({ presentationDefinitionId: z.string(), requestScheme: z.string(), responseMode: z.enum(['direct_post.jwt', 'direct_post']), + purpose: z.string().optional(), }) apiRouter.post('/requests/create', async (request: Request, response: Response) => { - const { requestSignerType, presentationDefinitionId, requestScheme, responseMode } = + const { requestSignerType, presentationDefinitionId, requestScheme, responseMode, purpose } = await zCreatePresentationRequestBody.parseAsync(request.body) const x509Certificate = getX509Certificate() @@ -293,13 +294,22 @@ apiRouter.post('/requests/create', async (request: Request, response: Response) presentationExchange: 'input_descriptors' in definition ? { - definition, + definition: { + ...definition, + purpose: purpose ?? definition.purpose, + }, } : undefined, dcql: 'credentials' in definition ? { - query: definition, + query: { + ...definition, + credential_sets: + purpose && definition.credential_sets + ? definition.credential_sets.map((set) => ({ ...set, purpose })) + : definition.credential_sets, + }, } : undefined, responseMode, diff --git a/agent/src/verifiers/turboKeys.ts b/agent/src/verifiers/turboKeys.ts index c0c012f..41f1d21 100644 --- a/agent/src/verifiers/turboKeys.ts +++ b/agent/src/verifiers/turboKeys.ts @@ -125,9 +125,11 @@ export const turboKeysVerifier = { name: 'PID and MDL - Rent a Car (both either sd-jwt vc or mso_mdoc, prefer sd-jwt vc)', credential_sets: [ { + purpose: 'To secure your car reservations and finalize the transaction, we require the following attributes', options: [['pid_sd_jwt'], ['pid_mdoc']], }, { + purpose: 'To secure your car reservations and finalize the transaction, we require the following attributes', options: [['mdl_sd_jwt'], ['mdl_mdoc']], }, ], @@ -176,9 +178,11 @@ export const turboKeysVerifier = { name: 'PID and MDL - Rent a Car (both either sd-jwt vc or mso_mdoc, prefer mdoc)', credential_sets: [ { + purpose: 'To secure your car reservations and finalize the transaction, we require the following attributes', options: [['pid_mdoc'], ['pid_sd_jwt']], }, { + purpose: 'To secure your car reservations and finalize the transaction, we require the following attributes', options: [['mdl_mdoc'], ['mdl_sd_jwt']], }, ], diff --git a/app/components/VerifyBlock.tsx b/app/components/VerifyBlock.tsx index d7c9835..e0cd553 100644 --- a/app/components/VerifyBlock.tsx +++ b/app/components/VerifyBlock.tsx @@ -61,6 +61,7 @@ export const VerifyBlock: React.FC = ({ createRequest, flowNam const isSuccess = requestStatus?.responseStatus === 'ResponseVerified' const [presentationDefinitionId, setPresentationDefinitionId] = useState() const [requestScheme, setRequestScheme] = useState('openid4vp://') + const [purpose, setPurpose] = useState() const [requestSignerType, setRequestSignerType] = useState('x5c') const [useCase, setUseCase] = useState('') useEffect(() => { @@ -94,6 +95,7 @@ export const VerifyBlock: React.FC = ({ createRequest, flowNam presentationDefinitionId: id, requestScheme, responseMode, + purpose: purpose && purpose !== '' ? purpose : undefined, requestSignerType, }) setRequestStatus(request) @@ -194,6 +196,11 @@ export const VerifyBlock: React.FC = ({ createRequest, flowNam onChange={({ target }) => setRequestScheme(target.value)} /> +
+ + - Optional. Each request has an associated default purpose + setPurpose(target.value)} /> +