@sphereon/ssi-sdk.siopv2-oid4vp-rp-rest-api 0.34.1-feature.SSISDK.58.host.nonce.endpoint.145 → 0.34.1-feature.SSISDK.62.218

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-rp-rest-api",
3
- "version": "0.34.1-feature.SSISDK.58.host.nonce.endpoint.145+5bfc0b12",
3
+ "version": "0.34.1-feature.SSISDK.62.218+da5863f4",
4
4
  "source": "src/index.ts",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -23,16 +23,16 @@
23
23
  "start:dev": "ts-node __tests__/RestAPI.ts"
24
24
  },
25
25
  "dependencies": {
26
- "@sphereon/did-auth-siop": "0.19.1-feature.SSISDK.58.host.nonce.endpoint.107",
27
- "@sphereon/ssi-express-support": "0.34.1-feature.SSISDK.58.host.nonce.endpoint.145+5bfc0b12",
28
- "@sphereon/ssi-sdk.core": "0.34.1-feature.SSISDK.58.host.nonce.endpoint.145+5bfc0b12",
29
- "@sphereon/ssi-sdk.credential-validation": "0.34.1-feature.SSISDK.58.host.nonce.endpoint.145+5bfc0b12",
30
- "@sphereon/ssi-sdk.kv-store-temp": "0.34.1-feature.SSISDK.58.host.nonce.endpoint.145+5bfc0b12",
31
- "@sphereon/ssi-sdk.pd-manager": "0.34.1-feature.SSISDK.58.host.nonce.endpoint.145+5bfc0b12",
32
- "@sphereon/ssi-sdk.presentation-exchange": "0.34.1-feature.SSISDK.58.host.nonce.endpoint.145+5bfc0b12",
33
- "@sphereon/ssi-sdk.siopv2-oid4vp-common": "0.34.1-feature.SSISDK.58.host.nonce.endpoint.145+5bfc0b12",
34
- "@sphereon/ssi-sdk.siopv2-oid4vp-rp-auth": "0.34.1-feature.SSISDK.58.host.nonce.endpoint.145+5bfc0b12",
35
- "@sphereon/ssi-types": "0.34.1-feature.SSISDK.58.host.nonce.endpoint.145+5bfc0b12",
26
+ "@sphereon/did-auth-siop": "0.19.1-feature.SSISDK.62.162",
27
+ "@sphereon/ssi-express-support": "0.34.1-feature.SSISDK.62.218+da5863f4",
28
+ "@sphereon/ssi-sdk.core": "0.34.1-feature.SSISDK.62.218+da5863f4",
29
+ "@sphereon/ssi-sdk.credential-validation": "0.34.1-feature.SSISDK.62.218+da5863f4",
30
+ "@sphereon/ssi-sdk.kv-store-temp": "0.34.1-feature.SSISDK.62.218+da5863f4",
31
+ "@sphereon/ssi-sdk.pd-manager": "0.34.1-feature.SSISDK.62.218+da5863f4",
32
+ "@sphereon/ssi-sdk.presentation-exchange": "0.34.1-feature.SSISDK.62.218+da5863f4",
33
+ "@sphereon/ssi-sdk.siopv2-oid4vp-common": "0.34.1-feature.SSISDK.62.218+da5863f4",
34
+ "@sphereon/ssi-sdk.siopv2-oid4vp-rp-auth": "0.34.1-feature.SSISDK.62.218+da5863f4",
35
+ "@sphereon/ssi-types": "0.34.1-feature.SSISDK.62.218+da5863f4",
36
36
  "@veramo/core": "4.2.0",
37
37
  "@veramo/credential-w3c": "4.2.0",
38
38
  "awesome-qr": "^2.1.5-rc.0",
@@ -44,18 +44,21 @@
44
44
  "express": "^4.19.2",
45
45
  "short-uuid": "^4.2.2",
46
46
  "swagger-ui-express": "^5.0.1",
47
- "uuid": "^9.0.1"
47
+ "uuid": "^9.0.1",
48
+ "zod": "^4.1.5"
48
49
  },
