From 7bbde647f41a0cede447ea83c7f698155adabebd Mon Sep 17 00:00:00 2001 From: Andreas Coroiu Date: Fri, 1 Mar 2024 14:58:55 +0100 Subject: [PATCH] [PM-5725] New passkeys should always return 0 as counter value (#8024) * [PM-5725] feat: do not increment counter if is zero * [PM-5725] feat: skip save to server when counter is 0 --- .../fido2/fido2-authenticator.service.spec.ts | 15 +++++++++++++-- .../services/fido2/fido2-authenticator.service.ts | 11 ++++++++--- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/libs/common/src/vault/services/fido2/fido2-authenticator.service.spec.ts b/libs/common/src/vault/services/fido2/fido2-authenticator.service.spec.ts index c5cf827561..a86dadab8f 100644 --- a/libs/common/src/vault/services/fido2/fido2-authenticator.service.spec.ts +++ b/libs/common/src/vault/services/fido2/fido2-authenticator.service.spec.ts @@ -656,14 +656,14 @@ describe("FidoAuthenticatorService", () => { beforeEach(init); /** Spec: Increment the credential associated signature counter */ - it("should increment counter", async () => { + it("should increment counter and save to server when stored counter is larger than zero", async () => { const encrypted = Symbol(); cipherService.encrypt.mockResolvedValue(encrypted as any); + ciphers[0].login.fido2Credentials[0].counter = 9000; await authenticator.getAssertion(params, tab); expect(cipherService.updateWithServer).toHaveBeenCalledWith(encrypted); - expect(cipherService.encrypt).toHaveBeenCalledWith( expect.objectContaining({ id: ciphers[0].id, @@ -678,6 +678,17 @@ describe("FidoAuthenticatorService", () => { ); }); + /** Spec: Authenticators that do not implement a signature counter leave the signCount in the authenticator data constant at zero. */ + it("should not save to server when stored counter is zero", async () => { + const encrypted = Symbol(); + cipherService.encrypt.mockResolvedValue(encrypted as any); + ciphers[0].login.fido2Credentials[0].counter = 0; + + await authenticator.getAssertion(params, tab); + + expect(cipherService.updateWithServer).not.toHaveBeenCalled(); + }); + it("should return an assertion result", async () => { const result = await authenticator.getAssertion(params, tab); diff --git a/libs/common/src/vault/services/fido2/fido2-authenticator.service.ts b/libs/common/src/vault/services/fido2/fido2-authenticator.service.ts index f3112eb350..e84f7add92 100644 --- a/libs/common/src/vault/services/fido2/fido2-authenticator.service.ts +++ b/libs/common/src/vault/services/fido2/fido2-authenticator.service.ts @@ -257,14 +257,19 @@ export class Fido2AuthenticatorService implements Fido2AuthenticatorServiceAbstr const selectedFido2Credential = selectedCipher.login.fido2Credentials[0]; const selectedCredentialId = selectedFido2Credential.credentialId; - ++selectedFido2Credential.counter; + if (selectedFido2Credential.counter > 0) { + ++selectedFido2Credential.counter; + } selectedCipher.localData = { ...selectedCipher.localData, lastUsedDate: new Date().getTime(), }; - const encrypted = await this.cipherService.encrypt(selectedCipher); - await this.cipherService.updateWithServer(encrypted); + + if (selectedFido2Credential.counter > 0) { + const encrypted = await this.cipherService.encrypt(selectedCipher); + await this.cipherService.updateWithServer(encrypted); + } const authenticatorData = await generateAuthData({ rpId: selectedFido2Credential.rpId,