From 1ba76dec1683a1ad04b606ae5c613d1905f971c0 Mon Sep 17 00:00:00 2001 From: Justin Baur Date: Tue, 9 Aug 2022 21:31:02 -0400 Subject: [PATCH] [PS-1107] User Verification Service Refactor (#3219) * UserVerificationService refactor * Remove temp change * move import order * Address PR feedback --- .../browser/src/background/main.background.ts | 11 ++++-- .../src/popup/services/services.module.ts | 2 +- .../src/popup/settings/export.component.ts | 2 +- apps/cli/src/bw.ts | 9 ++++- .../desktop/src/app/vault/export.component.ts | 2 +- .../app/accounts/update-password.component.ts | 2 +- .../billing-sync-api-key.component.ts | 2 +- .../settings/delete-organization.component.ts | 6 +-- .../import-export/org-export.component.ts | 4 +- .../enroll-master-password-reset.component.ts | 4 +- .../web/src/app/settings/api-key.component.ts | 2 +- .../deauthorize-sessions.component.ts | 4 +- .../src/app/settings/purge-vault.component.ts | 4 +- .../two-factor-authenticator.component.ts | 23 ++++++++++-- .../app/settings/two-factor-base.component.ts | 7 ++-- .../app/settings/two-factor-duo.component.ts | 7 ++-- .../settings/two-factor-email.component.ts | 9 +++-- .../settings/two-factor-verify.component.ts | 20 ++-------- .../settings/two-factor-webauthn.component.ts | 21 ++++++++--- .../settings/two-factor-yubikey.component.ts | 18 ++++++--- .../tools/import-export/export.component.ts | 2 +- .../src/components/export.component.ts | 4 +- .../components/update-password.component.ts | 4 +- .../components/user-verification.component.ts | 6 +-- .../src/services/jslib-services.module.ts | 17 +++++++-- libs/common/src/abstractions/api.service.ts | 3 -- ...serVerification-api.service.abstraction.ts | 6 +++ .../userVerification.service.abstraction.ts} | 4 +- .../src/services/account/account.service.ts | 4 +- libs/common/src/services/api.service.ts | 9 ----- .../userVerification-api.service.ts | 14 +++++++ .../userVerification.service.ts | 22 +++++------ libs/common/src/types/authResponse.ts | 12 ++++++ libs/common/src/types/twoFactorResponse.ts | 14 +++++++ .../src/services/electronStorage.service.ts | 37 ++++++++++++++++--- 35 files changed, 209 insertions(+), 108 deletions(-) create mode 100644 libs/common/src/abstractions/userVerification/userVerification-api.service.abstraction.ts rename libs/common/src/abstractions/{userVerification.service.ts => userVerification/userVerification.service.abstraction.ts} (67%) create mode 100644 libs/common/src/services/userVerification/userVerification-api.service.ts rename libs/common/src/services/{ => userVerification}/userVerification.service.ts (74%) create mode 100644 libs/common/src/types/authResponse.ts create mode 100644 libs/common/src/types/twoFactorResponse.ts diff --git a/apps/browser/src/background/main.background.ts b/apps/browser/src/background/main.background.ts index 101b2e564b..3b0f92e821 100644 --- a/apps/browser/src/background/main.background.ts +++ b/apps/browser/src/background/main.background.ts @@ -31,7 +31,8 @@ import { SystemService as SystemServiceAbstraction } from "@bitwarden/common/abs import { TokenService as TokenServiceAbstraction } from "@bitwarden/common/abstractions/token.service"; import { TotpService as TotpServiceAbstraction } from "@bitwarden/common/abstractions/totp.service"; import { TwoFactorService as TwoFactorServiceAbstraction } from "@bitwarden/common/abstractions/twoFactor.service"; -import { UserVerificationService as UserVerificationServiceAbstraction } from "@bitwarden/common/abstractions/userVerification.service"; +import { UserVerificationApiServiceAbstraction } from "@bitwarden/common/abstractions/userVerification/userVerification-api.service.abstraction"; +import { UserVerificationService as UserVerificationServiceAbstraction } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction"; import { UsernameGenerationService as UsernameGenerationServiceAbstraction } from "@bitwarden/common/abstractions/usernameGeneration.service"; import { VaultTimeoutService as VaultTimeoutServiceAbstraction } from "@bitwarden/common/abstractions/vaultTimeout.service"; import { AuthenticationStatus } from "@bitwarden/common/enums/authenticationStatus"; @@ -71,7 +72,8 @@ import { SystemService } from "@bitwarden/common/services/system.service"; import { TokenService } from "@bitwarden/common/services/token.service"; import { TotpService } from "@bitwarden/common/services/totp.service"; import { TwoFactorService } from "@bitwarden/common/services/twoFactor.service"; -import { UserVerificationService } from "@bitwarden/common/services/userVerification.service"; +import { UserVerificationApiService } from "@bitwarden/common/services/userVerification/userVerification-api.service"; +import { UserVerificationService } from "@bitwarden/common/services/userVerification/userVerification.service"; import { UsernameGenerationService } from "@bitwarden/common/services/usernameGeneration.service"; import { WebCryptoFunctionService } from "@bitwarden/common/services/webCryptoFunction.service"; @@ -152,6 +154,7 @@ export default class MainBackground { encryptService: EncryptService; folderApiService: FolderApiServiceAbstraction; policyApiService: PolicyApiServiceAbstraction; + userVerificationApiService: UserVerificationApiServiceAbstraction; // Passed to the popup for Safari to workaround issues with theming, downloading, etc. backgroundWindow = window; @@ -422,10 +425,12 @@ export default class MainBackground { ); this.popupUtilsService = new PopupUtilsService(isPrivateMode); + this.userVerificationApiService = new UserVerificationApiService(this.apiService); + this.userVerificationService = new UserVerificationService( this.cryptoService, this.i18nService, - this.apiService + this.userVerificationApiService ); const systemUtilsServiceReloadCallback = () => { diff --git a/apps/browser/src/popup/services/services.module.ts b/apps/browser/src/popup/services/services.module.ts index 7ed102b168..265c765cbb 100644 --- a/apps/browser/src/popup/services/services.module.ts +++ b/apps/browser/src/popup/services/services.module.ts @@ -45,7 +45,7 @@ import { SyncService } from "@bitwarden/common/abstractions/sync.service"; import { TokenService } from "@bitwarden/common/abstractions/token.service"; import { TotpService } from "@bitwarden/common/abstractions/totp.service"; import { TwoFactorService } from "@bitwarden/common/abstractions/twoFactor.service"; -import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification.service"; +import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction"; import { UsernameGenerationService } from "@bitwarden/common/abstractions/usernameGeneration.service"; import { VaultTimeoutService } from "@bitwarden/common/abstractions/vaultTimeout.service"; import { AuthService } from "@bitwarden/common/services/auth.service"; diff --git a/apps/browser/src/popup/settings/export.component.ts b/apps/browser/src/popup/settings/export.component.ts index 8dc123566d..47301b5fde 100644 --- a/apps/browser/src/popup/settings/export.component.ts +++ b/apps/browser/src/popup/settings/export.component.ts @@ -11,7 +11,7 @@ import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/abstractions/log.service"; import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service"; import { PolicyService } from "@bitwarden/common/abstractions/policy/policy.service.abstraction"; -import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification.service"; +import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction"; @Component({ selector: "app-export", diff --git a/apps/cli/src/bw.ts b/apps/cli/src/bw.ts index 6739eb5d97..0bdc1e0047 100644 --- a/apps/cli/src/bw.ts +++ b/apps/cli/src/bw.ts @@ -42,7 +42,8 @@ import { SyncService } from "@bitwarden/common/services/sync.service"; import { TokenService } from "@bitwarden/common/services/token.service"; import { TotpService } from "@bitwarden/common/services/totp.service"; import { TwoFactorService } from "@bitwarden/common/services/twoFactor.service"; -import { UserVerificationService } from "@bitwarden/common/services/userVerification.service"; +import { UserVerificationApiService } from "@bitwarden/common/services/userVerification/userVerification-api.service"; +import { UserVerificationService } from "@bitwarden/common/services/userVerification/userVerification.service"; import { VaultTimeoutService } from "@bitwarden/common/services/vaultTimeout.service"; import { CliPlatformUtilsService } from "@bitwarden/node/cli/services/cliPlatformUtils.service"; import { ConsoleLogService } from "@bitwarden/node/cli/services/consoleLog.service"; @@ -106,6 +107,7 @@ export class Main { twoFactorService: TwoFactorService; broadcasterService: BroadcasterService; folderApiService: FolderApiService; + userVerificationApiService: UserVerificationApiService; constructor() { let p = null; @@ -330,10 +332,13 @@ export class Main { this.program = new Program(this); this.vaultProgram = new VaultProgram(this); this.sendProgram = new SendProgram(this); + + this.userVerificationApiService = new UserVerificationApiService(this.apiService); + this.userVerificationService = new UserVerificationService( this.cryptoService, this.i18nService, - this.apiService + this.userVerificationApiService ); } diff --git a/apps/desktop/src/app/vault/export.component.ts b/apps/desktop/src/app/vault/export.component.ts index e21d8e9467..4793a70b75 100644 --- a/apps/desktop/src/app/vault/export.component.ts +++ b/apps/desktop/src/app/vault/export.component.ts @@ -13,7 +13,7 @@ import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/abstractions/log.service"; import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service"; import { PolicyService } from "@bitwarden/common/abstractions/policy/policy.service.abstraction"; -import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification.service"; +import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction"; const BroadcasterSubscriptionId = "ExportComponent"; diff --git a/apps/web/src/app/accounts/update-password.component.ts b/apps/web/src/app/accounts/update-password.component.ts index 0d5da3ca3f..dfa5d82c0d 100644 --- a/apps/web/src/app/accounts/update-password.component.ts +++ b/apps/web/src/app/accounts/update-password.component.ts @@ -11,7 +11,7 @@ import { PasswordGenerationService } from "@bitwarden/common/abstractions/passwo import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service"; import { PolicyService } from "@bitwarden/common/abstractions/policy/policy.service.abstraction"; import { StateService } from "@bitwarden/common/abstractions/state.service"; -import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification.service"; +import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction"; @Component({ selector: "app-update-password", diff --git a/apps/web/src/app/organizations/settings/billing-sync-api-key.component.ts b/apps/web/src/app/organizations/settings/billing-sync-api-key.component.ts index dfe87ebbf7..5b36a69e17 100644 --- a/apps/web/src/app/organizations/settings/billing-sync-api-key.component.ts +++ b/apps/web/src/app/organizations/settings/billing-sync-api-key.component.ts @@ -3,7 +3,7 @@ import { Component } from "@angular/core"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service"; -import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification.service"; +import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction"; import { OrganizationApiKeyType } from "@bitwarden/common/enums/organizationApiKeyType"; import { OrganizationApiKeyRequest } from "@bitwarden/common/models/request/organizationApiKeyRequest"; import { ApiKeyResponse } from "@bitwarden/common/models/response/apiKeyResponse"; diff --git a/apps/web/src/app/organizations/settings/delete-organization.component.ts b/apps/web/src/app/organizations/settings/delete-organization.component.ts index a008dab06a..19b82ebcaa 100644 --- a/apps/web/src/app/organizations/settings/delete-organization.component.ts +++ b/apps/web/src/app/organizations/settings/delete-organization.component.ts @@ -6,7 +6,7 @@ import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/abstractions/log.service"; import { OrganizationService } from "@bitwarden/common/abstractions/organization.service"; import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service"; -import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification.service"; +import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction"; import { CipherType } from "@bitwarden/common/enums/cipherType"; import { Utils } from "@bitwarden/common/misc/utils"; import { CipherView } from "@bitwarden/common/models/view/cipherView"; @@ -53,10 +53,10 @@ export class DeleteOrganizationComponent implements OnInit { deleteOrganizationRequestType: "InvalidFamiliesForEnterprise" | "RegularDelete" = "RegularDelete"; organizationName: string; organizationContentSummary: OrganizationContentSummary = new OrganizationContentSummary(); - @Output() onSuccess: EventEmitter = new EventEmitter(); + @Output() onSuccess: EventEmitter = new EventEmitter(); masterPassword: Verification; - formPromise: Promise; + formPromise: Promise; constructor( private apiService: ApiService, diff --git a/apps/web/src/app/organizations/tools/import-export/org-export.component.ts b/apps/web/src/app/organizations/tools/import-export/org-export.component.ts index 277446a36a..79f9254231 100644 --- a/apps/web/src/app/organizations/tools/import-export/org-export.component.ts +++ b/apps/web/src/app/organizations/tools/import-export/org-export.component.ts @@ -10,7 +10,7 @@ import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/abstractions/log.service"; import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service"; import { PolicyService } from "@bitwarden/common/abstractions/policy/policy.service.abstraction"; -import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification.service"; +import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction"; import { EventType } from "@bitwarden/common/enums/eventType"; import { ExportComponent } from "../../../tools/import-export/export.component"; @@ -66,7 +66,7 @@ export class OrganizationExportComponent extends ExportComponent { return super.getFileName("org"); } - async collectEvent(): Promise { + async collectEvent(): Promise { await this.eventService.collect( EventType.Organization_ClientExportedVault, null, diff --git a/apps/web/src/app/organizations/users/enroll-master-password-reset.component.ts b/apps/web/src/app/organizations/users/enroll-master-password-reset.component.ts index 9252c92feb..2a8e5f2188 100644 --- a/apps/web/src/app/organizations/users/enroll-master-password-reset.component.ts +++ b/apps/web/src/app/organizations/users/enroll-master-password-reset.component.ts @@ -8,7 +8,7 @@ import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/abstractions/log.service"; import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service"; import { SyncService } from "@bitwarden/common/abstractions/sync.service"; -import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification.service"; +import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction"; import { Utils } from "@bitwarden/common/misc/utils"; import { Organization } from "@bitwarden/common/models/domain/organization"; import { OrganizationUserResetPasswordEnrollmentRequest } from "@bitwarden/common/models/request/organizationUserResetPasswordEnrollmentRequest"; @@ -22,7 +22,7 @@ export class EnrollMasterPasswordReset { organization: Organization; verification: Verification; - formPromise: Promise; + formPromise: Promise; constructor( private userVerificationService: UserVerificationService, diff --git a/apps/web/src/app/settings/api-key.component.ts b/apps/web/src/app/settings/api-key.component.ts index 25238c2989..c0e976ea08 100644 --- a/apps/web/src/app/settings/api-key.component.ts +++ b/apps/web/src/app/settings/api-key.component.ts @@ -1,7 +1,7 @@ import { Component } from "@angular/core"; import { LogService } from "@bitwarden/common/abstractions/log.service"; -import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification.service"; +import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction"; import { SecretVerificationRequest } from "@bitwarden/common/models/request/secretVerificationRequest"; import { ApiKeyResponse } from "@bitwarden/common/models/response/apiKeyResponse"; import { Verification } from "@bitwarden/common/types/verification"; diff --git a/apps/web/src/app/settings/deauthorize-sessions.component.ts b/apps/web/src/app/settings/deauthorize-sessions.component.ts index c617b4750b..05a93233b6 100644 --- a/apps/web/src/app/settings/deauthorize-sessions.component.ts +++ b/apps/web/src/app/settings/deauthorize-sessions.component.ts @@ -5,7 +5,7 @@ import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/abstractions/log.service"; import { MessagingService } from "@bitwarden/common/abstractions/messaging.service"; import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service"; -import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification.service"; +import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction"; import { Verification } from "@bitwarden/common/types/verification"; @Component({ @@ -14,7 +14,7 @@ import { Verification } from "@bitwarden/common/types/verification"; }) export class DeauthorizeSessionsComponent { masterPassword: Verification; - formPromise: Promise; + formPromise: Promise; constructor( private apiService: ApiService, diff --git a/apps/web/src/app/settings/purge-vault.component.ts b/apps/web/src/app/settings/purge-vault.component.ts index b2ee3ee8c3..e10782914f 100644 --- a/apps/web/src/app/settings/purge-vault.component.ts +++ b/apps/web/src/app/settings/purge-vault.component.ts @@ -5,7 +5,7 @@ import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/abstractions/log.service"; import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service"; -import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification.service"; +import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction"; import { Verification } from "@bitwarden/common/types/verification"; @Component({ @@ -16,7 +16,7 @@ export class PurgeVaultComponent { @Input() organizationId?: string = null; masterPassword: Verification; - formPromise: Promise; + formPromise: Promise; constructor( private apiService: ApiService, diff --git a/apps/web/src/app/settings/two-factor-authenticator.component.ts b/apps/web/src/app/settings/two-factor-authenticator.component.ts index 9a1269d5f8..569a95621f 100644 --- a/apps/web/src/app/settings/two-factor-authenticator.component.ts +++ b/apps/web/src/app/settings/two-factor-authenticator.component.ts @@ -5,13 +5,28 @@ import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/abstractions/log.service"; import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service"; import { StateService } from "@bitwarden/common/abstractions/state.service"; -import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification.service"; +import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction"; import { TwoFactorProviderType } from "@bitwarden/common/enums/twoFactorProviderType"; import { UpdateTwoFactorAuthenticatorRequest } from "@bitwarden/common/models/request/updateTwoFactorAuthenticatorRequest"; import { TwoFactorAuthenticatorResponse } from "@bitwarden/common/models/response/twoFactorAuthenticatorResponse"; +import { AuthResponse } from "@bitwarden/common/types/authResponse"; import { TwoFactorBaseComponent } from "./two-factor-base.component"; +// NOTE: There are additional options available but these are just the ones we are current using. +// See: https://github.com/neocotic/qrious#examples +interface QRiousOptions { + element: HTMLElement; + value: string; + size: number; +} + +declare global { + interface Window { + QRious: new (options: QRiousOptions) => unknown; + } +} + @Component({ selector: "app-two-factor-authenticator", templateUrl: "two-factor-authenticator.component.html", @@ -23,7 +38,7 @@ export class TwoFactorAuthenticatorComponent type = TwoFactorProviderType.Authenticator; key: string; token: string; - formPromise: Promise; + formPromise: Promise; private qrScript: HTMLScriptElement; @@ -49,7 +64,7 @@ export class TwoFactorAuthenticatorComponent window.document.body.removeChild(this.qrScript); } - auth(authResponse: any) { + auth(authResponse: AuthResponse) { super.auth(authResponse); return this.processResponse(authResponse.response); } @@ -80,7 +95,7 @@ export class TwoFactorAuthenticatorComponent this.key = response.key; const email = await this.stateService.getEmail(); window.setTimeout(() => { - new (window as any).QRious({ + new window.QRious({ element: document.getElementById("qr"), value: "otpauth://totp/Bitwarden:" + diff --git a/apps/web/src/app/settings/two-factor-base.component.ts b/apps/web/src/app/settings/two-factor-base.component.ts index d38a59ed49..d54092aebd 100644 --- a/apps/web/src/app/settings/two-factor-base.component.ts +++ b/apps/web/src/app/settings/two-factor-base.component.ts @@ -4,11 +4,12 @@ import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/abstractions/log.service"; import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service"; -import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification.service"; +import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction"; import { TwoFactorProviderType } from "@bitwarden/common/enums/twoFactorProviderType"; import { VerificationType } from "@bitwarden/common/enums/verificationType"; import { SecretVerificationRequest } from "@bitwarden/common/models/request/secretVerificationRequest"; import { TwoFactorProviderRequest } from "@bitwarden/common/models/request/twoFactorProviderRequest"; +import { AuthResponseBase } from "@bitwarden/common/types/authResponse"; @Directive() export abstract class TwoFactorBaseComponent { @@ -31,7 +32,7 @@ export abstract class TwoFactorBaseComponent { protected userVerificationService: UserVerificationService ) {} - protected auth(authResponse: any) { + protected auth(authResponse: AuthResponseBase) { this.hashedSecret = authResponse.secret; this.verificationType = authResponse.verificationType; this.authed = true; @@ -46,7 +47,7 @@ export abstract class TwoFactorBaseComponent { } } - protected async disable(promise: Promise) { + protected async disable(promise: Promise) { const confirmed = await this.platformUtilsService.showDialog( this.i18nService.t("twoStepDisableDesc"), this.i18nService.t("disable"), diff --git a/apps/web/src/app/settings/two-factor-duo.component.ts b/apps/web/src/app/settings/two-factor-duo.component.ts index e2cb8f62d6..46c62b1bc5 100644 --- a/apps/web/src/app/settings/two-factor-duo.component.ts +++ b/apps/web/src/app/settings/two-factor-duo.component.ts @@ -4,10 +4,11 @@ import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/abstractions/log.service"; import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service"; -import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification.service"; +import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction"; import { TwoFactorProviderType } from "@bitwarden/common/enums/twoFactorProviderType"; import { UpdateTwoFactorDuoRequest } from "@bitwarden/common/models/request/updateTwoFactorDuoRequest"; import { TwoFactorDuoResponse } from "@bitwarden/common/models/response/twoFactorDuoResponse"; +import { AuthResponse } from "@bitwarden/common/types/authResponse"; import { TwoFactorBaseComponent } from "./two-factor-base.component"; @@ -20,7 +21,7 @@ export class TwoFactorDuoComponent extends TwoFactorBaseComponent { ikey: string; skey: string; host: string; - formPromise: Promise; + formPromise: Promise; constructor( apiService: ApiService, @@ -32,7 +33,7 @@ export class TwoFactorDuoComponent extends TwoFactorBaseComponent { super(apiService, i18nService, platformUtilsService, logService, userVerificationService); } - auth(authResponse: any) { + auth(authResponse: AuthResponse) { super.auth(authResponse); this.processResponse(authResponse.response); } diff --git a/apps/web/src/app/settings/two-factor-email.component.ts b/apps/web/src/app/settings/two-factor-email.component.ts index 4bf376ef6a..968695812b 100644 --- a/apps/web/src/app/settings/two-factor-email.component.ts +++ b/apps/web/src/app/settings/two-factor-email.component.ts @@ -5,11 +5,12 @@ import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/abstractions/log.service"; import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service"; import { StateService } from "@bitwarden/common/abstractions/state.service"; -import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification.service"; +import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction"; import { TwoFactorProviderType } from "@bitwarden/common/enums/twoFactorProviderType"; import { TwoFactorEmailRequest } from "@bitwarden/common/models/request/twoFactorEmailRequest"; import { UpdateTwoFactorEmailRequest } from "@bitwarden/common/models/request/updateTwoFactorEmailRequest"; import { TwoFactorEmailResponse } from "@bitwarden/common/models/response/twoFactorEmailResponse"; +import { AuthResponse } from "@bitwarden/common/types/authResponse"; import { TwoFactorBaseComponent } from "./two-factor-base.component"; @@ -22,8 +23,8 @@ export class TwoFactorEmailComponent extends TwoFactorBaseComponent { email: string; token: string; sentEmail: string; - formPromise: Promise; - emailPromise: Promise; + formPromise: Promise; + emailPromise: Promise; constructor( apiService: ApiService, @@ -36,7 +37,7 @@ export class TwoFactorEmailComponent extends TwoFactorBaseComponent { super(apiService, i18nService, platformUtilsService, logService, userVerificationService); } - auth(authResponse: any) { + auth(authResponse: AuthResponse) { super.auth(authResponse); return this.processResponse(authResponse.response); } diff --git a/apps/web/src/app/settings/two-factor-verify.component.ts b/apps/web/src/app/settings/two-factor-verify.component.ts index f9492edc6d..5e8b91fd77 100644 --- a/apps/web/src/app/settings/two-factor-verify.component.ts +++ b/apps/web/src/app/settings/two-factor-verify.component.ts @@ -2,26 +2,14 @@ import { Component, EventEmitter, Input, Output } from "@angular/core"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { LogService } from "@bitwarden/common/abstractions/log.service"; -import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification.service"; +import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction"; import { TwoFactorProviderType } from "@bitwarden/common/enums/twoFactorProviderType"; import { VerificationType } from "@bitwarden/common/enums/verificationType"; import { SecretVerificationRequest } from "@bitwarden/common/models/request/secretVerificationRequest"; -import { TwoFactorAuthenticatorResponse } from "@bitwarden/common/models/response/twoFactorAuthenticatorResponse"; -import { TwoFactorDuoResponse } from "@bitwarden/common/models/response/twoFactorDuoResponse"; -import { TwoFactorEmailResponse } from "@bitwarden/common/models/response/twoFactorEmailResponse"; -import { TwoFactorRecoverResponse } from "@bitwarden/common/models/response/twoFactorRescoverResponse"; -import { TwoFactorWebAuthnResponse } from "@bitwarden/common/models/response/twoFactorWebAuthnResponse"; -import { TwoFactorYubiKeyResponse } from "@bitwarden/common/models/response/twoFactorYubiKeyResponse"; +import { AuthResponse } from "@bitwarden/common/types/authResponse"; +import { TwoFactorResponse } from "@bitwarden/common/types/twoFactorResponse"; import { Verification } from "@bitwarden/common/types/verification"; -type TwoFactorResponse = - | TwoFactorRecoverResponse - | TwoFactorDuoResponse - | TwoFactorEmailResponse - | TwoFactorWebAuthnResponse - | TwoFactorAuthenticatorResponse - | TwoFactorYubiKeyResponse; - @Component({ selector: "app-two-factor-verify", templateUrl: "two-factor-verify.component.html", @@ -29,7 +17,7 @@ type TwoFactorResponse = export class TwoFactorVerifyComponent { @Input() type: TwoFactorProviderType; @Input() organizationId: string; - @Output() onAuthed = new EventEmitter(); + @Output() onAuthed = new EventEmitter>(); secret: Verification; formPromise: Promise; diff --git a/apps/web/src/app/settings/two-factor-webauthn.component.ts b/apps/web/src/app/settings/two-factor-webauthn.component.ts index f3c946c0ce..4180b95754 100644 --- a/apps/web/src/app/settings/two-factor-webauthn.component.ts +++ b/apps/web/src/app/settings/two-factor-webauthn.component.ts @@ -4,7 +4,7 @@ import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/abstractions/log.service"; import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service"; -import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification.service"; +import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction"; import { TwoFactorProviderType } from "@bitwarden/common/enums/twoFactorProviderType"; import { SecretVerificationRequest } from "@bitwarden/common/models/request/secretVerificationRequest"; import { UpdateTwoFactorWebAuthnDeleteRequest } from "@bitwarden/common/models/request/updateTwoFactorWebAuthnDeleteRequest"; @@ -13,9 +13,18 @@ import { ChallengeResponse, TwoFactorWebAuthnResponse, } from "@bitwarden/common/models/response/twoFactorWebAuthnResponse"; +import { AuthResponse } from "@bitwarden/common/types/authResponse"; import { TwoFactorBaseComponent } from "./two-factor-base.component"; +interface Key { + id: number; + name: string; + configured: boolean; + migrated?: boolean; + removePromise: Promise | null; +} + @Component({ selector: "app-two-factor-webauthn", templateUrl: "two-factor-webauthn.component.html", @@ -23,14 +32,14 @@ import { TwoFactorBaseComponent } from "./two-factor-base.component"; export class TwoFactorWebAuthnComponent extends TwoFactorBaseComponent { type = TwoFactorProviderType.WebAuthn; name: string; - keys: any[]; + keys: Key[]; keyIdAvailable: number = null; keysConfiguredCount = 0; webAuthnError: boolean; webAuthnListening: boolean; webAuthnResponse: PublicKeyCredential; challengePromise: Promise; - formPromise: Promise; + formPromise: Promise; constructor( apiService: ApiService, @@ -43,7 +52,7 @@ export class TwoFactorWebAuthnComponent extends TwoFactorBaseComponent { super(apiService, i18nService, platformUtilsService, logService, userVerificationService); } - auth(authResponse: any) { + auth(authResponse: AuthResponse) { super.auth(authResponse); this.processResponse(authResponse.response); } @@ -69,11 +78,11 @@ export class TwoFactorWebAuthnComponent extends TwoFactorBaseComponent { return super.disable(this.formPromise); } - async remove(key: any) { + async remove(key: Key) { if (this.keysConfiguredCount <= 1 || key.removePromise != null) { return; } - const name = key.name != null ? key.name : this.i18nService.t("webAuthnkeyX", key.id); + const name = key.name != null ? key.name : this.i18nService.t("webAuthnkeyX", key.id as any); const confirmed = await this.platformUtilsService.showDialog( this.i18nService.t("removeU2fConfirmation"), name, diff --git a/apps/web/src/app/settings/two-factor-yubikey.component.ts b/apps/web/src/app/settings/two-factor-yubikey.component.ts index 23dba61e5e..a6f75af1f8 100644 --- a/apps/web/src/app/settings/two-factor-yubikey.component.ts +++ b/apps/web/src/app/settings/two-factor-yubikey.component.ts @@ -4,24 +4,30 @@ import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/abstractions/log.service"; import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service"; -import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification.service"; +import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction"; import { TwoFactorProviderType } from "@bitwarden/common/enums/twoFactorProviderType"; import { UpdateTwoFactorYubioOtpRequest } from "@bitwarden/common/models/request/updateTwoFactorYubioOtpRequest"; import { TwoFactorYubiKeyResponse } from "@bitwarden/common/models/response/twoFactorYubiKeyResponse"; +import { AuthResponse } from "@bitwarden/common/types/authResponse"; import { TwoFactorBaseComponent } from "./two-factor-base.component"; +interface Key { + key: string; + existingKey: string; +} + @Component({ selector: "app-two-factor-yubikey", templateUrl: "two-factor-yubikey.component.html", }) export class TwoFactorYubiKeyComponent extends TwoFactorBaseComponent { type = TwoFactorProviderType.Yubikey; - keys: any[]; + keys: Key[]; nfc = false; - formPromise: Promise; - disablePromise: Promise; + formPromise: Promise; + disablePromise: Promise; constructor( apiService: ApiService, @@ -33,7 +39,7 @@ export class TwoFactorYubiKeyComponent extends TwoFactorBaseComponent { super(apiService, i18nService, platformUtilsService, logService, userVerificationService); } - auth(authResponse: any) { + auth(authResponse: AuthResponse) { super.auth(authResponse); this.processResponse(authResponse.response); } @@ -59,7 +65,7 @@ export class TwoFactorYubiKeyComponent extends TwoFactorBaseComponent { return super.disable(this.disablePromise); } - remove(key: any) { + remove(key: Key) { key.existingKey = null; key.key = null; } diff --git a/apps/web/src/app/tools/import-export/export.component.ts b/apps/web/src/app/tools/import-export/export.component.ts index 100f63015e..b9d8d963b6 100644 --- a/apps/web/src/app/tools/import-export/export.component.ts +++ b/apps/web/src/app/tools/import-export/export.component.ts @@ -10,7 +10,7 @@ import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/abstractions/log.service"; import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service"; import { PolicyService } from "@bitwarden/common/abstractions/policy/policy.service.abstraction"; -import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification.service"; +import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction"; @Component({ selector: "app-export", diff --git a/libs/angular/src/components/export.component.ts b/libs/angular/src/components/export.component.ts index c2a6187f44..d053b886d3 100644 --- a/libs/angular/src/components/export.component.ts +++ b/libs/angular/src/components/export.component.ts @@ -9,7 +9,7 @@ import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/abstractions/log.service"; import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service"; import { PolicyService } from "@bitwarden/common/abstractions/policy/policy.service.abstraction"; -import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification.service"; +import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction"; import { EventType } from "@bitwarden/common/enums/eventType"; import { PolicyType } from "@bitwarden/common/enums/policyType"; @@ -142,7 +142,7 @@ export class ExportComponent implements OnInit { return this.exportService.getFileName(prefix, extension); } - protected async collectEvent(): Promise { + protected async collectEvent(): Promise { await this.eventService.collect(EventType.User_ClientExportedVault); } diff --git a/libs/angular/src/components/update-password.component.ts b/libs/angular/src/components/update-password.component.ts index bc6bbba9a7..c2f076e107 100644 --- a/libs/angular/src/components/update-password.component.ts +++ b/libs/angular/src/components/update-password.component.ts @@ -10,7 +10,7 @@ import { PasswordGenerationService } from "@bitwarden/common/abstractions/passwo import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service"; import { PolicyService } from "@bitwarden/common/abstractions/policy/policy.service.abstraction"; import { StateService } from "@bitwarden/common/abstractions/state.service"; -import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification.service"; +import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction"; import { VerificationType } from "@bitwarden/common/enums/verificationType"; import { EncString } from "@bitwarden/common/models/domain/encString"; import { MasterPasswordPolicyOptions } from "@bitwarden/common/models/domain/masterPasswordPolicyOptions"; @@ -28,7 +28,7 @@ export class UpdatePasswordComponent extends BaseChangePasswordComponent { showPassword = false; currentMasterPassword: string; - onSuccessfulChangePassword: () => Promise; + onSuccessfulChangePassword: () => Promise; constructor( protected router: Router, diff --git a/libs/angular/src/components/user-verification.component.ts b/libs/angular/src/components/user-verification.component.ts index 2a486db01a..04af868b34 100644 --- a/libs/angular/src/components/user-verification.component.ts +++ b/libs/angular/src/components/user-verification.component.ts @@ -1,9 +1,9 @@ import { animate, style, transition, trigger } from "@angular/animations"; import { Component, OnInit } from "@angular/core"; -import { ControlValueAccessor, UntypedFormControl, NG_VALUE_ACCESSOR } from "@angular/forms"; +import { ControlValueAccessor, NG_VALUE_ACCESSOR, FormControl } from "@angular/forms"; import { KeyConnectorService } from "@bitwarden/common/abstractions/keyConnector.service"; -import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification.service"; +import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction"; import { VerificationType } from "@bitwarden/common/enums/verificationType"; import { Utils } from "@bitwarden/common/misc/utils"; import { Verification } from "@bitwarden/common/types/verification"; @@ -35,7 +35,7 @@ export class UserVerificationComponent implements ControlValueAccessor, OnInit { disableRequestOTP = false; sentCode = false; - secret = new UntypedFormControl(""); + secret = new FormControl(""); private onChange: (value: Verification) => void; diff --git a/libs/angular/src/services/jslib-services.module.ts b/libs/angular/src/services/jslib-services.module.ts index 529b3b52fa..729f876d3d 100644 --- a/libs/angular/src/services/jslib-services.module.ts +++ b/libs/angular/src/services/jslib-services.module.ts @@ -49,7 +49,8 @@ import { SyncService as SyncServiceAbstraction } from "@bitwarden/common/abstrac import { TokenService as TokenServiceAbstraction } from "@bitwarden/common/abstractions/token.service"; import { TotpService as TotpServiceAbstraction } from "@bitwarden/common/abstractions/totp.service"; import { TwoFactorService as TwoFactorServiceAbstraction } from "@bitwarden/common/abstractions/twoFactor.service"; -import { UserVerificationService as UserVerificationServiceAbstraction } from "@bitwarden/common/abstractions/userVerification.service"; +import { UserVerificationApiServiceAbstraction } from "@bitwarden/common/abstractions/userVerification/userVerification-api.service.abstraction"; +import { UserVerificationService as UserVerificationServiceAbstraction } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction"; import { UsernameGenerationService as UsernameGenerationServiceAbstraction } from "@bitwarden/common/abstractions/usernameGeneration.service"; import { VaultTimeoutService as VaultTimeoutServiceAbstraction } from "@bitwarden/common/abstractions/vaultTimeout.service"; import { StateFactory } from "@bitwarden/common/factories/stateFactory"; @@ -89,7 +90,8 @@ import { SyncService } from "@bitwarden/common/services/sync.service"; import { TokenService } from "@bitwarden/common/services/token.service"; import { TotpService } from "@bitwarden/common/services/totp.service"; import { TwoFactorService } from "@bitwarden/common/services/twoFactor.service"; -import { UserVerificationService } from "@bitwarden/common/services/userVerification.service"; +import { UserVerificationApiService } from "@bitwarden/common/services/userVerification/userVerification-api.service"; +import { UserVerificationService } from "@bitwarden/common/services/userVerification/userVerification.service"; import { UsernameGenerationService } from "@bitwarden/common/services/usernameGeneration.service"; import { VaultTimeoutService } from "@bitwarden/common/services/vaultTimeout.service"; import { WebCryptoFunctionService } from "@bitwarden/common/services/webCryptoFunction.service"; @@ -476,7 +478,11 @@ export const LOG_MAC_FAILURES = new InjectionToken("LOG_MAC_FAILURES"); { provide: UserVerificationServiceAbstraction, useClass: UserVerificationService, - deps: [CryptoServiceAbstraction, I18nServiceAbstraction, ApiServiceAbstraction], + deps: [ + CryptoServiceAbstraction, + I18nServiceAbstraction, + UserVerificationApiServiceAbstraction, + ], }, { provide: PasswordRepromptServiceAbstraction, useClass: PasswordRepromptService }, { @@ -502,6 +508,11 @@ export const LOG_MAC_FAILURES = new InjectionToken("LOG_MAC_FAILURES"); provide: FormValidationErrorsServiceAbstraction, useClass: FormValidationErrorsService, }, + { + provide: UserVerificationApiServiceAbstraction, + useClass: UserVerificationApiService, + deps: [ApiServiceAbstraction], + }, ], }) export class JslibServicesModule {} diff --git a/libs/common/src/abstractions/api.service.ts b/libs/common/src/abstractions/api.service.ts index 8599309836..d5267fa425 100644 --- a/libs/common/src/abstractions/api.service.ts +++ b/libs/common/src/abstractions/api.service.ts @@ -1,7 +1,6 @@ import { OrganizationApiKeyType } from "../enums/organizationApiKeyType"; import { OrganizationConnectionType } from "../enums/organizationConnectionType"; import { SetKeyConnectorKeyRequest } from "../models/request/account/setKeyConnectorKeyRequest"; -import { VerifyOTPRequest } from "../models/request/account/verifyOTPRequest"; import { AttachmentRequest } from "../models/request/attachmentRequest"; import { BitPayInvoiceRequest } from "../models/request/bitPayInvoiceRequest"; import { CipherBulkDeleteRequest } from "../models/request/cipherBulkDeleteRequest"; @@ -228,8 +227,6 @@ export abstract class ApiService { postUserApiKey: (id: string, request: SecretVerificationRequest) => Promise; postUserRotateApiKey: (id: string, request: SecretVerificationRequest) => Promise; putUpdateTempPassword: (request: UpdateTempPasswordRequest) => Promise; - postAccountRequestOTP: () => Promise; - postAccountVerifyOTP: (request: VerifyOTPRequest) => Promise; postConvertToKeyConnector: () => Promise; getUserBillingHistory: () => Promise; diff --git a/libs/common/src/abstractions/userVerification/userVerification-api.service.abstraction.ts b/libs/common/src/abstractions/userVerification/userVerification-api.service.abstraction.ts new file mode 100644 index 0000000000..c54077ef18 --- /dev/null +++ b/libs/common/src/abstractions/userVerification/userVerification-api.service.abstraction.ts @@ -0,0 +1,6 @@ +import { VerifyOTPRequest } from "@bitwarden/common/models/request/account/verifyOTPRequest"; + +export abstract class UserVerificationApiServiceAbstraction { + postAccountVerifyOTP: (request: VerifyOTPRequest) => Promise; + postAccountRequestOTP: () => Promise; +} diff --git a/libs/common/src/abstractions/userVerification.service.ts b/libs/common/src/abstractions/userVerification/userVerification.service.abstraction.ts similarity index 67% rename from libs/common/src/abstractions/userVerification.service.ts rename to libs/common/src/abstractions/userVerification/userVerification.service.abstraction.ts index ebd7d1f334..3d53063e45 100644 --- a/libs/common/src/abstractions/userVerification.service.ts +++ b/libs/common/src/abstractions/userVerification/userVerification.service.abstraction.ts @@ -1,5 +1,5 @@ -import { SecretVerificationRequest } from "../models/request/secretVerificationRequest"; -import { Verification } from "../types/verification"; +import { SecretVerificationRequest } from "../../models/request/secretVerificationRequest"; +import { Verification } from "../../types/verification"; export abstract class UserVerificationService { buildRequest: ( diff --git a/libs/common/src/services/account/account.service.ts b/libs/common/src/services/account/account.service.ts index 0870003414..2f3bacfbe1 100644 --- a/libs/common/src/services/account/account.service.ts +++ b/libs/common/src/services/account/account.service.ts @@ -1,7 +1,7 @@ import { AccountApiService } from "@bitwarden/common/abstractions/account/account-api.service.abstraction"; import { LogService } from "@bitwarden/common/abstractions/log.service"; import { MessagingService } from "@bitwarden/common/abstractions/messaging.service"; -import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification.service"; +import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction"; import { AccountService as AccountServiceAbstraction } from "../../abstractions/account/account.service.abstraction"; import { Verification } from "../../types/verification"; @@ -14,7 +14,7 @@ export class AccountService implements AccountServiceAbstraction { private logService: LogService ) {} - async delete(verification: Verification): Promise { + async delete(verification: Verification): Promise { try { const verificationRequest = await this.userVerificationService.buildRequest(verification); await this.accountApiService.deleteAccount(verificationRequest); diff --git a/libs/common/src/services/api.service.ts b/libs/common/src/services/api.service.ts index a68f06e97e..5573e644c4 100644 --- a/libs/common/src/services/api.service.ts +++ b/libs/common/src/services/api.service.ts @@ -8,7 +8,6 @@ import { OrganizationApiKeyType } from "../enums/organizationApiKeyType"; import { OrganizationConnectionType } from "../enums/organizationConnectionType"; import { Utils } from "../misc/utils"; import { SetKeyConnectorKeyRequest } from "../models/request/account/setKeyConnectorKeyRequest"; -import { VerifyOTPRequest } from "../models/request/account/verifyOTPRequest"; import { AttachmentRequest } from "../models/request/attachmentRequest"; import { BitPayInvoiceRequest } from "../models/request/bitPayInvoiceRequest"; import { CipherBulkDeleteRequest } from "../models/request/cipherBulkDeleteRequest"; @@ -457,14 +456,6 @@ export class ApiService implements ApiServiceAbstraction { return this.send("PUT", "/accounts/update-temp-password", request, true, false); } - postAccountRequestOTP(): Promise { - return this.send("POST", "/accounts/request-otp", null, true, false); - } - - postAccountVerifyOTP(request: VerifyOTPRequest): Promise { - return this.send("POST", "/accounts/verify-otp", request, true, false); - } - postConvertToKeyConnector(): Promise { return this.send("POST", "/accounts/convert-to-key-connector", null, true, false); } diff --git a/libs/common/src/services/userVerification/userVerification-api.service.ts b/libs/common/src/services/userVerification/userVerification-api.service.ts new file mode 100644 index 0000000000..26d5091354 --- /dev/null +++ b/libs/common/src/services/userVerification/userVerification-api.service.ts @@ -0,0 +1,14 @@ +import { ApiService } from "../../abstractions/api.service"; +import { UserVerificationApiServiceAbstraction } from "../../abstractions/userVerification/userVerification-api.service.abstraction"; +import { VerifyOTPRequest } from "../../models/request/account/verifyOTPRequest"; + +export class UserVerificationApiService implements UserVerificationApiServiceAbstraction { + constructor(private apiService: ApiService) {} + + postAccountVerifyOTP(request: VerifyOTPRequest): Promise { + return this.apiService.send("POST", "/accounts/verify-otp", request, true, false); + } + async postAccountRequestOTP(): Promise { + return this.apiService.send("POST", "/accounts/request-otp", null, true, false); + } +} diff --git a/libs/common/src/services/userVerification.service.ts b/libs/common/src/services/userVerification/userVerification.service.ts similarity index 74% rename from libs/common/src/services/userVerification.service.ts rename to libs/common/src/services/userVerification/userVerification.service.ts index 65207ac0a9..f58515d9a4 100644 --- a/libs/common/src/services/userVerification.service.ts +++ b/libs/common/src/services/userVerification/userVerification.service.ts @@ -1,11 +1,11 @@ -import { ApiService } from "../abstractions/api.service"; -import { CryptoService } from "../abstractions/crypto.service"; -import { I18nService } from "../abstractions/i18n.service"; -import { UserVerificationService as UserVerificationServiceAbstraction } from "../abstractions/userVerification.service"; -import { VerificationType } from "../enums/verificationType"; -import { VerifyOTPRequest } from "../models/request/account/verifyOTPRequest"; -import { SecretVerificationRequest } from "../models/request/secretVerificationRequest"; -import { Verification } from "../types/verification"; +import { CryptoService } from "../../abstractions/crypto.service"; +import { I18nService } from "../../abstractions/i18n.service"; +import { UserVerificationApiServiceAbstraction } from "../../abstractions/userVerification/userVerification-api.service.abstraction"; +import { UserVerificationService as UserVerificationServiceAbstraction } from "../../abstractions/userVerification/userVerification.service.abstraction"; +import { VerificationType } from "../../enums/verificationType"; +import { VerifyOTPRequest } from "../../models/request/account/verifyOTPRequest"; +import { SecretVerificationRequest } from "../../models/request/secretVerificationRequest"; +import { Verification } from "../../types/verification"; /** * Used for general-purpose user verification throughout the app. @@ -15,7 +15,7 @@ export class UserVerificationService implements UserVerificationServiceAbstracti constructor( private cryptoService: CryptoService, private i18nService: I18nService, - private apiService: ApiService + private userVerificationApiService: UserVerificationApiServiceAbstraction ) {} /** @@ -56,7 +56,7 @@ export class UserVerificationService implements UserVerificationServiceAbstracti if (verification.type === VerificationType.OTP) { const request = new VerifyOTPRequest(verification.secret); try { - await this.apiService.postAccountVerifyOTP(request); + await this.userVerificationApiService.postAccountVerifyOTP(request); } catch (e) { throw new Error(this.i18nService.t("invalidVerificationCode")); } @@ -73,7 +73,7 @@ export class UserVerificationService implements UserVerificationServiceAbstracti } async requestOTP() { - await this.apiService.postAccountRequestOTP(); + await this.userVerificationApiService.postAccountRequestOTP(); } private validateInput(verification: Verification) { diff --git a/libs/common/src/types/authResponse.ts b/libs/common/src/types/authResponse.ts new file mode 100644 index 0000000000..a6e7f1cb66 --- /dev/null +++ b/libs/common/src/types/authResponse.ts @@ -0,0 +1,12 @@ +import { VerificationType } from "../enums/verificationType"; + +import { TwoFactorResponse } from "./twoFactorResponse"; + +export type AuthResponseBase = { + secret: string; + verificationType: VerificationType; +}; + +export type AuthResponse = AuthResponseBase & { + response: T; +}; diff --git a/libs/common/src/types/twoFactorResponse.ts b/libs/common/src/types/twoFactorResponse.ts new file mode 100644 index 0000000000..fb9840fcc6 --- /dev/null +++ b/libs/common/src/types/twoFactorResponse.ts @@ -0,0 +1,14 @@ +import { TwoFactorAuthenticatorResponse } from "../models/response/twoFactorAuthenticatorResponse"; +import { TwoFactorDuoResponse } from "../models/response/twoFactorDuoResponse"; +import { TwoFactorEmailResponse } from "../models/response/twoFactorEmailResponse"; +import { TwoFactorRecoverResponse } from "../models/response/twoFactorRescoverResponse"; +import { TwoFactorWebAuthnResponse } from "../models/response/twoFactorWebAuthnResponse"; +import { TwoFactorYubiKeyResponse } from "../models/response/twoFactorYubiKeyResponse"; + +export type TwoFactorResponse = + | TwoFactorRecoverResponse + | TwoFactorDuoResponse + | TwoFactorEmailResponse + | TwoFactorWebAuthnResponse + | TwoFactorAuthenticatorResponse + | TwoFactorYubiKeyResponse; diff --git a/libs/electron/src/services/electronStorage.service.ts b/libs/electron/src/services/electronStorage.service.ts index e2ff9a92d0..d6e5bc4d52 100644 --- a/libs/electron/src/services/electronStorage.service.ts +++ b/libs/electron/src/services/electronStorage.service.ts @@ -5,23 +5,48 @@ import { ipcMain } from "electron"; import { AbstractStorageService } from "@bitwarden/common/abstractions/storage.service"; import { NodeUtils } from "@bitwarden/common/misc/nodeUtils"; +// See: https://github.com/sindresorhus/electron-store/blob/main/index.d.ts +interface ElectronStoreOptions { + defaults: unknown; + name: string; +} + +type ElectronStoreConstructor = new (options: ElectronStoreOptions) => ElectronStore; + // eslint-disable-next-line -const Store = require("electron-store"); +const Store: ElectronStoreConstructor = require("electron-store"); + +interface ElectronStore { + get: (key: string) => unknown; + set: (key: string, obj: unknown) => void; + delete: (key: string) => void; +} + +interface BaseOptions { + action: T; + key: string; +} + +interface SaveOptions extends BaseOptions<"save"> { + obj: unknown; +} + +type Options = BaseOptions<"get"> | BaseOptions<"has"> | SaveOptions | BaseOptions<"remove">; export class ElectronStorageService implements AbstractStorageService { - private store: any; + private store: ElectronStore; constructor(dir: string, defaults = {}) { if (!fs.existsSync(dir)) { NodeUtils.mkdirpSync(dir, "700"); } - const storeConfig: any = { + const storeConfig: ElectronStoreOptions = { defaults: defaults, name: "data", }; this.store = new Store(storeConfig); - ipcMain.handle("storageService", (event, options) => { + ipcMain.handle("storageService", (event, options: Options) => { switch (options.action) { case "get": return this.get(options.key); @@ -45,7 +70,7 @@ export class ElectronStorageService implements AbstractStorageService { return Promise.resolve(val != null); } - save(key: string, obj: any): Promise { + save(key: string, obj: unknown): Promise { if (obj instanceof Set) { obj = Array.from(obj); } @@ -53,7 +78,7 @@ export class ElectronStorageService implements AbstractStorageService { return Promise.resolve(); } - remove(key: string): Promise { + remove(key: string): Promise { this.store.delete(key); return Promise.resolve(); }