49
50
  "devDependencies": {
50
51
  "@decentralized-identity/ion-sdk": "^0.6.0",
51
- "@sphereon/did-auth-siop-adapter": "0.19.1-feature.SSISDK.58.host.nonce.endpoint.107",
52
+ "@sphereon/did-auth-siop-adapter": "0.19.1-feature.SSISDK.62.162",
52
53
  "@sphereon/did-uni-client": "^0.6.3",
53
54
  "@sphereon/pex": "5.0.0-unstable.28",
54
55
  "@sphereon/pex-models": "^2.3.2",
55
- "@sphereon/ssi-sdk-ext.did-provider-jwk": "0.34.1-feature.SSISDK.58.host.nonce.endpoint.145+5bfc0b12",
56
- "@sphereon/ssi-sdk.credential-vcdm": "0.34.1-feature.SSISDK.58.host.nonce.endpoint.145+5bfc0b12",
57
- "@sphereon/ssi-sdk.credential-vcdm-jsonld-provider": "0.34.1-feature.SSISDK.58.host.nonce.endpoint.145+5bfc0b12",
58
- "@sphereon/ssi-sdk.data-store": "0.34.1-feature.SSISDK.58.host.nonce.endpoint.145+5bfc0b12",
56
+ "@sphereon/ssi-sdk-ext.did-provider-jwk": "0.34.1-feature.SSISDK.62.218+da5863f4",
57
+ "@sphereon/ssi-sdk-ext.identifier-resolution": "0.34.1-feature.SSISDK.62.218+da5863f4",
58
+ "@sphereon/ssi-sdk-ext.jwt-service": "0.34.1-feature.SSISDK.62.218+da5863f4",
59
+ "@sphereon/ssi-sdk.credential-vcdm": "0.34.1-feature.SSISDK.62.218+da5863f4",
60
+ "@sphereon/ssi-sdk.credential-vcdm-jsonld-provider": "0.34.1-feature.SSISDK.62.218+da5863f4",
61
+ "@sphereon/ssi-sdk.data-store": "0.34.1-feature.SSISDK.62.218+da5863f4",
59
62
  "@types/body-parser": "^1.19.5",
60
63
  "@types/cookie-parser": "^1.4.7",
61
64
  "@types/cors": "^2.8.17",
@@ -114,5 +117,5 @@
114
117
  "OpenID Connect",
115
118
  "Authenticator"
116
119
  ],
117
- "gitHead": "5bfc0b1229134b5d80279a3baf1fc64c9c6e755e"
120
+ "gitHead": "da5863f4eaa8081dde4e943fe78c1217d62d1079"
118
121
  }
package/src/index.ts CHANGED
@@ -2,6 +2,6 @@
2
2
  * @public
3
3
  */
4
4
  export * from './siop-api-functions'
5
- export * from './webapp-api-functions'
5
+ export * from './universal-oid4vp-api-functions'
6
6
  export * from './types'
7
7
  export * from './siopv2-rp-api-server'
@@ -0,0 +1,20 @@
1
+ import { Request, Response, NextFunction } from 'express';
2
+ import { z, ZodError } from 'zod';
3
+
4
+ export const validateData = (schema: z.ZodObject<any, any>) => {
5
+ return (req: Request, res: Response, next: NextFunction) => {
6
+ try {
7
+ schema.parse(req.body);
8
+ next();
9
+ } catch (error) {
10
+ if (error instanceof ZodError) {
11
+ const errorMessages = error.issues.map((issue: any) => ({
12
+ message: `${issue.path.join('.')} is ${issue.message}`,
13
+ }))
14
+ res.status(400).json({ status: 400, message: 'Invalid data', error_details: errorMessages[0].message });
15
+ } else {
16
+ res.status(500).json({ status: 500, message: 'Internal Server Error' });
17
+ }
18
+ }
19
+ };
20
+ }
@@ -46,21 +46,32 @@ export function verifyAuthResponseSIOPv2Endpoint(router: Router, context: IRequi
46
46
  console.log(`verifyAuthResponse SIOP endpoint is disabled`)
47
47
  return
48
48
  }
