1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-17 00:33:44 +00:00

[EC-598] feat: allow discoverable credentials to be used for non-discoverable assertions

This commit is contained in:
Andreas Coroiu
2023-04-18 10:09:01 +02:00
parent 0493565658
commit 53f35d59fb
2 changed files with 25 additions and 16 deletions

View File

@@ -655,11 +655,16 @@ describe("FidoAuthenticatorService", () => {
beforeEach(async () => { beforeEach(async () => {
credentialIds = [Utils.newGuid(), Utils.newGuid()]; credentialIds = [Utils.newGuid(), Utils.newGuid()];
ciphers = await Promise.all( ciphers = [
credentialIds.map((id) => await createCipherView(
createCipherView({ type: CipherType.Login }, { nonDiscoverableId: id, rpId: RpId }) { type: CipherType.Login },
) { nonDiscoverableId: credentialIds[0], rpId: RpId }
); ),
await createCipherView(
{ type: CipherType.Fido2Key, id: credentialIds[1] },
{ rpId: RpId }
),
];
params = await createParams({ params = await createParams({
allowCredentialDescriptorList: credentialIds.map((credentialId) => ({ allowCredentialDescriptorList: credentialIds.map((credentialId) => ({
id: Utils.guidToRawFormat(credentialId), id: Utils.guidToRawFormat(credentialId),

View File

@@ -66,7 +66,7 @@ export class Fido2AuthenticatorService implements Fido2AuthenticatorServiceAbstr
throw new Fido2AutenticatorError(Fido2AutenticatorErrorCode.Constraint); throw new Fido2AutenticatorError(Fido2AutenticatorErrorCode.Constraint);
} }
const existingCipherIds = await this.findExistingCredentials( const existingCipherIds = await this.findExcludedCredentials(
params.excludeCredentialDescriptorList params.excludeCredentialDescriptorList
); );
if (existingCipherIds.length > 0) { if (existingCipherIds.length > 0) {
@@ -182,12 +182,12 @@ export class Fido2AuthenticatorService implements Fido2AuthenticatorServiceAbstr
// eslint-disable-next-line no-empty // eslint-disable-next-line no-empty
if (params.allowCredentialDescriptorList?.length > 0) { if (params.allowCredentialDescriptorList?.length > 0) {
cipherOptions = await this.findNonDiscoverableCredentials( cipherOptions = await this.findCredentialsById(
params.allowCredentialDescriptorList, params.allowCredentialDescriptorList,
params.rpId params.rpId
); );
} else { } else {
cipherOptions = await this.findDiscoverableCredentials(params.rpId); cipherOptions = await this.findCredentialsByRp(params.rpId);
} }
if (cipherOptions.length === 0) { if (cipherOptions.length === 0) {
@@ -254,7 +254,7 @@ export class Fido2AuthenticatorService implements Fido2AuthenticatorServiceAbstr
} }
/** Finds existing crendetials and returns the `cipherId` for each one */ /** Finds existing crendetials and returns the `cipherId` for each one */
private async findExistingCredentials( private async findExcludedCredentials(
credentials: PublicKeyCredentialDescriptor[] credentials: PublicKeyCredentialDescriptor[]
): Promise<string[]> { ): Promise<string[]> {
const ids: string[] = []; const ids: string[] = [];
@@ -274,6 +274,7 @@ export class Fido2AuthenticatorService implements Fido2AuthenticatorServiceAbstr
return ciphers return ciphers
.filter( .filter(
(cipher) => (cipher) =>
!cipher.isDeleted &&
cipher.organizationId == undefined && cipher.organizationId == undefined &&
((cipher.type === CipherType.Fido2Key && ids.includes(cipher.id)) || ((cipher.type === CipherType.Fido2Key && ids.includes(cipher.id)) ||
(cipher.type === CipherType.Login && (cipher.type === CipherType.Login &&
@@ -283,7 +284,7 @@ export class Fido2AuthenticatorService implements Fido2AuthenticatorServiceAbstr
.map((cipher) => cipher.id); .map((cipher) => cipher.id);
} }
private async findNonDiscoverableCredentials( private async findCredentialsById(
credentials: PublicKeyCredentialDescriptor[], credentials: PublicKeyCredentialDescriptor[],
rpId: string rpId: string
): Promise<CipherView[]> { ): Promise<CipherView[]> {
@@ -303,15 +304,18 @@ export class Fido2AuthenticatorService implements Fido2AuthenticatorServiceAbstr
const ciphers = await this.cipherService.getAllDecrypted(); const ciphers = await this.cipherService.getAllDecrypted();
return ciphers.filter( return ciphers.filter(
(cipher) => (cipher) =>
!cipher.isDeleted && (!cipher.isDeleted &&
cipher.type === CipherType.Login && cipher.type === CipherType.Login &&
cipher.login.fido2Key != undefined && cipher.login.fido2Key != undefined &&
cipher.login.fido2Key.rpId === rpId && cipher.login.fido2Key.rpId === rpId &&
ids.includes(cipher.login.fido2Key.nonDiscoverableId) ids.includes(cipher.login.fido2Key.nonDiscoverableId)) ||
(cipher.type === CipherType.Fido2Key &&
cipher.fido2Key.rpId === rpId &&
ids.includes(cipher.id))
); );
} }
private async findDiscoverableCredentials(rpId: string): Promise<CipherView[]> { private async findCredentialsByRp(rpId: string): Promise<CipherView[]> {
const ciphers = await this.cipherService.getAllDecrypted(); const ciphers = await this.cipherService.getAllDecrypted();
return ciphers.filter( return ciphers.filter(
(cipher) => (cipher) =>