@bedrock/vc-delivery 5.5.0 → 5.6.0

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/lib/http.js CHANGED
@@ -16,6 +16,8 @@ import {getWorkflowId} from './helpers.js';
16
16
  import {logger} from './logger.js';
17
17
  import {createValidateMiddleware as validate} from '@bedrock/validation';
18
18
 
19
+ const {util: {BedrockError}} = bedrock;
20
+
19
21
  // FIXME: remove and apply at top-level application
20
22
  bedrock.events.on('bedrock-express.configure.bodyParser', app => {
21
23
  app.use(bodyParser.json({
@@ -32,7 +34,8 @@ export async function addRoutes({app, service} = {}) {
32
34
  const baseUrl = `${routePrefix}/:localId`;
33
35
  const routes = {
34
36
  exchanges: `${baseUrl}/exchanges`,
35
- exchange: `${baseUrl}/exchanges/:exchangeId`
37
+ exchange: `${baseUrl}/exchanges/:exchangeId`,
38
+ protocols: `${baseUrl}/exchanges/:exchangeId/protocols`
36
39
  };
37
40
 
38
41
  // used to retrieve service object (workflow) config
@@ -117,6 +120,49 @@ export async function addRoutes({app, service} = {}) {
117
120
  await processExchange({req, res, workflow, exchangeRecord});
118
121
  }));
119
122
 
123
+ // VC-API get interaction `{"protocols": {...}}` options
124
+ app.get(
125
+ routes.protocols,
126
+ cors(),
127
+ getExchange,
128
+ getConfigMiddleware,
129
+ asyncHandler(async (req, res) => {
130
+ if(!req.accepts('json')) {
131
+ // provide hopefully useful error for when VC API interaction URLs
132
+ // are processed improperly, e.g., directly loaded by a browser instead
133
+ // of by a digital wallet
134
+ throw new BedrockError(
135
+ 'Unsupported "Accept" header. A VC API interaction URL must be ' +
136
+ 'processed by an exchange client, e.g., a digital wallet.', {
137
+ name: 'NotSupportedError',
138
+ details: {httpStatusCode: 406, public: true}
139
+ });
140
+ }
141
+ // construct and return `protocols` object
142
+ const {config: workflow} = req.serviceObject;
143
+ const {exchange} = await req.getExchange();
144
+ const exchangeId = `${workflow.id}/exchanges/${exchange.id}`;
145
+ const protocols = {
146
+ vcapi: exchangeId
147
+ };
148
+ const openIdRoute = `${exchangeId}/openid`;
149
+ if(oid4.supportsOID4VCI({exchange})) {
150
+ // OID4VCI supported; add credential offer URL
151
+ const searchParams = new URLSearchParams();
152
+ const uri = `${openIdRoute}/credential-offer`;
153
+ searchParams.set('credential_offer_uri', uri);
154
+ protocols.OID4VCI = `openid-credential-offer://?${searchParams}`;
155
+ } else if(await oid4.supportsOID4VP({workflow, exchange})) {
156
+ // OID4VP supported; add openid4vp URL
157
+ const searchParams = new URLSearchParams({
158
+ client_id: `${openIdRoute}/client/authorization/response`,
159
+ request_uri: `${openIdRoute}/client/authorization/request`
160
+ });
161
+ protocols.OID4VP = `openid4vp://authorize?${searchParams}`;
162
+ }
163
+ res.json({protocols});
164
+ }));
165
+
120
166
  // create OID4* routes to be used with each individual exchange
121
167
  await oid4.createRoutes(
122
168
  {app, exchangeRoute: routes.exchange, getConfigMiddleware, getExchange});
package/lib/oid4/http.js CHANGED
@@ -12,9 +12,14 @@ import {
12
12
  import {asyncHandler} from '@bedrock/express';
13
13
  import bodyParser from 'body-parser';
14
14
  import cors from 'cors';
15
+ import {logger} from '../logger.js';
15
16
  import {UnsecuredJWT} from 'jose';
16
17
  import {createValidateMiddleware as validate} from '@bedrock/validation';
17
18
 
19
+ // re-export support detection helpers
20
+ export {supportsOID4VCI} from './oid4vci.js';
21
+ export {supportsOID4VP} from './oid4vp.js';
22
+
18
23
  /* NOTE: Parts of the OID4VCI design imply tight integration between the
19
24
  authorization server and the credential issuance / delivery server. This
20
25
  file provides the routes for both and treats them as integrated; supporting
@@ -374,6 +379,7 @@ export async function createRoutes({
374
379
  }
375
380
 
376
381
  function _sendOID4Error({res, error}) {
382
+ logger.error(error.message, {error});
377
383
  const status = error.details?.httpStatusCode ?? 500;
378
384
  const oid4Error = {
379
385
  error: _camelToSnakeCase(error.name ?? 'OperationError'),
@@ -149,6 +149,10 @@ export async function processCredentialRequests({req, res, isBatchRequest}) {
149
149
  return _processExchange({req, res, workflow, exchangeRecord, isBatchRequest});
150
150
  }
151
151
 
152
+ export function supportsOID4VCI({exchange}) {
153
+ return exchange.openId?.expectedCredentialRequests !== undefined;
154
+ }
155
+
152
156
  function _assertCredentialRequests({
153
157
  workflow, credentialRequests, expectedCredentialRequests
154
158
  }) {
@@ -201,7 +205,7 @@ function _assertCredentialRequests({
201
205
  }
202
206
 
203
207
  function _assertOID4VCISupported({exchange}) {
204
- if(!exchange.openId?.expectedCredentialRequests) {
208
+ if(!supportsOID4VCI({exchange})) {
205
209
  throw new BedrockError('OID4VCI is not supported by this exchange.', {
206
210
  name: 'NotSupportedError',
207
211
  details: {httpStatusCode: 400, public: true}
@@ -276,6 +276,18 @@ export async function processAuthorizationResponse({req}) {
276
276
  }
277
277
  }
278
278
 
279
+ export async function supportsOID4VP({workflow, exchange}) {
280
+ if(!exchange.step) {
281
+ return false;
282
+ }
283
+ let step = workflow.steps[exchange.step];
284
+ if(step.stepTemplate) {
285
+ step = await evaluateTemplate(
286
+ {workflow, exchange, typedTemplate: step.stepTemplate});
287
+ }
288
+ return step.openId !== undefined;
289
+ }
290
+
279
291
  function _createClientMetaData() {
280
292
  // return default supported `vp_formats`
281
293
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bedrock/vc-delivery",
3
- "version": "5.5.0",
3
+ "version": "5.6.0",
4
4
  "type": "module",
5
5
  "description": "Bedrock Verifiable Credential Delivery",
6
6
  "main": "./lib/index.js",