From 0878c2848aa5144ee863e6f192c9f8b8eb46ff34 Mon Sep 17 00:00:00 2001 From: Niels Klomp Date: Sat, 17 Jun 2023 01:59:24 +0200 Subject: [PATCH] feat: Allow to supply data for VCI Issuer REST client and server during offer --- .../__tests__/RestAPI.ts | 18 +++++--- packages/oid4vci-issuer-rest-api/package.json | 6 +-- .../shared/issuanceRestClientAgentLogic.ts | 2 +- .../oid4vci-issuer-rest-client/package.json | 2 +- .../src/agent/OID4VCIRestClient.ts | 3 +- .../src/types/IOID4VCIRestClient.ts | 19 ++++---- packages/oid4vci-issuer-store/package.json | 2 +- packages/oid4vci-issuer/package.json | 4 +- .../oid4vci-issuer/src/agent/OID4VCIIssuer.ts | 13 +++++- .../src/types/IOID4VCIIssuer.ts | 30 ++++++------ pnpm-lock.yaml | 46 +++++++++---------- 11 files changed, 82 insertions(+), 63 deletions(-) diff --git a/packages/oid4vci-issuer-rest-api/__tests__/RestAPI.ts b/packages/oid4vci-issuer-rest-api/__tests__/RestAPI.ts index b8a373e89..4e3609a8d 100644 --- a/packages/oid4vci-issuer-rest-api/__tests__/RestAPI.ts +++ b/packages/oid4vci-issuer-rest-api/__tests__/RestAPI.ts @@ -1,4 +1,5 @@ -import { CredentialDataSupplierResult } from '@sphereon/oid4vci-issuer' +import { CredentialDataSupplier, CredentialDataSupplierResult } from '@sphereon/oid4vci-issuer' +import { CredentialDataSupplierArgs } from '@sphereon/oid4vci-issuer/lib/types' import { TAgent } from '@veramo/core' import { IOID4VCIRestAPIOpts, IPlugins, OID4VCIRestAPI } from '../src' import agent from './agent' @@ -10,16 +11,20 @@ export const opts: IOID4VCIRestAPIOpts = { }, } -const credentialDataSupplier = () => - Promise.resolve({ +const credentialDataSupplier: CredentialDataSupplier = (args: CredentialDataSupplierArgs) => { + const firstName = args.credentialDataSupplierInput?.firstName ?? 'Hello' + const lastName = args.credentialDataSupplierInput?.lastName ?? 'DBC' + const email = args.credentialDataSupplierInput?.email ?? 'dbc@example.com' + + return Promise.resolve({ format: 'jwt_vc_json', credential: { '@context': ['https://www.w3.org/2018/credentials/v1'], type: ['VerifiableCredential', 'DBCConferenceAttendee'], credentialSubject: { - firstName: 'Hello', - lastName: 'DBC', - email: 'example@sphereon.com', // based on user form input, + firstName, + lastName, + email, event: { name: 'DBC Conference 2023', date: '2023-06-26', @@ -27,6 +32,7 @@ const credentialDataSupplier = () => }, }, } as unknown as CredentialDataSupplierResult) +} export function start() { OID4VCIRestAPI.init({ diff --git a/packages/oid4vci-issuer-rest-api/package.json b/packages/oid4vci-issuer-rest-api/package.json index 3d24d4a5e..98dcc1f77 100644 --- a/packages/oid4vci-issuer-rest-api/package.json +++ b/packages/oid4vci-issuer-rest-api/package.json @@ -11,9 +11,9 @@ "start:dev": "ts-node __tests__/RestAPI.ts" }, "dependencies": { - "@sphereon/oid4vci-common": "0.4.1-unstable.296", - "@sphereon/oid4vci-issuer": "0.4.1-unstable.296", - "@sphereon/oid4vci-issuer-server": "0.4.1-unstable.296", + "@sphereon/oid4vci-common": "0.4.1-unstable.302", + "@sphereon/oid4vci-issuer": "0.4.1-unstable.302", + "@sphereon/oid4vci-issuer-server": "0.4.1-unstable.302", "@sphereon/ssi-sdk.kv-store-temp": "workspace:*", "@sphereon/ssi-sdk.oid4vci-issuer": "workspace:*", "@sphereon/ssi-sdk.oid4vci-issuer-store": "workspace:*", diff --git a/packages/oid4vci-issuer-rest-client/__tests__/shared/issuanceRestClientAgentLogic.ts b/packages/oid4vci-issuer-rest-client/__tests__/shared/issuanceRestClientAgentLogic.ts index 5b18800a0..f85b63857 100644 --- a/packages/oid4vci-issuer-rest-client/__tests__/shared/issuanceRestClientAgentLogic.ts +++ b/packages/oid4vci-issuer-rest-client/__tests__/shared/issuanceRestClientAgentLogic.ts @@ -17,7 +17,7 @@ export default (testContext: { getAgent: () => ConfiguredAgent; setup: () => Pro it('should create the url Offer Url with baseUrl', async () => { const result = await agent.oid4vciClientCreateOfferUri({ - baseUrl: 'https://ssi-backend.sphereon.com', + agentBaseUrl: 'https://ssi-backend.sphereon.com', grants: { 'urn:ietf:params:oauth:grant-type:pre-authorized_code': { 'pre-authorized_code': '1234', diff --git a/packages/oid4vci-issuer-rest-client/package.json b/packages/oid4vci-issuer-rest-client/package.json index 1b9fad233..e5b516284 100644 --- a/packages/oid4vci-issuer-rest-client/package.json +++ b/packages/oid4vci-issuer-rest-client/package.json @@ -16,7 +16,7 @@ "generate-plugin-schema": "ts-node ../../packages/dev/bin/sphereon.js dev generate-plugin-schema" }, "dependencies": { - "@sphereon/oid4vci-common": "0.4.1-unstable.296", + "@sphereon/oid4vci-common": "0.4.1-unstable.302", "@veramo/core": "4.2.0", "cross-fetch": "^3.1.5" }, diff --git a/packages/oid4vci-issuer-rest-client/src/agent/OID4VCIRestClient.ts b/packages/oid4vci-issuer-rest-client/src/agent/OID4VCIRestClient.ts index 317e75c4c..d4bfd9de1 100644 --- a/packages/oid4vci-issuer-rest-client/src/agent/OID4VCIRestClient.ts +++ b/packages/oid4vci-issuer-rest-client/src/agent/OID4VCIRestClient.ts @@ -34,10 +34,11 @@ export class OID4VCIRestClient implements IAgentPlugin { if (!args.credentials || !args.grants) { return Promise.reject(Error("Can't generate the credential offer url without credentials and grants params present.")) } - const baseUrl = this.assertedAgentBaseUrl(args.baseUrl) + const baseUrl = this.assertedAgentBaseUrl(args.agentBaseUrl) const request: IOID4VCIClientCreateOfferUriRequest = { credentials: args.credentials, grants: args.grants, + ...(args.credentialDataSupplierInput && { credentialDataSupplierInput: args.credentialDataSupplierInput }), } const url = OID4VCIRestClient.urlWithBase(`webapp/credential-offers`, baseUrl) debug(`OID4VCIRestClient is going to send request: ${JSON.stringify(request)} to ${url}`) diff --git a/packages/oid4vci-issuer-rest-client/src/types/IOID4VCIRestClient.ts b/packages/oid4vci-issuer-rest-client/src/types/IOID4VCIRestClient.ts index 4f2f62709..8bcda7776 100644 --- a/packages/oid4vci-issuer-rest-client/src/types/IOID4VCIRestClient.ts +++ b/packages/oid4vci-issuer-rest-client/src/types/IOID4VCIRestClient.ts @@ -1,15 +1,19 @@ import { IAgentContext, IPluginMethodMap } from '@veramo/core' -import { CredentialOfferFormat, Grant, IssueStatusResponse } from '@sphereon/oid4vci-common' +import { + CredentialOfferFormat, + Grant, + IssueStatusResponse, + CredentialDataSupplierInput, + CreateCredentialOfferURIResult, +} from '@sphereon/oid4vci-common' export interface IOID4VCIRestClient extends IPluginMethodMap { oid4vciClientCreateOfferUri(args: IOID4VCIClientCreateOfferUriRequestArgs, context: IRequiredContext): Promise oid4vciClientGetIssueStatus(args: IOID4VCIClientGetIssueStatusArgs, context: IRequiredContext): Promise } -export interface IOID4VCIClientCreateOfferUriRequestArgs { - grants: Grant - credentials: (CredentialOfferFormat | string)[] - baseUrl?: string +export interface IOID4VCIClientCreateOfferUriRequestArgs extends IOID4VCIClientCreateOfferUriRequest { + agentBaseUrl?: string } export interface IOID4VCIClientGetIssueStatusArgs { @@ -17,13 +21,12 @@ export interface IOID4VCIClientGetIssueStatusArgs { baseUrl?: string } -export interface IOID4VCIClientCreateOfferUriResponse { - uri: string -} +export type IOID4VCIClientCreateOfferUriResponse = Omit export interface IOID4VCIClientCreateOfferUriRequest { credentials: (CredentialOfferFormat | string)[] grants: Grant + credentialDataSupplierInput?: CredentialDataSupplierInput } export type IRequiredContext = IAgentContext diff --git a/packages/oid4vci-issuer-store/package.json b/packages/oid4vci-issuer-store/package.json index cc9b7c8f4..72e9a8a2b 100644 --- a/packages/oid4vci-issuer-store/package.json +++ b/packages/oid4vci-issuer-store/package.json @@ -14,7 +14,7 @@ "build:clean": "tsc --build --clean && tsc --build" }, "dependencies": { - "@sphereon/oid4vci-common": "0.4.1-unstable.296", + "@sphereon/oid4vci-common": "0.4.1-unstable.302", "@sphereon/ssi-sdk-ext.did-utils": "^0.12.0", "@types/uuid": "^9.0.1", "@veramo/core": "4.2.0", diff --git a/packages/oid4vci-issuer/package.json b/packages/oid4vci-issuer/package.json index ee02a7024..b4e53c571 100644 --- a/packages/oid4vci-issuer/package.json +++ b/packages/oid4vci-issuer/package.json @@ -14,8 +14,8 @@ "build:clean": "tsc --build --clean && tsc --build" }, "dependencies": { - "@sphereon/oid4vci-common": "0.4.1-unstable.296", - "@sphereon/oid4vci-issuer": "0.4.1-unstable.296", + "@sphereon/oid4vci-common": "0.4.1-unstable.302", + "@sphereon/oid4vci-issuer": "0.4.1-unstable.302", "@sphereon/ssi-sdk.oid4vci-issuer-store": "workspace:*", "@sphereon/ssi-sdk.core": "workspace:*", "@sphereon/ssi-sdk-ext.did-utils": "^0.12.0", diff --git a/packages/oid4vci-issuer/src/agent/OID4VCIIssuer.ts b/packages/oid4vci-issuer/src/agent/OID4VCIIssuer.ts index 0a395068e..cd68f5aab 100644 --- a/packages/oid4vci-issuer/src/agent/OID4VCIIssuer.ts +++ b/packages/oid4vci-issuer/src/agent/OID4VCIIssuer.ts @@ -6,6 +6,7 @@ import { IAgentPlugin } from '@veramo/core' import { getAccessTokenSignerCallback } from '../functions' import { IAssertValidAccessTokenArgs, + ICreateCredentialOfferURIResult, ICreateOfferArgs, IIssueCredentialArgs, IIssuerInstanceArgs, @@ -35,10 +36,18 @@ export class OID4VCIIssuer implements IAgentPlugin { this._opts = opts ?? {} } - private async oid4vciCreateOfferURI(createArgs: ICreateOfferArgs, context: IRequiredContext): Promise { + private async oid4vciCreateOfferURI(createArgs: ICreateOfferArgs, context: IRequiredContext): Promise { return await this.oid4vciGetInstance(createArgs, context) .then((instance) => instance.get({ context })) - .then((issuer: VcIssuer) => issuer.createCredentialOfferURI(createArgs)) + .then((issuer: VcIssuer) => + issuer.createCredentialOfferURI(createArgs).then((response) => { + const result: ICreateCredentialOfferURIResult = response + if (this._opts.returnSessions === false) { + delete result.session + } + return result + }) + ) } private async oid4vciIssueCredential(issueArgs: IIssueCredentialArgs, context: IRequiredContext): Promise { diff --git a/packages/oid4vci-issuer/src/types/IOID4VCIIssuer.ts b/packages/oid4vci-issuer/src/types/IOID4VCIIssuer.ts index bf1a42c83..979eea091 100644 --- a/packages/oid4vci-issuer/src/types/IOID4VCIIssuer.ts +++ b/packages/oid4vci-issuer/src/types/IOID4VCIIssuer.ts @@ -1,4 +1,4 @@ -import { AccessTokenRequest, AccessTokenResponse } from '@sphereon/oid4vci-common' +import { AccessTokenRequest, AccessTokenResponse, CredentialDataSupplierInput, CredentialOfferSession } from '@sphereon/oid4vci-common' import { CredentialIssuerMetadataOpts, CredentialOfferFormat, @@ -11,20 +11,11 @@ import { CredentialDataSupplier } from '@sphereon/oid4vci-issuer/lib/types' import { IDIDOptions, ResolveOpts } from '@sphereon/ssi-sdk-ext.did-utils' import { IOID4VCIStore } from '@sphereon/ssi-sdk.oid4vci-issuer-store' import { ICredential } from '@sphereon/ssi-types/dist' -import { - IAgentContext, - ICredentialIssuer, - ICredentialVerifier, - IDataStoreORM, - IDIDManager, - IKeyManager, - IPluginMethodMap, - IResolver, -} from '@veramo/core' +import { IAgentContext, ICredentialIssuer, IDataStoreORM, IDIDManager, IKeyManager, IPluginMethodMap, IResolver } from '@veramo/core' import { IssuerInstance } from '../IssuerInstance' export interface IOID4VCIIssuer extends IPluginMethodMap { - oid4vciCreateOfferURI(createArgs: ICreateOfferArgs, context: IRequiredContext): Promise + oid4vciCreateOfferURI(createArgs: ICreateOfferArgs, context: IRequiredContext): Promise oid4vciIssueCredential(issueArgs: IIssueCredentialArgs, context: IRequiredContext): Promise oid4vciCreateAccessTokenResponse(accessTokenArgs: IAssertValidAccessTokenArgs, context: IRequiredContext): Promise oid4vciGetInstance(args: IIssuerInstanceArgs, context: IRequiredContext): Promise @@ -34,6 +25,7 @@ export interface IOID4VCIIssuerOpts { defaultStoreId?: string defaultNamespace?: string resolveOpts?: ResolveOpts + returnSessions?: boolean } export interface IIssuerDefaultOpts extends IIssuerOptions {} @@ -43,6 +35,7 @@ export interface ICreateOfferArgs extends IIssuerInstanceArgs { credentials?: (CredentialOfferFormat | string)[] credentialDefinition?: IssuerCredentialDefinition credentialOfferUri?: string + credentialDataSupplierInput?: CredentialDataSupplierInput // Optional storage that can help the credential Data Supplier. For instance to store credential input data during offer creation, if no additional data can be supplied later on baseUri?: string scheme?: string pinLength?: number @@ -52,6 +45,7 @@ export interface IIssueCredentialArgs extends IIssuerInstanceArgs { credentialRequest: CredentialRequestV1_0_11 credential?: ICredential credentialDataSupplier?: CredentialDataSupplier + credentialDataSupplierInput?: CredentialDataSupplierInput newCNonce?: string cNonceExpiresIn?: number tokenExpiresIn?: number @@ -86,6 +80,12 @@ export interface IMetadataOptions { storeNamespace?: string } -export type IRequiredContext = IAgentContext< - IDataStoreORM & IResolver & IDIDManager & IKeyManager & ICredentialIssuer & ICredentialVerifier & IOID4VCIStore -> +export type ICreateCredentialOfferURIResult = { + uri: string + session?: CredentialOfferSession + userPin?: string + userPinLength?: number + userPinRequired: boolean +} + +export type IRequiredContext = IAgentContext diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2a53928e9..d4a7457d2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -457,11 +457,11 @@ importers: packages/oid4vci-issuer: dependencies: '@sphereon/oid4vci-common': - specifier: 0.4.1-unstable.296 - version: 0.4.1-unstable.296 + specifier: 0.4.1-unstable.302 + version: 0.4.1-unstable.302 '@sphereon/oid4vci-issuer': - specifier: 0.4.1-unstable.296 - version: 0.4.1-unstable.296 + specifier: 0.4.1-unstable.302 + version: 0.4.1-unstable.302 '@sphereon/ssi-sdk-ext.did-utils': specifier: ^0.12.0 version: 0.12.0 @@ -515,14 +515,14 @@ importers: packages/oid4vci-issuer-rest-api: dependencies: '@sphereon/oid4vci-common': - specifier: 0.4.1-unstable.296 - version: 0.4.1-unstable.296 + specifier: 0.4.1-unstable.302 + version: 0.4.1-unstable.302 '@sphereon/oid4vci-issuer': - specifier: 0.4.1-unstable.296 - version: 0.4.1-unstable.296 + specifier: 0.4.1-unstable.302 + version: 0.4.1-unstable.302 '@sphereon/oid4vci-issuer-server': - specifier: 0.4.1-unstable.296 - version: 0.4.1-unstable.296 + specifier: 0.4.1-unstable.302 + version: 0.4.1-unstable.302 '@sphereon/ssi-sdk.kv-store-temp': specifier: workspace:* version: link:../kv-store @@ -666,8 +666,8 @@ importers: packages/oid4vci-issuer-rest-client: dependencies: '@sphereon/oid4vci-common': - specifier: 0.4.1-unstable.296 - version: 0.4.1-unstable.296 + specifier: 0.4.1-unstable.302 + version: 0.4.1-unstable.302 '@veramo/core': specifier: 4.2.0 version: 4.2.0(patch_hash=c5oempznsz4br5w3tcuk2i2mau) @@ -700,8 +700,8 @@ importers: packages/oid4vci-issuer-store: dependencies: '@sphereon/oid4vci-common': - specifier: 0.4.1-unstable.296 - version: 0.4.1-unstable.296 + specifier: 0.4.1-unstable.302 + version: 0.4.1-unstable.302 '@sphereon/ssi-sdk-ext.did-utils': specifier: ^0.12.0 version: 0.12.0 @@ -5637,8 +5637,8 @@ packages: - typescript dev: true - /@sphereon/oid4vci-common@0.4.1-unstable.296: - resolution: {integrity: sha512-Mt7o31iAjYT+FBYqlkYm2SQgaUjtE06jTK553aBDxPxuKF+qS03ItDbGp7/69e4Ki1TEFbr/4RZaJvvblrpHsA==} + /@sphereon/oid4vci-common@0.4.1-unstable.302: + resolution: {integrity: sha512-+fGc/66/0QdYcFi+1/m+WPxxT7iTDjskYiI4yEHP93wEPY9X429PW+RFdo37tWHvVxUFXTGFqN+dKL2H7sDm7Q==} engines: {node: '>=16'} dependencies: '@sphereon/ssi-types': link:packages/ssi-types @@ -5648,12 +5648,12 @@ packages: - encoding dev: false - /@sphereon/oid4vci-issuer-server@0.4.1-unstable.296: - resolution: {integrity: sha512-l8jMr8mxSc03fdTF9R+AKSLSEcE6O25yeHmm0vuhgof6wsVMyazaZHJbKcOB5ZjntYeSMmoUVRmkW3Z1d4hBKg==} + /@sphereon/oid4vci-issuer-server@0.4.1-unstable.302: + resolution: {integrity: sha512-vCKK25E63tekbUm4KErCgiWo1IS5gkX02roU0M6MtHXLtWolbOjruXgeohK1NLVeKP65u3s31WG5scWdwmWzLA==} engines: {node: '>=16'} dependencies: - '@sphereon/oid4vci-common': 0.4.1-unstable.296 - '@sphereon/oid4vci-issuer': 0.4.1-unstable.296 + '@sphereon/oid4vci-common': 0.4.1-unstable.302 + '@sphereon/oid4vci-issuer': 0.4.1-unstable.302 '@sphereon/ssi-types': link:packages/ssi-types body-parser: 1.20.2 cookie-parser: 1.4.6 @@ -5666,11 +5666,11 @@ packages: - supports-color dev: false - /@sphereon/oid4vci-issuer@0.4.1-unstable.296: - resolution: {integrity: sha512-IJ1hVBUs5LSVqgo7EY84lK9IQcQbnH8sWPTsz7J/A4p3/8IOJa/5hX+Stbe0O9qEwFvDYZsiNFfBl5yskDqWTw==} + /@sphereon/oid4vci-issuer@0.4.1-unstable.302: + resolution: {integrity: sha512-fKg21GAswy9b9vJVe+XjH4tXS8KM0V0cwLBu4cbTd7zo5HFn8KKqoHTVp6vIaqGQ8m07xBOP6T/CoESJw2kO+A==} engines: {node: '>=16'} dependencies: - '@sphereon/oid4vci-common': 0.4.1-unstable.296 + '@sphereon/oid4vci-common': 0.4.1-unstable.302 '@sphereon/ssi-types': link:packages/ssi-types uuid: 9.0.0 transitivePeerDependencies: