From a15070f093b65e07874a63a60085487ec6a399b1 Mon Sep 17 00:00:00 2001 From: Jonathan Prusik Date: Mon, 20 Oct 2025 12:03:42 -0400 Subject: [PATCH] add support for targeting rules for totp --- .../collect-autofill-content.service.ts | 4 +- .../src/autofill/services/autofill.service.ts | 44 +++++++++++++++---- libs/common/src/autofill/types/index.ts | 6 ++- 3 files changed, 42 insertions(+), 12 deletions(-) diff --git a/apps/browser/src/autofill/services/abstractions/collect-autofill-content.service.ts b/apps/browser/src/autofill/services/abstractions/collect-autofill-content.service.ts index ef6c6518a20..7824344fc07 100644 --- a/apps/browser/src/autofill/services/abstractions/collect-autofill-content.service.ts +++ b/apps/browser/src/autofill/services/abstractions/collect-autofill-content.service.ts @@ -1,4 +1,4 @@ -import { AutofillFieldQualifierType } from "@bitwarden/common/autofill/types"; +import { AutofillTargetingRuleTypes } from "@bitwarden/common/autofill/types"; import AutofillField from "../../models/autofill-field"; import AutofillForm from "../../models/autofill-form"; @@ -16,7 +16,7 @@ type UpdateAutofillDataAttributeParams = { dataTargetKey?: string; }; -type TargetedFields = { [type in AutofillFieldQualifierType | "totp"]?: Element }; +type TargetedFields = { [type in AutofillTargetingRuleTypes]?: Element }; interface CollectAutofillContentService { autofillFormElements: AutofillFormElements; diff --git a/apps/browser/src/autofill/services/autofill.service.ts b/apps/browser/src/autofill/services/autofill.service.ts index 0a6a942873f..6df1ba2f837 100644 --- a/apps/browser/src/autofill/services/autofill.service.ts +++ b/apps/browser/src/autofill/services/autofill.service.ts @@ -29,6 +29,7 @@ import { UserNotificationSettingsServiceAbstraction } from "@bitwarden/common/au import { AutofillFieldQualifierType, AutofillTargetingRules, + AutofillTargetingRuleTypes, InlineMenuVisibilitySetting, } from "@bitwarden/common/autofill/types"; import { normalizeExpiryYearFormat } from "@bitwarden/common/autofill/utils"; @@ -521,7 +522,7 @@ export default class AutofillService implements AutofillServiceInterface { const shouldAutoCopyTotp = await this.getShouldAutoCopyTotp(); totp = shouldAutoCopyTotp - ? (await firstValueFrom(this.totpService.getCode$(options.cipher.login.totp))).code + ? (await this.getTotpCode(options.cipher.login.totp))?.code || null : null; }), ); @@ -816,7 +817,10 @@ export default class AutofillService implements AutofillServiceInterface { case CipherType.Login: if (pageHasTargetingRules) { for (const fieldType of pageTargetedFields) { - const fieldTypeValue = this.findCipherPropertyValueFieldType(options.cipher, fieldType); + const fieldTypeValue = await this.findCipherPropertyValueFieldType( + options.cipher, + fieldType, + ); if (fieldTypeValue) { AutofillService.fillByTargetingRule(fillScript, fieldType, fieldTypeValue); @@ -1033,10 +1037,10 @@ export default class AutofillService implements AutofillServiceInterface { filledFields[t.opid] = t; - const totpResponse = await firstValueFrom(this.totpService.getCode$(login.totp)); - let totpValue = totpResponse.code; + const totpResponse = await this.getTotpCode(login.totp); + let totpValue = totpResponse?.code; - if (totpValue.length == totps.length) { + if (totpValue?.length == totps.length) { totpValue = totpValue.charAt(i); } AutofillService.fillByOpid(fillScript, t, totpValue); @@ -2459,10 +2463,30 @@ export default class AutofillService implements AutofillServiceInterface { return totpField; } - private findCipherPropertyValueFieldType( + /** + * Returns the derived totpService response given a key + * @private + * @param {CipherView["login"]["totp"]} totpKey + */ + private async getTotpCode(totpKey: CipherView["login"]["totp"]) { + if (!totpKey) { + return null; + } + + return (await firstValueFrom(this.totpService.getCode$(totpKey))) || null; + } + + /** + * Map cipher values to field targeting rules + * @private + * @param {CipherView} cipher + * @param {AutofillTargetingRuleTypes} fieldType + */ + private async findCipherPropertyValueFieldType( cipher: CipherView, - fieldType: AutofillFieldQualifierType | "totp", + fieldType: AutofillTargetingRuleTypes, ) { + let totp = null; let cipherPropertyValue = null; switch (fieldType) { @@ -2473,7 +2497,11 @@ export default class AutofillService implements AutofillServiceInterface { cipherPropertyValue = cipher.login?.password || null; break; case "totp": - cipherPropertyValue = cipher.login?.totp || null; + totp = await this.getTotpCode(cipher.login?.totp); + + if (totp?.code) { + cipherPropertyValue = totp.code; + } break; default: break; diff --git a/libs/common/src/autofill/types/index.ts b/libs/common/src/autofill/types/index.ts index 5affa75c190..481d7d43159 100644 --- a/libs/common/src/autofill/types/index.ts +++ b/libs/common/src/autofill/types/index.ts @@ -22,9 +22,11 @@ export type AutofillFieldQualifierType = (typeof AutofillFieldQualifier)[keyof typeof AutofillFieldQualifier]; export type AutofillTargetingRules = { - [type in AutofillFieldQualifierType]?: string; + [type in AutofillTargetingRuleTypes]?: string; }; +export type AutofillTargetingRuleTypes = keyof typeof AutofillFieldQualifier | "totp"; + export type AutofillTargetingRulesByDomain = { - [key: string]: AutofillTargetingRules + [key: string]: AutofillTargetingRules; };