diff --git a/packages/client/lib/CredentialRequestClientBuilder.ts b/packages/client/lib/CredentialRequestClientBuilder.ts index 3b01cd41..b90f95ea 100644 --- a/packages/client/lib/CredentialRequestClientBuilder.ts +++ b/packages/client/lib/CredentialRequestClientBuilder.ts @@ -8,6 +8,7 @@ import { ExperimentalSubjectIssuance, OID4VCICredentialFormat, OpenId4VCIVersion, + SchemaValidation, UniformCredentialOfferRequest, } from '@sphereon/oid4vci-common'; import { CredentialFormat } from '@sphereon/ssi-types'; @@ -173,6 +174,11 @@ export class CredentialRequestClientBuilder { return this; } + public withSchemaValidation(schemaValidation: SchemaValidation): this { + this._builder.withSchemaValidation(schemaValidation); + return this; + } + public withFormat(format: CredentialFormat | OID4VCICredentialFormat): this { this._builder.withFormat(format); return this; diff --git a/packages/client/lib/CredentialRequestClientBuilderV1_0_11.ts b/packages/client/lib/CredentialRequestClientBuilderV1_0_11.ts index 0ce84145..fa7502c7 100644 --- a/packages/client/lib/CredentialRequestClientBuilderV1_0_11.ts +++ b/packages/client/lib/CredentialRequestClientBuilderV1_0_11.ts @@ -11,6 +11,7 @@ import { getTypesFromOfferV1_0_11, OID4VCICredentialFormat, OpenId4VCIVersion, + SchemaValidation, UniformCredentialOfferRequest, } from '@sphereon/oid4vci-common'; import { CredentialFormat } from '@sphereon/ssi-types'; @@ -24,6 +25,7 @@ export class CredentialRequestClientBuilderV1_0_11 { deferredCredentialAwait = false; deferredCredentialIntervalInMS = 5000; credentialTypes: string[] = []; + schemaValidation: SchemaValidation = SchemaValidation.WHEN_PRESENT; format?: CredentialFormat | OID4VCICredentialFormat; token?: string; version?: OpenId4VCIVersion; @@ -129,6 +131,11 @@ export class CredentialRequestClientBuilderV1_0_11 { return this; } + public withSchemaValidation(schemaValidation: SchemaValidation): this { + this.schemaValidation = schemaValidation; + return this; + } + public withFormat(format: CredentialFormat | OID4VCICredentialFormat): this { this.format = format; return this; diff --git a/packages/client/lib/CredentialRequestClientBuilderV1_0_13.ts b/packages/client/lib/CredentialRequestClientBuilderV1_0_13.ts index 23508740..8b61dea9 100644 --- a/packages/client/lib/CredentialRequestClientBuilderV1_0_13.ts +++ b/packages/client/lib/CredentialRequestClientBuilderV1_0_13.ts @@ -9,6 +9,7 @@ import { getIssuerFromCredentialOfferPayload, OID4VCICredentialFormat, OpenId4VCIVersion, + SchemaValidation, UniformCredentialOfferRequest, } from '@sphereon/oid4vci-common'; import { CredentialFormat } from '@sphereon/ssi-types'; @@ -23,6 +24,7 @@ export class CredentialRequestClientBuilderV1_0_13 { deferredCredentialIntervalInMS = 5000; credentialIdentifier?: string; credentialTypes?: string[] = []; + schemaValidation: SchemaValidation = SchemaValidation.WHEN_PRESENT; format?: CredentialFormat | OID4VCICredentialFormat; token?: string; version?: OpenId4VCIVersion; @@ -139,6 +141,11 @@ export class CredentialRequestClientBuilderV1_0_13 { return this; } + public withSchemaValidation(schemaValidation: SchemaValidation): this { + this.schemaValidation = schemaValidation; + return this; + } + public withFormat(format: CredentialFormat | OID4VCICredentialFormat): this { this.format = format; return this; diff --git a/packages/client/lib/CredentialRequestClientV1_0_11.ts b/packages/client/lib/CredentialRequestClientV1_0_11.ts index f1669aa0..f00ba712 100644 --- a/packages/client/lib/CredentialRequestClientV1_0_11.ts +++ b/packages/client/lib/CredentialRequestClientV1_0_11.ts @@ -13,6 +13,7 @@ import { OpenIDResponse, post, ProofOfPossession, + SchemaValidation, UniformCredentialRequest, URL_NOT_VALID, } from '@sphereon/oid4vci-common'; @@ -35,6 +36,7 @@ export interface CredentialRequestOptsV1_0_11 { format?: CredentialFormat | OID4VCICredentialFormat; proof: ProofOfPossession; token: string; + schemaValidation: SchemaValidation; version: OpenId4VCIVersion; } @@ -54,6 +56,9 @@ export class CredentialRequestClientV1_0_11 { return this.credentialRequestOpts.credentialEndpoint; } + public getSchemaValidation(): SchemaValidation { + return this.credentialRequestOpts.schemaValidation; + } public getDeferredCredentialEndpoint(): string | undefined { return this.credentialRequestOpts.deferredCredentialEndpoint; } diff --git a/packages/client/lib/__tests__/CredentialRequestClientV1_0_11.spec.ts b/packages/client/lib/__tests__/CredentialRequestClientV1_0_11.spec.ts index 9e07dcab..360603d2 100644 --- a/packages/client/lib/__tests__/CredentialRequestClientV1_0_11.spec.ts +++ b/packages/client/lib/__tests__/CredentialRequestClientV1_0_11.spec.ts @@ -8,6 +8,7 @@ import { Jwt, OpenId4VCIVersion, ProofOfPossession, + SchemaValidation, URL_NOT_VALID, WellKnownEndpoints, } from '@sphereon/oid4vci-common'; @@ -90,6 +91,7 @@ describe('Credential Request Client ', () => { const credReqClient = CredentialRequestClientBuilderV1_0_11.fromCredentialOffer({ credentialOffer: INITIATION_TEST_V1_0_08 }) .withCredentialEndpoint(basePath + '/credential') .withFormat('ldp_vc') + .withSchemaValidation(SchemaValidation.NEVER) .withCredentialType('https://imsglobal.github.io/openbadges-specification/ob_v3p0.html#OpenBadgeCredential') .build(); const proof: ProofOfPossession = await ProofOfPossessionBuilder.fromJwt({ @@ -103,6 +105,7 @@ describe('Credential Request Client ', () => { .withClientId('sphereon:wallet') .withKid(kid) .build(); + expect(credReqClient.getSchemaValidation()).toEqual(SchemaValidation.NEVER); expect(credReqClient.getCredentialEndpoint()).toEqual(basePath + '/credential'); const credentialRequest = await credReqClient.createCredentialRequest({ proofInput: proof, version: OpenId4VCIVersion.VER_1_0_08 }); expect(credentialRequest.proof?.jwt?.includes(partialJWT)).toBeTruthy(); @@ -120,6 +123,7 @@ describe('Credential Request Client ', () => { const credReqClient = CredentialRequestClientBuilderV1_0_11.fromCredentialOffer({ credentialOffer: INITIATION_TEST_V1_0_08 }) .withCredentialEndpoint(basePath + '/credential') .withFormat('ldp_vc') + .withSchemaValidation(SchemaValidation.ALWAYS) .withCredentialType('https://imsglobal.github.io/openbadges-specification/ob_v3p0.html#OpenBadgeCredential') .build(); const proof: ProofOfPossession = await ProofOfPossessionBuilder.fromJwt({ @@ -133,6 +137,7 @@ describe('Credential Request Client ', () => { .withClientId('sphereon:wallet') .withKid(kid_withoutDid) .build(); + expect(credReqClient.getSchemaValidation()).toEqual(SchemaValidation.ALWAYS); expect(credReqClient.getCredentialEndpoint()).toEqual(basePath + '/credential'); const credentialRequest = await credReqClient.createCredentialRequest({ proofInput: proof, version: OpenId4VCIVersion.VER_1_0_08 }); expect(credentialRequest.proof?.jwt?.includes(partialJWT_withoutDid)).toBeTruthy(); diff --git a/packages/oid4vci-common/lib/types/Generic.types.ts b/packages/oid4vci-common/lib/types/Generic.types.ts index a9680f0d..815ff658 100644 --- a/packages/oid4vci-common/lib/types/Generic.types.ts +++ b/packages/oid4vci-common/lib/types/Generic.types.ts @@ -424,3 +424,9 @@ export type NotificationResult = { export interface NotificationErrorResponse { error: NotificationError | string; } + +export enum SchemaValidation { + ALWAYS = 'ALWAYS', + NEVER = 'NEVER', + WHEN_PRESENT = 'WHEN_PRESENT', +}