diff --git a/packages/callback-example/lib/__tests__/issuerCallback.spec.ts b/packages/callback-example/lib/__tests__/issuerCallback.spec.ts index 572da72e..e69a65f1 100644 --- a/packages/callback-example/lib/__tests__/issuerCallback.spec.ts +++ b/packages/callback-example/lib/__tests__/issuerCallback.spec.ts @@ -264,7 +264,7 @@ describe('issuerCallback', () => { // format: 'jwt_vc_json', proof: { jwt: expect.stringContaining('eyJhbGciOiJFUzI1NiIsImtpZCI6ImRpZDpleGFtcGxlOmViZmViMWY3MTJlYmM2ZjFj'), - proof_type: 'jwt', + proof_type: 'JWT', }, credential_identifier: 'VerifiableCredential', }) diff --git a/packages/client/lib/AccessTokenClient.ts b/packages/client/lib/AccessTokenClient.ts index cab19221..b5630b1c 100644 --- a/packages/client/lib/AccessTokenClient.ts +++ b/packages/client/lib/AccessTokenClient.ts @@ -50,6 +50,7 @@ export class AccessTokenClient { redirectUri, pin, pinMetadata, + credentialIssuer: issuer, }), pinMetadata, metadata, @@ -95,7 +96,8 @@ export class AccessTokenClient { if (asOpts?.clientOpts?.clientId) { request.client_id = asOpts.clientOpts.clientId; } - await createJwtBearerClientAssertion(request, opts); + const credentialIssuer = opts.credentialIssuer ?? credentialOfferRequest?.credential_offer?.credential_issuer; + await createJwtBearerClientAssertion(request, { ...opts, credentialIssuer }); if (credentialOfferRequest?.supportedFlows.includes(AuthzFlowType.PRE_AUTHORIZED_CODE_FLOW)) { this.assertAlphanumericPin(opts.pinMetadata, pin); diff --git a/packages/client/lib/AccessTokenClientV1_0_11.ts b/packages/client/lib/AccessTokenClientV1_0_11.ts index f1c81080..8066ea62 100644 --- a/packages/client/lib/AccessTokenClientV1_0_11.ts +++ b/packages/client/lib/AccessTokenClientV1_0_11.ts @@ -95,11 +95,12 @@ export class AccessTokenClientV1_0_11 { ? await toUniformCredentialOfferRequest(opts.credentialOffer as CredentialOfferV1_0_11 | CredentialOfferV1_0_13) : undefined; const request: Partial = { ...opts.additionalParams }; + const credentialIssuer = opts.credentialIssuer ?? credentialOfferRequest?.credential_offer?.credential_issuer; if (asOpts?.clientOpts?.clientId) { request.client_id = asOpts.clientOpts.clientId; } - await createJwtBearerClientAssertion(request, { ...opts, version: OpenId4VCIVersion.VER_1_0_11 }); + await createJwtBearerClientAssertion(request, { ...opts, version: OpenId4VCIVersion.VER_1_0_11, credentialIssuer }); if (credentialOfferRequest?.supportedFlows.includes(AuthzFlowType.PRE_AUTHORIZED_CODE_FLOW)) { this.assertNumericPin(this.isPinRequiredValue(credentialOfferRequest.credential_offer), pin); diff --git a/packages/client/lib/AuthorizationCodeClient.ts b/packages/client/lib/AuthorizationCodeClient.ts index 6de5e665..2b273c58 100644 --- a/packages/client/lib/AuthorizationCodeClient.ts +++ b/packages/client/lib/AuthorizationCodeClient.ts @@ -52,14 +52,14 @@ export async function createSignedAuthRequestWhenNeeded(requestObject: Record { if (jwt) { this.withJwt(jwt); } else { - this.withTyp(version < OpenId4VCIVersion.VER_1_0_11 || mode === 'jwt' ? 'jwt' : 'openid4vci-proof+jwt'); + this.withTyp(version < OpenId4VCIVersion.VER_1_0_11 || mode === 'JWT' ? 'JWT' : 'openid4vci-proof+jwt'); } if (accessTokenResponse) { this.withAccessTokenResponse(accessTokenResponse); @@ -64,7 +64,7 @@ export class ProofOfPossessionBuilder { jwt, callbacks, version, - mode = 'jwt', + mode = 'JWT', }: { jwt?: Jwt; callbacks: ProofOfPossessionCallbacks; @@ -144,11 +144,11 @@ export class ProofOfPossessionBuilder { withTyp(typ: Typ): this { if (this.mode === 'pop' && this.version >= OpenId4VCIVersion.VER_1_0_11) { if (!!typ && typ !== 'openid4vci-proof+jwt') { - throw Error('typ must be openid4vci-proof+jwt for version 1.0.11 and up'); + throw Error(`typ must be openid4vci-proof+jwt for version 1.0.11 and up. Provided: ${typ}`); } } else { - if (!!typ && typ !== 'jwt') { - throw Error('typ must be jwt for version 1.0.10 and below'); + if (!!typ && typ !== 'JWT') { + throw Error(`typ must be jwt for version 1.0.10 and below. Provided: ${typ}`); } } this.typ = typ; @@ -216,7 +216,7 @@ export class ProofOfPossessionBuilder { this.mode, this.callbacks, { - typ: this.typ ?? (this.version < OpenId4VCIVersion.VER_1_0_11 || this.mode === 'jwt' ? 'jwt' : 'openid4vci-proof+jwt'), + typ: this.typ ?? (this.version < OpenId4VCIVersion.VER_1_0_11 || this.mode === 'JWT' ? 'JWT' : 'openid4vci-proof+jwt'), kid: this.kid, jwk: this.jwk, jti: this.jti, diff --git a/packages/client/lib/__tests__/CredentialRequestClient.spec.ts b/packages/client/lib/__tests__/CredentialRequestClient.spec.ts index 64579f1f..b9ee8037 100644 --- a/packages/client/lib/__tests__/CredentialRequestClient.spec.ts +++ b/packages/client/lib/__tests__/CredentialRequestClient.spec.ts @@ -29,7 +29,7 @@ import { getMockData } from './data/VciDataFixtures'; const partialJWT = 'eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJkaWQ6ZXhhbXBsZTplYmZlYjFmN'; const jwt1_0_08: Jwt = { - header: { alg: Alg.ES256, kid: 'did:example:ebfeb1f712ebc6f1c276e12ec21/keys/1', typ: 'jwt' }, + header: { alg: Alg.ES256, kid: 'did:example:ebfeb1f712ebc6f1c276e12ec21/keys/1', typ: 'JWT' }, payload: { iss: 'sphereon:wallet', nonce: 'tZignsnFbp', jti: 'tZignsnFbp223', aud: IDENTIPROOF_ISSUER_URL }, }; @@ -184,7 +184,7 @@ describe('Credential Request Client with different issuers ', () => { .build() .createCredentialRequest({ proofInput: { - proof_type: 'jwt', + proof_type: 'JWT', jwt: getMockData('spruce')?.credential.request.proof.jwt as string, }, credentialTypes: 'OpenBadgeCredential', @@ -208,7 +208,7 @@ describe('Credential Request Client with different issuers ', () => { .build() .createCredentialRequest({ proofInput: { - proof_type: 'jwt', + proof_type: 'JWT', jwt: getMockData('walt')?.credential.request.proof.jwt as string, }, credentialTypes: ['OpenBadgeCredential'], @@ -231,7 +231,7 @@ describe('Credential Request Client with different issuers ', () => { .build() .createCredentialRequest({ proofInput: { - proof_type: 'jwt', + proof_type: 'JWT', jwt: getMockData('uniissuer')?.credential.request.proof.jwt as string, }, credentialIdentifier: 'OpenBadgeCredential', @@ -253,7 +253,7 @@ describe('Credential Request Client with different issuers ', () => { .build() .createCredentialRequest({ proofInput: { - proof_type: 'jwt', + proof_type: 'JWT', jwt: getMockData('mattr')?.credential.request.proof.jwt as string, }, credentialTypes: ['OpenBadgeCredential'], @@ -276,7 +276,7 @@ describe('Credential Request Client with different issuers ', () => { .build() .createCredentialRequest({ proofInput: { - proof_type: 'jwt', + proof_type: 'JWT', jwt: getMockData('diwala')?.credential.request.proof.jwt as string, }, credentialTypes: ['OpenBadgeCredential'], @@ -318,7 +318,7 @@ describe('Credential Request Client with different issuers ', () => { .build() .createCredentialRequest({ proofInput: { - proof_type: 'jwt', + proof_type: 'JWT', jwt: getMockData('diwala')?.credential.request.proof.jwt as string, }, credentialIdentifier: 'BevoegdheidUittreksel_jwt_vc_json', @@ -337,7 +337,7 @@ describe('Credential Request Client with different issuers ', () => { expect(credentialRequest.credential_identifier).toEqual('BevoegdheidUittreksel_jwt_vc_json'); expect(credentialRequest.proof).toEqual({ jwt: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJFZERTQSIsImtpZCI6ImRpZDprZXk6ejZNa3AxM3N6QUFMVFN0cDV1OGtMcnl5YW5vYWtrVWtFUGZXazdvOHY3dms0RW1KI3o2TWtwMTNzekFBTFRTdHA1dThrTHJ5eWFub2Fra1VrRVBmV2s3bzh2N3ZrNEVtSiJ9.eyJhdWQiOiJodHRwczovL29pZGM0dmMuZGl3YWxhLmlvIiwiaWF0IjoxNjgxOTE1MDk1LjIwMiwiZXhwIjoxNjgxOTE1NzU1LjIwMiwiaXNzIjoic3BoZXJlb246c3NpLXdhbGxldCIsImp0aSI6IjYxN2MwM2EzLTM3MTUtNGJlMy1hYjkxNzM4MTlmYzYxNTYzIn0.KA-cHjecaYp9FSaWHkz5cqtNyhBIVT_0I7cJnpHn03T4UWFvdhjhn8Hpe-BU247enFyWOWJ6v3NQZyZgle7xBA', - proof_type: 'jwt', + proof_type: 'JWT', }); }); }); diff --git a/packages/client/lib/__tests__/CredentialRequestClientBuilder.spec.ts b/packages/client/lib/__tests__/CredentialRequestClientBuilder.spec.ts index f011edf1..23af7e8a 100644 --- a/packages/client/lib/__tests__/CredentialRequestClientBuilder.spec.ts +++ b/packages/client/lib/__tests__/CredentialRequestClientBuilder.spec.ts @@ -20,7 +20,7 @@ const partialJWT = 'eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJkaWQ6ZXhhbXBsZTplYmZlYjFmN'; const partialJWT_withoutDid = 'eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJlYmZlYjFmNzEyZWJjNmYxYzI3N'; /*const jwtv1_0_08: Jwt = { - header: { alg: Alg.ES256, kid: 'did:example:ebfeb1f712ebc6f1c276e12ec21/keys/1', typ: 'jwt' }, + header: { alg: Alg.ES256, kid: 'did:example:ebfeb1f712ebc6f1c276e12ec21/keys/1', typ: 'JWT' }, payload: { iss: 'sphereon:wallet', nonce: 'tZignsnFbp', jti: 'tZignsnFbp223', aud: IDENTIPROOF_ISSUER_URL }, };*/ diff --git a/packages/client/lib/__tests__/CredentialRequestClientV1_0_11.spec.ts b/packages/client/lib/__tests__/CredentialRequestClientV1_0_11.spec.ts index ebdda679..cf091709 100644 --- a/packages/client/lib/__tests__/CredentialRequestClientV1_0_11.spec.ts +++ b/packages/client/lib/__tests__/CredentialRequestClientV1_0_11.spec.ts @@ -31,12 +31,12 @@ const partialJWT = 'eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJkaWQ6ZXhhbXBsZTplYmZlYjFmN'; const partialJWT_withoutDid = 'eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJlYmZlYjFmNzEyZWJjNmYxYzI3N'; const jwt: Jwt = { - header: { alg: Alg.ES256, kid: 'did:example:ebfeb1f712ebc6f1c276e12ec21/keys/1', typ: 'jwt' }, + header: { alg: Alg.ES256, kid: 'did:example:ebfeb1f712ebc6f1c276e12ec21/keys/1', typ: 'JWT' }, payload: { iss: 'sphereon:wallet', nonce: 'tZignsnFbp', jti: 'tZignsnFbp223', aud: IDENTIPROOF_ISSUER_URL }, }; const jwt_withoutDid: Jwt = { - header: { alg: Alg.ES256, kid: 'ebfeb1f712ebc6f1c276e12ec21/keys/1', typ: 'jwt' }, + header: { alg: Alg.ES256, kid: 'ebfeb1f712ebc6f1c276e12ec21/keys/1', typ: 'JWT' }, payload: { iss: 'sphereon:wallet', nonce: 'tZignsnFbp', jti: 'tZignsnFbp223', aud: IDENTIPROOF_ISSUER_URL }, }; @@ -305,7 +305,7 @@ describe('Credential Request Client with different issuers ', () => { .build() .createCredentialRequest({ proofInput: { - proof_type: 'jwt', + proof_type: 'JWT', jwt: getMockData('spruce')?.credential.request.proof.jwt as string, }, credentialTypes: ['OpenBadgeCredential'], @@ -329,7 +329,7 @@ describe('Credential Request Client with different issuers ', () => { .build() .createCredentialRequest({ proofInput: { - proof_type: 'jwt', + proof_type: 'JWT', jwt: getMockData('walt')?.credential.request.proof.jwt as string, }, credentialTypes: ['OpenBadgeCredential'], @@ -352,7 +352,7 @@ describe('Credential Request Client with different issuers ', () => { .build() .createCredentialRequest({ proofInput: { - proof_type: 'jwt', + proof_type: 'JWT', jwt: getMockData('uniissuer')?.credential.request.proof.jwt as string, }, credentialTypes: ['OpenBadgeCredential'], @@ -374,7 +374,7 @@ describe('Credential Request Client with different issuers ', () => { .build() .createCredentialRequest({ proofInput: { - proof_type: 'jwt', + proof_type: 'JWT', jwt: getMockData('mattr')?.credential.request.proof.jwt as string, }, credentialTypes: ['OpenBadgeCredential'], @@ -397,7 +397,7 @@ describe('Credential Request Client with different issuers ', () => { .build() .createCredentialRequest({ proofInput: { - proof_type: 'jwt', + proof_type: 'JWT', jwt: getMockData('diwala')?.credential.request.proof.jwt as string, }, credentialTypes: ['OpenBadgeCredential'], diff --git a/packages/client/lib/__tests__/ProofOfPossessionBuilder.spec.ts b/packages/client/lib/__tests__/ProofOfPossessionBuilder.spec.ts index 0c57e951..6cf40bc2 100644 --- a/packages/client/lib/__tests__/ProofOfPossessionBuilder.spec.ts +++ b/packages/client/lib/__tests__/ProofOfPossessionBuilder.spec.ts @@ -8,12 +8,12 @@ import { ProofOfPossessionBuilder } from '..'; import { IDENTIPROOF_ISSUER_URL } from './MetadataMocks'; const jwt: Jwt = { - header: { alg: Alg.ES256, kid: 'did:example:ebfeb1f712ebc6f1c276e12ec21/keys/1', typ: 'jwt' }, + header: { alg: Alg.ES256, kid: 'did:example:ebfeb1f712ebc6f1c276e12ec21/keys/1', typ: 'JWT' }, payload: { iss: 'sphereon:wallet', nonce: 'tZignsnFbp', jti: 'tZignsnFbp223', aud: IDENTIPROOF_ISSUER_URL, iat: Date.now() / 1000 }, }; const jwt_withoutDid: Jwt = { - header: { alg: Alg.ES256, kid: 'ebfeb1f712ebc6f1c276e12ec21/keys/1', typ: 'jwt' }, + header: { alg: Alg.ES256, kid: 'ebfeb1f712ebc6f1c276e12ec21/keys/1', typ: 'JWT' }, payload: { iss: 'sphereon:wallet', nonce: 'tZignsnFbp', jti: 'tZignsnFbp223', aud: IDENTIPROOF_ISSUER_URL, iat: Date.now() / 1000 }, }; diff --git a/packages/client/lib/__tests__/data/VciDataFixtures.ts b/packages/client/lib/__tests__/data/VciDataFixtures.ts index f99437c9..d80661bf 100644 --- a/packages/client/lib/__tests__/data/VciDataFixtures.ts +++ b/packages/client/lib/__tests__/data/VciDataFixtures.ts @@ -51,7 +51,7 @@ export interface IssuerMockData { type?: string; format: 'jwt_vc' | 'ldp_vc' | 'jwt_vc_json-ld' | string; proof: { - proof_type: 'jwt' | string; + proof_type: 'JWT' | string; jwt: string; }; }; @@ -119,7 +119,7 @@ const mockData: VciMockDataStructure = { type: 'OpenBadgeCredential', format: 'jwt_vc', proof: { - proof_type: 'jwt', + proof_type: 'JWT', jwt: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksiLCJraWQiOiJkaWQ6andrOmV5SmhiR2NpT2lKRlV6STFOa3NpTENKMWMyVWlPaUp6YVdjaUxDSnJkSGtpT2lKRlF5SXNJbU55ZGlJNkluTmxZM0F5TlRack1TSXNJbmdpT2lKclpuVmpTa0V0VEhKck9VWjBPRmx5TFVkMlQzSmpia3N3YjNkc2RqUlhNblUwU3pJeFNHZHZTVlIzSWl3aWVTSTZJalozY0ZCUE1rOUNRVXBTU0ZFMVRXdEtXVlJaV0dsQlJFUXdOMU5OTlV0amVXcDNYMkUzVUUxWmVGa2lmUSMwIn0.eyJhdWQiOiJodHRwczovL25naS1vaWRjNHZjaS10ZXN0LnNwcnVjZWlkLnh5eiIsImlhdCI6MTY4MTkxMTA2MC45NDIsImV4cCI6MTY4MTkxMTcyMC45NDIsImlzcyI6InNwaGVyZW9uOnNzaS13YWxsZXQiLCJqdGkiOiJhNjA4MzMxZi02ZmE0LTQ0ZjAtYWNkZWY5NmFjMjdmNmQ3MCJ9.NwF3_41gwnlIdd_6Uk9CczeQHzIQt6UcvTT5Cxv72j9S1vNwiY9annA2kLsjsTiR5-WMBdUhJCO7wYCtZ15mxw', }, }, @@ -365,7 +365,7 @@ const mockData: VciMockDataStructure = { types: ['OpenBadgeCredential'], format: 'jwt_vc', proof: { - proof_type: 'jwt', + proof_type: 'JWT', jwt: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksiLCJraWQiOiJkaWQ6andrOmV5SmhiR2NpT2lKRlV6STFOa3NpTENKMWMyVWlPaUp6YVdjaUxDSnJkSGtpT2lKRlF5SXNJbU55ZGlJNkluTmxZM0F5TlRack1TSXNJbmdpT2lKclpuVmpTa0V0VEhKck9VWjBPRmx5TFVkMlQzSmpia3N3YjNkc2RqUlhNblUwU3pJeFNHZHZTVlIzSWl3aWVTSTZJalozY0ZCUE1rOUNRVXBTU0ZFMVRXdEtXVlJaV0dsQlJFUXdOMU5OTlV0amVXcDNYMkUzVUUxWmVGa2lmUSMwIn0.eyJhdWQiOiJodHRwczovL2pmZi53YWx0LmlkL2lzc3Vlci1hcGkvZGVmYXVsdC9vaWRjLyIsImlhdCI6MTY4MTkxMTk0Mi4yMzgsImV4cCI6MTY4MTkxMjYwMi4yMzgsIm5vbmNlIjoiZjA2YTMxMDUtYTJlZC00NGZjLTk1NGItNGEyNTk3MDM0OTNiIiwiaXNzIjoic3BoZXJlb246c3NpLXdhbGxldCIsImp0aSI6IjA1OWM3ODA5LTlmOGYtNGE3ZS1hZDI4YTNhMTNhMGIzNmViIn0.RfiWyybxpe3nkx3b0yIsqDHQtvB1WwhDW4t0X-kijy2dsSfv2cYhSEmAzs1shg7OV4EW8fSzt_Te79xiVl6jCw', }, }, @@ -483,7 +483,7 @@ const mockData: VciMockDataStructure = { types: ['OpenBadgeCredential'], format: 'jwt_vc', proof: { - proof_type: 'jwt', + proof_type: 'JWT', jwt: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksiLCJraWQiOiJkaWQ6andrOmV5SmhiR2NpT2lKRlV6STFOa3NpTENKMWMyVWlPaUp6YVdjaUxDSnJkSGtpT2lKRlF5SXNJbU55ZGlJNkluTmxZM0F5TlRack1TSXNJbmdpT2lKclpuVmpTa0V0VEhKck9VWjBPRmx5TFVkMlQzSmpia3N3YjNkc2RqUlhNblUwU3pJeFNHZHZTVlIzSWl3aWVTSTZJalozY0ZCUE1rOUNRVXBTU0ZFMVRXdEtXVlJaV0dsQlJFUXdOMU5OTlV0amVXcDNYMkUzVUUxWmVGa2lmUSMwIn0.eyJhdWQiOiJodHRwczovL29pZGM0dmMudW5paXNzdWVyLmlvLyIsImlhdCI6MTY4MTkxMjgzNy40MTQsImV4cCI6MTY4MTkxMzQ5Ny40MTQsIm5vbmNlIjoiMzhkMzZmM2ItNzJlMy00ODg2LWI2MGMtMzZiNzcwZDBlNGVhIiwiaXNzIjoic3BoZXJlb246c3NpLXdhbGxldCIsImp0aSI6ImIzYWEyMmFkLWExZTItNDJjOC1iMGI4ZTdjNDgzZDg4M2U4In0.awwIJ0422HSdOsCIe8k7zjxqY6RVaHK2ItUFqbmVjqLXxWt-Mp7cXF84n9HGgC8fgGOKmjlgXdNLr_Jiio_e3g', }, }, @@ -582,7 +582,7 @@ const mockData: VciMockDataStructure = { type: 'OpenBadgeCredential', format: 'ldp_vc', proof: { - proof_type: 'jwt', + proof_type: 'JWT', jwt: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJFZERTQSIsImtpZCI6ImRpZDprZXk6ejZNa3AxM3N6QUFMVFN0cDV1OGtMcnl5YW5vYWtrVWtFUGZXazdvOHY3dms0RW1KI3o2TWtwMTNzekFBTFRTdHA1dThrTHJ5eWFub2Fra1VrRVBmV2s3bzh2N3ZrNEVtSiJ9.eyJhdWQiOiJodHRwczovL2xhdW5jaHBhZC5tYXR0cmxhYnMuY29tIiwiaWF0IjoxNjgxOTE0NDgyLjUxOSwiZXhwIjoxNjgxOTE1MTQyLjUxOSwiaXNzIjoic3BoZXJlb246c3NpLXdhbGxldCIsImp0aSI6ImI5NDY1ZGE5LTY4OGYtNDdjNi04MjUwNDA0ZGNiOWI5Y2E5In0.uQ8ewOfIjy_1p_Gk6PjeEWccBJnjOca1pwbTWiCAFMQX9wlIsfeUdGtXUoHjH5_PQtpwytodx7WU456_CT9iBQ', }, }, @@ -696,7 +696,7 @@ const mockData: VciMockDataStructure = { type: 'OpenBadgeCredential', format: 'ldp_vc', proof: { - proof_type: 'jwt', + proof_type: 'JWT', jwt: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJFZERTQSIsImtpZCI6ImRpZDprZXk6ejZNa3AxM3N6QUFMVFN0cDV1OGtMcnl5YW5vYWtrVWtFUGZXazdvOHY3dms0RW1KI3o2TWtwMTNzekFBTFRTdHA1dThrTHJ5eWFub2Fra1VrRVBmV2s3bzh2N3ZrNEVtSiJ9.eyJhdWQiOiJodHRwczovL29pZGM0dmMuZGl3YWxhLmlvIiwiaWF0IjoxNjgxOTE1MDk1LjIwMiwiZXhwIjoxNjgxOTE1NzU1LjIwMiwiaXNzIjoic3BoZXJlb246c3NpLXdhbGxldCIsImp0aSI6IjYxN2MwM2EzLTM3MTUtNGJlMy1hYjkxNzM4MTlmYzYxNTYzIn0.KA-cHjecaYp9FSaWHkz5cqtNyhBIVT_0I7cJnpHn03T4UWFvdhjhn8Hpe-BU247enFyWOWJ6v3NQZyZgle7xBA', }, }, diff --git a/packages/client/lib/functions/AccessTokenUtil.ts b/packages/client/lib/functions/AccessTokenUtil.ts index 7617551d..b22a4034 100644 --- a/packages/client/lib/functions/AccessTokenUtil.ts +++ b/packages/client/lib/functions/AccessTokenUtil.ts @@ -9,25 +9,28 @@ export const createJwtBearerClientAssertion = async ( version?: OpenId4VCIVersion; }, ): Promise => { - const { asOpts } = opts; + const { asOpts, credentialIssuer } = opts; if (asOpts?.clientOpts?.clientAssertionType === 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer') { - if (!request.client_id) { - throw Error(`Not client_id supplied, but client-assertion jwt-bearer requested.`); - } else if (!asOpts.clientOpts.kid) { - throw Error(`No kid supplied, but client-assertion jwt-bearer requested.`); - } else if (!asOpts.clientOpts.signCallbacks) { - throw Error(`No sign callback supplied, but client-assertion jwt-bearer requested.`); + const { kid, clientId = request.client_id, signCallbacks, alg } = asOpts.clientOpts; + if (!clientId) { + return Promise.reject(Error(`Not client_id supplied, but client-assertion jwt-bearer requested.`)); + } else if (!kid) { + return Promise.reject(Error(`No kid supplied, but client-assertion jwt-bearer requested.`)); + } else if (typeof signCallbacks !== 'function') { + return Promise.reject(Error(`No sign callback supplied, but client-assertion jwt-bearer requested.`)); + } else if (!credentialIssuer) { + return Promise.reject(Error(`No credential issuer supplied, but client-assertion jwt-bearer requested.`)); } const jwt: Jwt = { header: { typ: 'JWT', - kid: asOpts.clientOpts.kid, - alg: asOpts.clientOpts.alg ?? 'ES256', + kid: kid, + alg: alg ?? 'ES256', }, payload: { - iss: request.client_id, - sub: request.client_id, - aud: opts.credentialIssuer, + iss: clientId, + sub: clientId, + aud: credentialIssuer, jti: v4(), exp: Date.now() / 1000 + 60, iat: Date.now() / 1000 - 60, @@ -35,9 +38,9 @@ export const createJwtBearerClientAssertion = async ( }; const pop = await ProofOfPossessionBuilder.fromJwt({ jwt, - callbacks: asOpts.clientOpts.signCallbacks, + callbacks: signCallbacks, version: opts.version ?? OpenId4VCIVersion.VER_1_0_13, - mode: 'jwt', + mode: 'JWT', }).build(); request.client_assertion_type = 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer'; request.client_assertion = pop.jwt; diff --git a/packages/common/lib/functions/FormatUtils.ts b/packages/common/lib/functions/FormatUtils.ts index ed2a6b08..5d2fc9ec 100644 --- a/packages/common/lib/functions/FormatUtils.ts +++ b/packages/common/lib/functions/FormatUtils.ts @@ -27,7 +27,7 @@ export function getUniformFormat(format: string | OID4VCICredentialFormat | Cred } // Older formats - if (format === 'jwt_vc' || format === 'jwt') { + if (format.toLocaleLowerCase() === 'jwt_vc' || format.toLocaleLowerCase() === 'jwt') { return 'jwt_vc'; } if (format === 'ldp_vc' || format === 'ldp') { diff --git a/packages/common/lib/functions/ProofUtil.ts b/packages/common/lib/functions/ProofUtil.ts index 0a82a56a..a20bef3a 100644 --- a/packages/common/lib/functions/ProofUtil.ts +++ b/packages/common/lib/functions/ProofUtil.ts @@ -50,7 +50,7 @@ export const createProofOfPossession = async ( const signerArgs = createJWT(popMode, jwtProps, existingJwt); const jwt = await callbacks.signCallback(signerArgs, signerArgs.header.kid); const proof = { - proof_type: 'jwt', + proof_type: 'JWT', jwt, } as ProofOfPossession; @@ -133,7 +133,7 @@ const createJWT = (mode: PoPMode, jwtProps?: JwtProps, existingJwt?: Jwt): Jwt = // mode === 'pop' getJwtProperty('iss', false, jwtProps?.clientId, existingJwt?.payload?.iss); // : getJwtProperty('iss', false, jwtProps?.issuer, existingJwt?.payload?.iss); - const client_id = mode === 'jwt' ? getJwtProperty('client_id', false, jwtProps?.clientId, existingJwt?.payload?.client_id) : undefined; + const client_id = mode === 'JWT' ? getJwtProperty('client_id', false, jwtProps?.clientId, existingJwt?.payload?.client_id) : undefined; const jti = getJwtProperty('jti', false, jwtProps?.jti, existingJwt?.payload?.jti); const typ = getJwtProperty('typ', true, jwtProps?.typ, existingJwt?.header?.typ, 'openid4vci-proof+jwt'); const nonce = getJwtProperty('nonce', false, jwtProps?.nonce, existingJwt?.payload?.nonce); // Officially this is required, but some implementations don't have it diff --git a/packages/common/lib/types/CredentialIssuance.types.ts b/packages/common/lib/types/CredentialIssuance.types.ts index fc161411..2128ed68 100644 --- a/packages/common/lib/types/CredentialIssuance.types.ts +++ b/packages/common/lib/types/CredentialIssuance.types.ts @@ -64,7 +64,7 @@ export interface UniformCredentialOfferRequest extends AssertedUniformCredential export type UniformCredentialOfferPayload = CredentialOfferPayloadV1_0_11 | CredentialOfferPayloadV1_0_13; export interface ProofOfPossession { - proof_type: 'jwt'; + proof_type: 'JWT'; jwt: string; [x: string]: unknown; @@ -158,7 +158,7 @@ export enum Alg { } export type Typ = - | 'jwt' + | 'JWT' // https://www.rfc-editor.org/rfc/rfc8725.pdf#name-use-explicit-typing // https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html#section-7.2.1-2.1.2.1.2.1.1 | 'openid4vci-proof+jwt'; diff --git a/packages/common/lib/types/Generic.types.ts b/packages/common/lib/types/Generic.types.ts index a1912208..21a170f9 100644 --- a/packages/common/lib/types/Generic.types.ts +++ b/packages/common/lib/types/Generic.types.ts @@ -17,7 +17,7 @@ import { export type InputCharSet = 'numeric' | 'text'; export type KeyProofType = 'jwt' | 'cwt' | 'ldp_vp'; -export type PoPMode = 'pop' | 'jwt'; // Proof of posession, or regular JWT +export type PoPMode = 'pop' | 'JWT'; // Proof of posession, or regular JWT /** * Important Note: please be aware that these Common interfaces are based on versions v1_0.11 and v1_0.09 diff --git a/packages/issuer/lib/__tests__/VcIssuer.spec.ts b/packages/issuer/lib/__tests__/VcIssuer.spec.ts index f30c58a7..3cc271df 100644 --- a/packages/issuer/lib/__tests__/VcIssuer.spec.ts +++ b/packages/issuer/lib/__tests__/VcIssuer.spec.ts @@ -318,7 +318,7 @@ describe('VcIssuer', () => { credential_identifier: 'VerifiableCredential', format: 'jwt_vc_json', proof: { - proof_type: 'jwt', + proof_type: 'JWT', jwt: 'ye.ye.ye', }, }, @@ -377,7 +377,7 @@ describe('VcIssuer', () => { credential_identifier: 'VerifiableCredential', format: 'jwt_vc_json', proof: { - proof_type: 'jwt', + proof_type: 'JWT', jwt: 'ye.ye.ye', }, }, @@ -441,7 +441,7 @@ describe('VcIssuer', () => { credential_identifier: 'VerifiableCredential', format: 'jwt_vc_json', proof: { - proof_type: 'jwt', + proof_type: 'JWT', jwt: 'ye.ye.ye', }, }, @@ -580,7 +580,7 @@ describe('VcIssuer without did', () => { credential_identifier: 'VerifiableCredential', format: 'jwt_vc_json', proof: { - proof_type: 'jwt', + proof_type: 'JWT', jwt: 'ye.ye.ye', }, }, @@ -633,7 +633,7 @@ describe('VcIssuer without did', () => { credential_identifier: 'VerifiableCredential', format: 'jwt_vc_json', proof: { - proof_type: 'jwt', + proof_type: 'JWT', jwt: 'ye.ye.ye', }, }, @@ -691,7 +691,7 @@ describe('VcIssuer without did', () => { credential_identifier: 'VerifiableCredential', format: 'jwt_vc_json', proof: { - proof_type: 'jwt', + proof_type: 'JWT', jwt: 'ye.ye.ye', }, }, diff --git a/packages/issuer/lib/tokens/index.ts b/packages/issuer/lib/tokens/index.ts index a7f6f66d..9ec1befe 100644 --- a/packages/issuer/lib/tokens/index.ts +++ b/packages/issuer/lib/tokens/index.ts @@ -49,7 +49,7 @@ export const generateAccessToken = async ( const iat = new Date().getTime() / 1000 const exp = iat + tokenExpiresIn const jwt: Jwt = { - header: { typ: 'JWT', alg: alg ?? Alg.ES256K }, + header: { typ: 'JWT', alg: alg ?? Alg.ES256 }, payload: { iat, exp,