49
- const path = opts?.path ?? '/siop/definitions/:definitionId/auth-responses/:correlationId'
49
+ const path = opts?.path ?? '/siop/queries/:queryId/auth-responses/:correlationId'
50
50
  router.post(path, checkAuth(opts?.endpoint), async (request: Request, response: Response) => {
51
51
  try {
52
- const { correlationId, definitionId, tenantId, version } = request.params
53
- if (!correlationId || !definitionId) {
54
- console.log(`No authorization request could be found for the given url. correlationId: ${correlationId}, definitionId: ${definitionId}`)
52
+ const { correlationId, queryId, tenantId, version } = request.params
53
+ if (!correlationId) {
54
+ console.log(`No authorization request could be found for the given url. correlationId: ${correlationId}`)
55
55
  return sendErrorResponse(response, 404, 'No authorization request could be found')
56
56
  }
57
- console.log('Authorization Response (siop-sessions')
58
- console.log(JSON.stringify(request.body, null, 2))
59
- const definitionItems = await context.agent.pdmGetDefinitions({ filter: [{ definitionId, tenantId, version }] })
57
+ console.debug('Authorization Response (siop-sessions') // TODO use logger
58
+ console.debug(JSON.stringify(request.body, null, 2))
59
+ const definitionItems = await context.agent.pdmGetDefinitions({
60
+ filter: [
61
+ {
62
+ queryId,
63
+ ...(tenantId && { tenantId }),
64
+ ...(version && { version }),
65
+ },
66
+ {
67
+ id: queryId,
68
+ },
69
+ ],
70
+ })
60
71
  if (definitionItems.length === 0) {
61
- console.log(`Could not get definition ${definitionId} from agent. Will return 404`)
72
+ console.log(`Could not get dcql query with id ${queryId} from agent. Will return 404`)
62
73
  response.statusCode = 404
63
- response.statusMessage = `No definition ${definitionId}`
74
+ response.statusMessage = `No definition ${queryId}`
64
75
  return response.send()
65
76
  }
66
77
 
@@ -71,8 +82,8 @@ export function verifyAuthResponseSIOPv2Endpoint(router: Router, context: IRequi
71
82
  const verifiedResponse = await context.agent.siopVerifyAuthResponse({
72
83
  authorizationResponse,
73
84
  correlationId,
74
- definitionId,
75
- dcqlQueryPayload: definitionItem.dcqlPayload,
85
+ queryId,
86
+ dcqlQuery: definitionItem.query,
76
87
  })
77
88
 
78
89
  // FIXME SSISDK-55 add proper support for checking for DCQL presentations
@@ -89,7 +100,7 @@ export function verifyAuthResponseSIOPv2Endpoint(router: Router, context: IRequi
89
100
  return response.send(JSON.stringify(authorizationChallengeValidationResponse))
90
101
  }
91
102
 
92
- const responseRedirectURI = await context.agent.siopGetRedirectURI({ correlationId, definitionId, state: verifiedResponse.state })
103
+ const responseRedirectURI = await context.agent.siopGetRedirectURI({ correlationId, queryId, state: verifiedResponse.state })
93
104
  if (responseRedirectURI) {
94
105
  response.setHeader('Content-Type', 'application/json')
95
106
  return response.send(JSON.stringify({ redirect_uri: responseRedirectURI }))
@@ -113,23 +124,23 @@ export function getAuthRequestSIOPv2Endpoint(router: Router, context: IRequiredC
113
124
  console.log(`getAuthRequest SIOP endpoint is disabled`)
114
125
  return
115
126
  }
116
- const path = opts?.path ?? '/siop/definitions/:definitionId/auth-requests/:correlationId'
127
+ const path = opts?.path ?? '/siop/queries/:queryId/auth-requests/:correlationId'
117
128
  router.get(path, checkAuth(opts?.endpoint), async (request: Request, response: Response) => {
118
129
  try {
119
130
  const correlationId = request.params.correlationId
120
- const definitionId = request.params.definitionId
121
- if (!correlationId || !definitionId) {
122
- console.log(`No authorization request could be found for the given url. correlationId: ${correlationId}, definitionId: ${definitionId}`)
131
+ const queryId = request.params.queryId
132
+ if (!correlationId || !queryId) {
133
+ console.log(`No authorization request could be found for the given url. correlationId: ${correlationId}, queryId: ${queryId}`)
123
134
  return sendErrorResponse(response, 404, 'No authorization request could be found')
124
135
  }
125
136
  const requestState = await context.agent.siopGetAuthRequestState({
126
137
  correlationId,
127
- definitionId,
138
+ queryId,
128
139
  errorOnNotFound: false,
129
140
  })
130
141
  if (!requestState) {
131
142
  console.log(
132
- `No authorization request could be found for the given url in the state manager. correlationId: ${correlationId}, definitionId: ${definitionId}`,
143
+ `No authorization request could be found for the given url in the state manager. correlationId: ${correlationId}, definitionId: ${queryId}`,
133
144
  )
134
145
  return sendErrorResponse(response, 404, `No authorization request could be found`)
135
146
  }
@@ -148,8 +159,8 @@ export function getAuthRequestSIOPv2Endpoint(router: Router, context: IRequiredC
148
159
  } finally {
149
160
  await context.agent.siopUpdateAuthRequestState({
150
161
  correlationId,
151
- definitionId,
152
- state: 'sent',
162
+ queryId: queryId,
163
+ state: 'authorization_request_created',
153
164
  error,
154
165
  })
155
166
  }
@@ -1,23 +1,22 @@
1
1
  import { agentContext } from '@sphereon/ssi-sdk.core'
2
2
  import { copyGlobalAuthToEndpoints, ExpressSupport } from '@sphereon/ssi-express-support'
3
- import { IPresentationExchange } from '@sphereon/ssi-sdk.presentation-exchange'
4
3
  import { ISIOPv2RP } from '@sphereon/ssi-sdk.siopv2-oid4vp-rp-auth'
5
4
  import { TAgent } from '@veramo/core'
6
5
  import express, { Express, Request, Response, Router } from 'express'
7
6
  import { getAuthRequestSIOPv2Endpoint, verifyAuthResponseSIOPv2Endpoint } from './siop-api-functions'
8
7
  import { IRequiredPlugins, ISIOPv2RPRestAPIOpts } from './types'
9
8
  import {
10
- authStatusWebappEndpoint,
11
- createAuthRequestWebappEndpoint,
9
+ authStatusUniversalOID4VPEndpoint,
10
+ createAuthRequestUniversalOID4VPEndpoint,
12
11
  getDefinitionsEndpoint,
13
- removeAuthRequestStateWebappEndpoint,
14
- } from './webapp-api-functions'
12
+ removeAuthRequestStateUniversalOID4VPEndpoint,
13
+ } from './universal-oid4vp-api-functions'
15
14
  import swaggerUi from 'swagger-ui-express'
16
15
 
17
16
  export class SIOPv2RPApiServer {
18
17
  private readonly _express: Express
19
18
  private readonly _router: Router
20
- private readonly _agent: TAgent<IPresentationExchange & ISIOPv2RP>
19
+ private readonly _agent: TAgent<ISIOPv2RP>
21
20
  private readonly _opts?: ISIOPv2RPRestAPIOpts
22
21
  private readonly _basePath: string
23
22
 
@@ -40,9 +39,9 @@ export class SIOPv2RPApiServer {
40
39
 
41
40
  // Webapp endpoints
42
41
  if (features.includes('rp-status')) {
43
- createAuthRequestWebappEndpoint(this._router, context, opts?.endpointOpts?.webappCreateAuthRequest)
44
- authStatusWebappEndpoint(this._router, context, opts?.endpointOpts?.webappAuthStatus)
45
- removeAuthRequestStateWebappEndpoint(this._router, context, opts?.endpointOpts?.webappDeleteAuthRequest)
42
+ createAuthRequestUniversalOID4VPEndpoint(this._router, context, opts?.endpointOpts?.webappCreateAuthRequest)
43
+ authStatusUniversalOID4VPEndpoint(this._router, context, opts?.endpointOpts?.webappAuthStatus)
44
+ removeAuthRequestStateUniversalOID4VPEndpoint(this._router, context, opts?.endpointOpts?.webappDeleteAuthRequest)
46
45
  getDefinitionsEndpoint(this._router, context, opts?.endpointOpts?.webappGetDefinitions)
47
46
  }
48
47
 
@@ -92,7 +91,7 @@ export class SIOPv2RPApiServer {
92
91
  return this._router
93
92
  }
94
93
 
95
- get agent(): TAgent<IPresentationExchange & ISIOPv2RP> {
94
+ get agent(): TAgent<ISIOPv2RP> {
96
95
  return this._agent
97
96
  }
98
97
 
@@ -1,11 +1,15 @@
1
+ import { CreateAuthorizationRequestPayload, CreateAuthorizationResponsePayload } from '@sphereon/did-auth-siop'
1
2
  import { GenericAuthArgs, ISingleEndpointOpts } from '@sphereon/ssi-express-support'
2
- import { IPresentationExchange } from '@sphereon/ssi-sdk.presentation-exchange'
3
+ import { IPDManager } from '@sphereon/ssi-sdk.pd-manager'
4
+ import { AuthorizationRequestStateStatus, AuthorizationResponseStateStatus } from '@sphereon/ssi-sdk.siopv2-oid4vp-common'
3
5
  import { ISIOPv2RP } from '@sphereon/ssi-sdk.siopv2-oid4vp-rp-auth'
6
+ import { AdditionalClaims } from '@sphereon/ssi-types'
4
7
  import { IAgentContext, ICredentialVerifier } from '@veramo/core'
5
- import { IPDManager } from '@sphereon/ssi-sdk.pd-manager'
8
+ import { Request, Response } from 'express'
6
9
  import { QRCodeOpts } from './QRCode.types'
7
10
 
8
11
  export type SiopFeatures = 'rp-status' | 'siop'
12
+
9
13
  export interface ISIOPv2RPRestAPIOpts {
10
14
  enableFeatures?: SiopFeatures[]
11
15
  endpointOpts?: {
@@ -28,5 +32,58 @@ export interface ICreateAuthRequestWebappEndpointOpts extends ISingleEndpointOpt
28
32
  responseRedirectURI?: string
29
33
  }
30
34
 
31
- export type IRequiredPlugins = ICredentialVerifier & ISIOPv2RP & IPresentationExchange & IPDManager
35
+ export type IRequiredPlugins = ICredentialVerifier & ISIOPv2RP & IPDManager
32
36
  export type IRequiredContext = IAgentContext<IRequiredPlugins>
37
+
38
+ export type CreateAuthorizationRequestPayloadRequest = Request<Record<string, never>, any, CreateAuthorizationRequestPayload, Record<string, never>>
39
+
40
+ export type CreateAuthorizationResponsePayloadResponse = Response<CreateAuthorizationResponsePayload>
41
+
42
+ export type DeleteAuthorizationRequest = Request<DeleteAuthorizationRequestPathParameters, any, Record<string, any>, Record<string, any>>
43
+
44
+ export type DeleteAuthorizationRequestPathParameters = {
45
+ correlationId: string
46
+ }
47
+
48
+ export type GetAuthorizationRequestStatus = Request<GetAuthorizationRequestStatusPathParameters, any, Record<string, any>, Record<string, any>>
49
+
50
+ export type GetAuthorizationRequestStatusPathParameters = {
51
+ correlationId: string
52
+ }
53
+
54
+ export type RequestError = {
55
+ status: number
56
+ message: string
57
+ error_details?: string
58
+ }
59
+
60
+ export interface AuthStatusResponse {
61
+ status: AuthorizationRequestStateStatus | AuthorizationResponseStateStatus
62
+ correlation_id: string
63
+ query_id: string
64
+ last_updated: number
65
+ verified_data?: VerifiedData
66
+ error?: RequestError
67
+ }
68
+
69
+ export type VerifiedData = {
70
+ authorization_response?: AuthorizationResponse
71
+ credential_claims?: AdditionalClaims
72
+ }
73
+
74
+ export type AuthorizationResponse = {
75
+ presentation_submission?: Record<string, any>
76
+ vp_token?: VpToken
77
+ }
78
+
79
+ export type SingleObjectVpTokenPE = Record<string, any>
80
+
81
+ export type SingleStringVpTokenPE = string
82
+
83
+ export type MultipleVpTokens = Array<SingleObjectVpTokenPE> | Array<SingleStringVpTokenPE>
84
+
85
+ export type MultipleVpTokenDCQL = {
86
+ [key: string]: MultipleVpTokens
87
+ }
88
+
89
+ export type VpToken = SingleObjectVpTokenPE | SingleStringVpTokenPE | MultipleVpTokens | MultipleVpTokenDCQL
@@ -0,0 +1,195 @@
1
+ import {
2
+ AuthorizationRequestStateStatus,
3
+ AuthorizationResponseStateStatus,
4
+ CreateAuthorizationRequest,
5
+ createAuthorizationRequestFromPayload,
6
+ CreateAuthorizationRequestPayloadSchema,
7
+ CreateAuthorizationResponsePayload,
8
+ } from '@sphereon/did-auth-siop'
9
+ import { checkAuth, ISingleEndpointOpts, sendErrorResponse } from '@sphereon/ssi-express-support'
10
+ import { uriWithBase } from '@sphereon/ssi-sdk.siopv2-oid4vp-common'
11
+ import { VerifiedDataMode } from '@sphereon/ssi-sdk.siopv2-oid4vp-rp-auth'
12
+ import { Request, Response, Router } from 'express'
13
+ import uuid from 'short-uuid'
14
+ import { validateData } from './middleware/validationMiddleware'
15
+ import {
16
+ AuthStatusResponse,
17
+ CreateAuthorizationRequestPayloadRequest,
18
+ CreateAuthorizationResponsePayloadResponse,
19
+ DeleteAuthorizationRequest,
20
+ GetAuthorizationRequestStatus,
21
+ ICreateAuthRequestWebappEndpointOpts,
22
+ IRequiredContext,
23
+ QRCodeOpts,
24
+ } from './types'
25
+
26
+ export function createAuthRequestUniversalOID4VPEndpoint(router: Router, context: IRequiredContext, opts?: ICreateAuthRequestWebappEndpointOpts) {
27
+ if (opts?.enabled === false) {
28
+ console.log(`createAuthRequest universal OID4VP endpoint is disabled`)
29
+ return
30
+ }
31
+
32
+ const path = opts?.path ?? '/backend/auth/requests'
33
+ router.post(
34
+ path,
35
+ checkAuth(opts?.endpoint),
36
+ validateData(CreateAuthorizationRequestPayloadSchema),
37
+ async (request: CreateAuthorizationRequestPayloadRequest, response: CreateAuthorizationResponsePayloadResponse) => {
38
+ try {
39
+ const authRequest: CreateAuthorizationRequest = createAuthorizationRequestFromPayload(request.body)
40
+ const correlationId = authRequest.correlationId ?? uuid.uuid()
41
+ const qrCodeOpts = authRequest.qrCode ? ({ ...authRequest.qrCode } satisfies QRCodeOpts) : opts?.qrCodeOpts
42
+ const queryId = authRequest.queryId
43
+
44
+ const definitionItems = await context.agent.pdmGetDefinitions({
45
+ filter: [
46
+ { id: queryId }, // Allow both PK (unique queryId + version combi) or just plain queryId which assumes the latest version
47
+ { queryId },
48
+ ],
49
+ })
50
+ if (definitionItems.length === 0) {
51
+ console.log(`No query could be found for the given id. Query id: ${queryId}`)
52
+ return sendErrorResponse(response, 404, { status: 404, message: 'No query could be found' })
53
+ }
54
+
55
+ const requestByReferenceURI = uriWithBase(`/siop/queries/${queryId}/auth-requests/${correlationId}`, {
56
+ baseURI: authRequest.requestUriBase ?? opts?.siopBaseURI,
57
+ })
58
+ const responseURI = uriWithBase(`/siop/queries/${queryId}/auth-responses/${correlationId}`, { baseURI: opts?.siopBaseURI })
59
+
60
+ const authRequestURI = await context.agent.siopCreateAuthRequestURI({
61
+ queryId,
62
+ correlationId,
63
+ nonce: uuid.uuid(),
64
+ requestByReferenceURI,
65
+ responseURIType: 'response_uri',
66
+ responseURI,
67
+ ...(authRequest.directPostResponseRedirectUri && { responseRedirectURI: authRequest.directPostResponseRedirectUri }),
68
+ ...(authRequest.callback && { callback: authRequest.callback }),
69
+ })
70
+
71
+ let qrCodeDataUri: string | undefined
72
+ if (qrCodeOpts) {
73
+ const { AwesomeQR } = await import('awesome-qr')
74
+ const qrCode = new AwesomeQR({ ...qrCodeOpts, text: authRequestURI })
75
+ qrCodeDataUri = `data:image/png;base64,${(await qrCode.draw())!.toString('base64')}`
76
+ } else {
77
+ qrCodeDataUri = authRequestURI
78
+ }
79
+
80
+ const authRequestBody = {
81
+ query_id: queryId,
82
+ correlation_id: correlationId,
83
+ request_uri: authRequestURI,
84
+ status_uri: `${uriWithBase(opts?.webappAuthStatusPath ?? `/backend/auth/status/${correlationId}`, { baseURI: opts?.webappBaseURI })}`,
85
+ ...(qrCodeDataUri && { qr_uri: qrCodeDataUri }),
86
+ } satisfies CreateAuthorizationResponsePayload
87
+ console.log(`Auth Request URI data to send back: ${JSON.stringify(authRequestBody)}`)
88
+
89
+ return response.status(201).json(authRequestBody)
90
+ } catch (error) {
91
+ return sendErrorResponse(response, 500, { status: 500, message: 'Could not create an authorization request URI' }, error)
92
+ }
93
+ },
94
+ )
95
+ }
96
+
97
+ export function removeAuthRequestStateUniversalOID4VPEndpoint(router: Router, context: IRequiredContext, opts?: ISingleEndpointOpts) {
98
+ if (opts?.enabled === false) {
99
+ console.log(`removeAuthStatus universal OID4VP endpoint is disabled`)
100
+ return
101
+ }
102
+
103
+ const path = opts?.path ?? '/backend/auth/requests/:correlationId'
104
+ router.delete(path, checkAuth(opts?.endpoint), async (request: DeleteAuthorizationRequest, response: Response) => {
105
+ try {
106
+ const correlationId: string = request.params.correlationId
107
+
108
+ const authRequestState = await context.agent.siopGetAuthRequestState({
109
+ correlationId,
110
+ errorOnNotFound: false,
111
+ })
112
+ if (!authRequestState) {
113
+ console.log(`No authorization request could be found for the given correlationId. correlationId: ${correlationId}`)
114
+ return sendErrorResponse(response, 404, { status: 404, message: 'No authorization request could be found' })
115
+ }
116
+
117
+ await context.agent.siopDeleteAuthState({ correlationId })
118
+
119
+ return response.status(204).json()
120
+ } catch (error) {
121
+ return sendErrorResponse(response, 500, { status: 500, message: error.message }, error)
122
+ }
123
+ })
124
+ }
125
+
126
+ export function authStatusUniversalOID4VPEndpoint(router: Router, context: IRequiredContext, opts?: ISingleEndpointOpts) {
127
+ if (opts?.enabled === false) {
128
+ console.log(`authStatus universal OID4VP endpoint is disabled`)
129
+ return
130
+ }
131
+
132
+ const path = opts?.path ?? '/backend/auth/status/:correlationId'
133
+ router.get(path, checkAuth(opts?.endpoint), async (request: GetAuthorizationRequestStatus, response: Response) => {
134
+ try {
135
+ console.log('Received auth-status request...')
136
+ const correlationId: string = request.params.correlationId
137
+
138
+ const requestState = await context.agent.siopGetAuthRequestState({
139
+ correlationId,
140
+ errorOnNotFound: false,
141
+ })
142
+
143
+ if (!requestState) {
144
+ console.log(`No authorization request could be found for the given correlationId. correlationId: ${correlationId}`)
145
+ return sendErrorResponse(response, 404, { status: 404, message: 'No authorization request could be found' })
146
+ }
147
+
148
+ let responseState
149
+ if (requestState.status === AuthorizationRequestStateStatus.RETRIEVED) {
150
+ responseState = await context.agent.siopGetAuthResponseState({
151
+ correlationId,
152
+ errorOnNotFound: false,
153
+ includeVerifiedData: VerifiedDataMode.VERIFIED_PRESENTATION,
154
+ })
155
+ }
156
+ const overallState = responseState ?? requestState
157
+
158
+ const statusBody = {
159
+ status: overallState.status,
160
+ correlation_id: overallState.correlationId,
161
+ query_id: overallState.queryId,
162
+ last_updated: overallState.lastUpdated,
163
+ ...(responseState?.status === AuthorizationResponseStateStatus.VERIFIED &&
164
+ responseState.verifiedData !== undefined && { verified_data: responseState.verifiedData }),
165
+ ...(overallState.error && { message: overallState.error.message }),
166
+ } satisfies AuthStatusResponse
167
+ console.debug(`Will send auth status: ${JSON.stringify(statusBody)}`)
168
+
169
+ if (overallState.status === 'error') {
170
+ return response.status(500).json(statusBody)
171
+ }
172
+ return response.status(200).json(statusBody)
173
+ } catch (error) {
174
+ return sendErrorResponse(response, 500, { status: 500, message: error.message }, error)
175
+ }
176
+ })
177
+ }
178
+
179
+ export function getDefinitionsEndpoint(router: Router, context: IRequiredContext, opts?: ISingleEndpointOpts) {
180
+ if (opts?.enabled === false) {
181
+ console.log(`getDefinitions universal OID4VP endpoint is disabled`)
182
+ return
183
+ }
184
+
185
+ const path = opts?.path ?? '/backend/definitions'
186
+ router.get(path, checkAuth(opts?.endpoint), async (request: Request, response: Response) => {
187
+ try {
188
+ const definitions = await context.agent.pdmGetDefinitions()
189
+ response.statusCode = 200
190
+ return response.json(definitions)
191
+ } catch (error) {
192
+ return sendErrorResponse(response, 500, { status: 500, message: error.message }, error)
193
+ }
194
+ })
195
+ }