1
0
mirror of https://github.com/bitwarden/browser.git synced 2025-02-08 00:01:28 +01:00

[EC-598] feat: increment counter during assertion

This commit is contained in:
Andreas Coroiu 2023-03-29 16:55:09 +02:00
parent 597bc0b197
commit 5bf4156fc6
No known key found for this signature in database
GPG Key ID: E70B5FFC81DFEC1A
2 changed files with 70 additions and 5 deletions

View File

@ -588,7 +588,7 @@ describe("FidoAuthenticatorService", () => {
});
});
describe("assertion of non-discoverable credential", () => {
describe("vault contains credential", () => {
let credentialIds: string[];
let ciphers: CipherView[];
let params: Fido2AuthenticatorGetAssertionParams;
@ -612,10 +612,66 @@ describe("FidoAuthenticatorService", () => {
/** Spec: Prompt the user to select a public key credential source selectedCredential from credentialOptions. */
it("should request confirmation from the user", async () => {
userInterface.pickCredential.mockResolvedValue(ciphers[0].id);
await authenticator.getAssertion(params);
expect(userInterface.pickCredential).toHaveBeenCalledWith(ciphers.map((c) => c.id));
});
/** Spec: If the user does not consent, return an error code equivalent to "NotAllowedError" and terminate the operation. */
it("should throw error", async () => {
userInterface.pickCredential.mockResolvedValue(undefined);
const result = async () => await authenticator.getAssertion(params);
await expect(result).rejects.toThrowError(Fido2AutenticatorErrorCode.NotAllowed);
});
});
describe("assertion of non-discoverable credential", () => {
let credentialIds: string[];
let ciphers: CipherView[];
let params: Fido2AuthenticatorGetAssertionParams;
beforeEach(async () => {
credentialIds = [Utils.newGuid(), Utils.newGuid()];
ciphers = await Promise.all(
credentialIds.map((id) =>
createCipherView(
{ type: CipherType.Login },
{ nonDiscoverableId: id, rpId: RpId, counter: 9000 }
)
)
);
params = await createParams({
allowCredentialDescriptorList: credentialIds.map((credentialId) => ({
id: Utils.guidToRawFormat(credentialId),
type: "public-key",
})),
rpId: RpId,
});
cipherService.getAllDecrypted.mockResolvedValue(ciphers);
userInterface.pickCredential.mockResolvedValue(ciphers[0].id);
});
/** Spec: Increment the credential associated signature counter */
it("should increment counter", async () => {
const encrypted = Symbol();
cipherService.encrypt.mockResolvedValue(encrypted as any);
await authenticator.getAssertion(params);
expect(cipherService.encrypt).toHaveBeenCalledWith(
expect.objectContaining({
id: ciphers[0].id,
fido2Key: expect.objectContaining({
counter: 9001,
}),
})
);
expect(cipherService.updateWithServer).toHaveBeenCalledWith(encrypted);
});
});
async function createParams(
@ -651,10 +707,12 @@ function createCipherView(
const cipher = new CipherView();
cipher.id = data.id ?? Utils.newGuid();
cipher.type = data.type ?? CipherType.Fido2Key;
cipher.localData = {};
cipher.login = data.type ?? data.type === CipherType.Login ? new LoginView() : null;
cipher.fido2Key = new Fido2KeyView();
cipher.fido2Key.nonDiscoverableId = fido2Key.nonDiscoverableId;
cipher.fido2Key.rpId = fido2Key.rpId;
cipher.fido2Key.rpId = fido2Key.rpId ?? RpId;
cipher.fido2Key.counter = fido2Key.counter ?? 0;
return cipher;
}

View File

@ -162,12 +162,19 @@ export class Fido2AuthenticatorService implements Fido2AuthenticatorServiceAbstr
throw new Fido2AutenticatorError(Fido2AutenticatorErrorCode.NotAllowed);
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const selectedCredential = await this.userInterface.pickCredential(
const selectedCredentialId = await this.userInterface.pickCredential(
credentialOptions.map((cipher) => cipher.id)
);
const selectedCredential = credentialOptions.find((c) => c.id === selectedCredentialId);
return null;
if (selectedCredential === undefined) {
throw new Fido2AutenticatorError(Fido2AutenticatorErrorCode.NotAllowed);
}
++selectedCredential.fido2Key.counter;
selectedCredential.localData.lastUsedDate = new Date().getTime();
const encrypted = await this.cipherService.encrypt(selectedCredential);
await this.cipherService.updateWithServer(encrypted);
}
private async vaultContainsCredentials(