diff --git a/libs/common/src/webauthn/abstractions/fido2-client.service.abstraction.ts b/libs/common/src/webauthn/abstractions/fido2-client.service.abstraction.ts index 06fcfadff5..3f5412eff0 100644 --- a/libs/common/src/webauthn/abstractions/fido2-client.service.abstraction.ts +++ b/libs/common/src/webauthn/abstractions/fido2-client.service.abstraction.ts @@ -33,10 +33,7 @@ export interface CreateCredentialParams { credProps?: boolean; uvm?: boolean; }; - pubKeyCredParams: { - alg: number; - // type: "public-key"; // not used - }[]; + pubKeyCredParams: PublicKeyCredentialParam[]; rp: { id?: string; name: string; @@ -74,6 +71,11 @@ export interface AssertCredentialResult { userHandle: string; } +export interface PublicKeyCredentialParam { + alg: number; + type: "public-key"; +} + export class Fido2Error extends Error { constructor(message: string, readonly fallbackRequested = false) { super(message); diff --git a/libs/common/src/webauthn/services/fido2-client.service.spec.ts b/libs/common/src/webauthn/services/fido2-client.service.spec.ts index 1fb615d1e1..9ddf89430d 100644 --- a/libs/common/src/webauthn/services/fido2-client.service.spec.ts +++ b/libs/common/src/webauthn/services/fido2-client.service.spec.ts @@ -82,6 +82,22 @@ describe("FidoAuthenticatorService", () => { await rejects.toMatchObject({ name: "SecurityError" }); await rejects.toBeInstanceOf(DOMException); }); + + // Spec: If credTypesAndPubKeyAlgs is empty, return a DOMException whose name is "NotSupportedError", and terminate this algorithm. + it("should throw error if no support key algorithms were found", async () => { + const params = createParams({ + pubKeyCredParams: [ + { alg: -9001, type: "public-key" }, + { alg: -7, type: "not-supported" as any }, + ], + }); + + const result = async () => await client.createCredential(params); + + const rejects = expect(result).rejects; + await rejects.toMatchObject({ name: "NotSupportedError" }); + await rejects.toBeInstanceOf(DOMException); + }); }); function createParams(params: Partial = {}): CreateCredentialParams { @@ -96,6 +112,7 @@ describe("FidoAuthenticatorService", () => { pubKeyCredParams: params.pubKeyCredParams ?? [ { alg: -7, + type: "public-key", }, ], rp: params.rp ?? { diff --git a/libs/common/src/webauthn/services/fido2-client.service.ts b/libs/common/src/webauthn/services/fido2-client.service.ts index 3e898bf422..ec06e2a00b 100644 --- a/libs/common/src/webauthn/services/fido2-client.service.ts +++ b/libs/common/src/webauthn/services/fido2-client.service.ts @@ -7,6 +7,7 @@ import { CreateCredentialParams, CreateCredentialResult, Fido2ClientService as Fido2ClientServiceAbstraction, + PublicKeyCredentialParam, } from "../abstractions/fido2-client.service.abstraction"; import { Fido2Utils } from "../abstractions/fido2-utils"; @@ -36,7 +37,21 @@ export class Fido2ClientService implements Fido2ClientServiceAbstraction { throw new DOMException("'rp.id' does not match origin effective domain", "SecurityError"); } - throw new Error("Not implemented"); + let credTypesAndPubKeyAlgs: PublicKeyCredentialParam[]; + if (params.pubKeyCredParams?.length > 0) { + credTypesAndPubKeyAlgs = params.pubKeyCredParams.filter( + (kp) => kp.alg === -7 && kp.type === "public-key" + ); + } else { + credTypesAndPubKeyAlgs = [ + { alg: -7, type: "public-key" }, + { alg: -257, type: "public-key" }, + ]; + } + + if (credTypesAndPubKeyAlgs.length === 0) { + throw new DOMException("No supported key algorithms were found", "NotSupportedError"); + } } assertCredential(