diff --git a/packages/openid4vc/src/openid4vc-issuer/OpenId4VcIssuerService.ts b/packages/openid4vc/src/openid4vc-issuer/OpenId4VcIssuerService.ts index 8fad44c055..bb805a9126 100644 --- a/packages/openid4vc/src/openid4vc-issuer/OpenId4VcIssuerService.ts +++ b/packages/openid4vc/src/openid4vc-issuer/OpenId4VcIssuerService.ts @@ -113,6 +113,7 @@ export class OpenId4VcIssuerService { credentials: offeredCredentials, credentialOfferUri: hostedCredentialOfferUri, baseUri: options.baseUri, + credentialDataSupplierInput: options.issuanceMetadata, }) const issuanceSession = await this.openId4VcIssuanceSessionRepository.getSingleByQuery(agentContext, { @@ -469,6 +470,7 @@ export class OpenId4VcIssuerService { agentContext: AgentContext, options: OpenId4VciCreateCredentialResponseOptions & { issuer: OpenId4VcIssuerRecord + issuanceSession: OpenId4VcIssuanceSessionRecord } ): CredentialDataSupplier => { return async (args: CredentialDataSupplierArgs) => { @@ -497,6 +499,7 @@ export class OpenId4VcIssuerService { this.openId4VcIssuerConfig.credentialEndpoint.credentialRequestToCredentialMapper const signOptions = await mapper({ agentContext, + issuanceSession: options.issuanceSession, holderBinding, credentialOffer, diff --git a/packages/openid4vc/src/openid4vc-issuer/OpenId4VcIssuerServiceOptions.ts b/packages/openid4vc/src/openid4vc-issuer/OpenId4VcIssuerServiceOptions.ts index 9a2c4dfa42..8c696fabc5 100644 --- a/packages/openid4vc/src/openid4vc-issuer/OpenId4VcIssuerServiceOptions.ts +++ b/packages/openid4vc/src/openid4vc-issuer/OpenId4VcIssuerServiceOptions.ts @@ -1,3 +1,4 @@ +import type { OpenId4VcIssuanceSessionRecord } from './repository' import type { OpenId4VcCredentialHolderBinding, OpenId4VciCredentialOffer, @@ -37,6 +38,14 @@ export interface OpenId4VciCreateCredentialOfferOptions { baseUri?: string preAuthorizedCodeFlowConfig: OpenId4VciPreAuthorizedCodeFlowConfig + + /** + * Metadata about the issuance, that will be stored in the issuance session record and + * passed to the credential request to credential mapper. This can be used to e.g. store an + * user identifier so user data can be fetched in the credential mapper, or the actual credential + * data. + */ + issuanceMetadata?: Record } export interface OpenId4VciCreateCredentialResponseOptions { @@ -60,6 +69,12 @@ export interface OpenId4VciCreateCredentialResponseOptions { export type OpenId4VciCredentialRequestToCredentialMapper = (options: { agentContext: AgentContext + /** + * The issuance session associated with the credential request. You can extract the + * issuance metadata from this record if passed in the offer creation method. + */ + issuanceSession: OpenId4VcIssuanceSessionRecord + /** * The credential request received from the wallet */ diff --git a/packages/openid4vc/src/openid4vc-issuer/__tests__/openid4vc-issuer.test.ts b/packages/openid4vc/src/openid4vc-issuer/__tests__/openid4vc-issuer.test.ts index d6678c2a09..eab440259f 100644 --- a/packages/openid4vc/src/openid4vc-issuer/__tests__/openid4vc-issuer.test.ts +++ b/packages/openid4vc/src/openid4vc-issuer/__tests__/openid4vc-issuer.test.ts @@ -42,7 +42,6 @@ import { agentDependencies } from '../../../../node/src' import { OpenId4VciCredentialFormatProfile } from '../../shared' import { OpenId4VcIssuanceSessionState } from '../OpenId4VcIssuanceSessionState' import { OpenId4VcIssuerModule } from '../OpenId4VcIssuerModule' -import { OpenId4VcIssuerService } from '../OpenId4VcIssuerService' import { OpenId4VcIssuanceSessionRepository } from '../repository' const openBadgeCredential = { @@ -368,6 +367,9 @@ describe('OpenId4VcIssuer', () => { preAuthorizedCode, userPinRequired: false, }, + issuanceMetadata: { + myIssuance: 'metadata', + }, }) const issuanceSessionRepository = issuer.context.dependencyManager.resolve(OpenId4VcIssuanceSessionRepository) @@ -381,16 +383,23 @@ describe('OpenId4VcIssuer', () => { const issuerMetadata = await issuer.modules.openId4VcIssuer.getIssuerMetadata(openId4VcIssuer.issuerId) const { credentialResponse } = await issuer.modules.openId4VcIssuer.createCredentialResponse({ issuanceSessionId: result.issuanceSession.id, - credentialRequestToCredentialMapper: () => ({ - format: 'jwt_vc', - credential: new W3cCredential({ - type: openBadgeCredential.types, - issuer: new W3cIssuer({ id: issuerDid }), - credentialSubject: new W3cCredentialSubject({ id: holderDid }), - issuanceDate: w3cDate(Date.now()), - }), - verificationMethod: issuerVerificationMethod.id, - }), + credentialRequestToCredentialMapper: ({ issuanceSession }) => { + expect(issuanceSession.id).toEqual(result.issuanceSession.id) + expect(issuanceSession.issuanceMetadata).toEqual({ + myIssuance: 'metadata', + }) + + return { + format: 'jwt_vc', + credential: new W3cCredential({ + type: openBadgeCredential.types, + issuer: new W3cIssuer({ id: issuerDid }), + credentialSubject: new W3cCredentialSubject({ id: holderDid }), + issuanceDate: w3cDate(Date.now()), + }), + verificationMethod: issuerVerificationMethod.id, + } + }, credentialRequest: await createCredentialRequest(holder.context, { credentialSupported: openBadgeCredential, issuerMetadata,