diff --git a/.github/whitelist-capital-letters.txt b/.github/whitelist-capital-letters.txt
index 471602a09b..fd03af5f08 100644
--- a/.github/whitelist-capital-letters.txt
+++ b/.github/whitelist-capital-letters.txt
@@ -4,7 +4,6 @@
./apps/browser/src/safari/desktop/Base.lproj
./apps/browser/src/services/vaultTimeout
./apps/browser/store/windows/Assets
-./libs/common/src/abstractions/userVerification
./libs/common/src/abstractions/vaultTimeout
./libs/common/src/services/vaultTimeout
./bitwarden_license/README.md
@@ -26,8 +25,6 @@
./libs/common/src/misc/linkedFieldOption.decorator.ts
./libs/common/src/misc/serviceUtils.ts
./libs/common/src/misc/serviceUtils.spec.ts
-./libs/common/src/abstractions/userVerification/userVerification.service.abstraction.ts
-./libs/common/src/abstractions/userVerification/userVerification-api.service.abstraction.ts
./libs/common/src/abstractions/vaultTimeout/vaultTimeoutSettings.service.ts
./libs/common/src/abstractions/vaultTimeout/vaultTimeout.service.ts
./libs/common/src/abstractions/anonymousHub.service.ts
diff --git a/apps/browser/src/_locales/en/messages.json b/apps/browser/src/_locales/en/messages.json
index 498f41bde6..121c15aebd 100644
--- a/apps/browser/src/_locales/en/messages.json
+++ b/apps/browser/src/_locales/en/messages.json
@@ -952,7 +952,7 @@
"message": "Server URL"
},
"apiUrl": {
- "message": "API Server URL"
+ "message": "API server URL"
},
"webVaultUrl": {
"message": "Web vault server URL"
diff --git a/apps/browser/src/background/main.background.ts b/apps/browser/src/background/main.background.ts
index 0437fa55e0..f816624097 100644
--- a/apps/browser/src/background/main.background.ts
+++ b/apps/browser/src/background/main.background.ts
@@ -7,8 +7,6 @@ import { NotificationsService as NotificationsServiceAbstraction } from "@bitwar
import { SearchService as SearchServiceAbstraction } from "@bitwarden/common/abstractions/search.service";
import { SettingsService as SettingsServiceAbstraction } from "@bitwarden/common/abstractions/settings.service";
import { TotpService as TotpServiceAbstraction } from "@bitwarden/common/abstractions/totp.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 { VaultTimeoutService as VaultTimeoutServiceAbstraction } from "@bitwarden/common/abstractions/vaultTimeout/vaultTimeout.service";
import { VaultTimeoutSettingsService as VaultTimeoutSettingsServiceAbstraction } from "@bitwarden/common/abstractions/vaultTimeout/vaultTimeoutSettings.service";
import { InternalOrganizationService as InternalOrganizationServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
@@ -21,6 +19,8 @@ import { AuthService as AuthServiceAbstraction } from "@bitwarden/common/auth/ab
import { KeyConnectorService as KeyConnectorServiceAbstraction } from "@bitwarden/common/auth/abstractions/key-connector.service";
import { TokenService as TokenServiceAbstraction } from "@bitwarden/common/auth/abstractions/token.service";
import { TwoFactorService as TwoFactorServiceAbstraction } from "@bitwarden/common/auth/abstractions/two-factor.service";
+import { UserVerificationApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/user-verification/user-verification-api.service.abstraction";
+import { UserVerificationService as UserVerificationServiceAbstraction } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { AuthService } from "@bitwarden/common/auth/services/auth.service";
import { KeyConnectorService } from "@bitwarden/common/auth/services/key-connector.service";
import { TokenService } from "@bitwarden/common/auth/services/token.service";
diff --git a/apps/browser/src/popup/services/services.module.ts b/apps/browser/src/popup/services/services.module.ts
index e71bdd1c08..09be39be07 100644
--- a/apps/browser/src/popup/services/services.module.ts
+++ b/apps/browser/src/popup/services/services.module.ts
@@ -15,7 +15,6 @@ import { NotificationsService } from "@bitwarden/common/abstractions/notificatio
import { SearchService as SearchServiceAbstraction } from "@bitwarden/common/abstractions/search.service";
import { SettingsService } from "@bitwarden/common/abstractions/settings.service";
import { TotpService } from "@bitwarden/common/abstractions/totp.service";
-import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction";
import { VaultTimeoutService } from "@bitwarden/common/abstractions/vaultTimeout/vaultTimeout.service";
import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vaultTimeout/vaultTimeoutSettings.service";
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
@@ -31,6 +30,7 @@ import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-con
import { LoginService as LoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/login.service";
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
+import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { AuthService } from "@bitwarden/common/auth/services/auth.service";
import { LoginService } from "@bitwarden/common/auth/services/login.service";
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
diff --git a/apps/browser/src/tools/popup/settings/export.component.ts b/apps/browser/src/tools/popup/settings/export.component.ts
index c56b5c1f25..e21f3b9bd4 100644
--- a/apps/browser/src/tools/popup/settings/export.component.ts
+++ b/apps/browser/src/tools/popup/settings/export.component.ts
@@ -5,8 +5,8 @@ import { Router } from "@angular/router";
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
import { ExportComponent as BaseExportComponent } from "@bitwarden/angular/tools/export/components/export.component";
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
-import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction";
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
+import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
diff --git a/apps/desktop/src/app/tools/export/export.component.ts b/apps/desktop/src/app/tools/export/export.component.ts
index 70f74d0ecd..770c3bf5f5 100644
--- a/apps/desktop/src/app/tools/export/export.component.ts
+++ b/apps/desktop/src/app/tools/export/export.component.ts
@@ -6,8 +6,8 @@ import { UntypedFormBuilder } from "@angular/forms";
import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog";
import { ExportComponent as BaseExportComponent } from "@bitwarden/angular/tools/export/components/export.component";
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
-import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction";
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
+import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
diff --git a/apps/web/src/app/admin-console/organizations/settings/components/delete-organization-dialog.component.ts b/apps/web/src/app/admin-console/organizations/settings/components/delete-organization-dialog.component.ts
index 646b542aa1..df436e687e 100644
--- a/apps/web/src/app/admin-console/organizations/settings/components/delete-organization-dialog.component.ts
+++ b/apps/web/src/app/admin-console/organizations/settings/components/delete-organization-dialog.component.ts
@@ -4,10 +4,10 @@ import { FormBuilder, FormControl, Validators } from "@angular/forms";
import { combineLatest, Subject, takeUntil } from "rxjs";
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
-import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction";
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
+import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
@@ -17,7 +17,7 @@ import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.servi
import { CipherType } from "@bitwarden/common/vault/enums/cipher-type";
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
-import { UserVerificationModule } from "../../../../shared/components/user-verification";
+import { UserVerificationModule } from "../../../../auth/shared/components/user-verification";
import { SharedModule } from "../../../../shared/shared.module";
class CountBasedLocalizationKey {
diff --git a/apps/web/src/app/admin-console/organizations/tools/import-export/org-export.component.ts b/apps/web/src/app/admin-console/organizations/tools/import-export/org-export.component.ts
index 56fffd8260..35d445cb41 100644
--- a/apps/web/src/app/admin-console/organizations/tools/import-export/org-export.component.ts
+++ b/apps/web/src/app/admin-console/organizations/tools/import-export/org-export.component.ts
@@ -3,10 +3,9 @@ import { UntypedFormBuilder } from "@angular/forms";
import { ActivatedRoute } from "@angular/router";
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
-import { ModalService } from "@bitwarden/angular/services/modal.service";
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
-import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction";
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
+import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { EventType } from "@bitwarden/common/enums";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
@@ -35,7 +34,6 @@ export class OrganizationExportComponent extends ExportComponent {
userVerificationService: UserVerificationService,
formBuilder: UntypedFormBuilder,
fileDownloadService: FileDownloadService,
- modalService: ModalService,
dialogService: DialogServiceAbstraction
) {
super(
@@ -49,7 +47,6 @@ export class OrganizationExportComponent extends ExportComponent {
userVerificationService,
formBuilder,
fileDownloadService,
- modalService,
dialogService
);
}
diff --git a/apps/web/src/app/admin-console/organizations/users/enroll-master-password-reset.component.ts b/apps/web/src/app/admin-console/organizations/users/enroll-master-password-reset.component.ts
index 45b0cc318f..6680cbeae0 100644
--- a/apps/web/src/app/admin-console/organizations/users/enroll-master-password-reset.component.ts
+++ b/apps/web/src/app/admin-console/organizations/users/enroll-master-password-reset.component.ts
@@ -4,9 +4,9 @@ import { ModalRef } from "@bitwarden/angular/components/modal/modal.ref";
import { ModalConfig } from "@bitwarden/angular/services/modal.service";
import { OrganizationUserService } from "@bitwarden/common/abstractions/organization-user/organization-user.service";
import { OrganizationUserResetPasswordEnrollmentRequest } from "@bitwarden/common/abstractions/organization-user/requests";
-import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction";
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
+import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
diff --git a/apps/web/src/app/admin-console/organizations/users/organization-user.module.ts b/apps/web/src/app/admin-console/organizations/users/organization-user.module.ts
index 6799ae3ac4..30e2b5abe7 100644
--- a/apps/web/src/app/admin-console/organizations/users/organization-user.module.ts
+++ b/apps/web/src/app/admin-console/organizations/users/organization-user.module.ts
@@ -1,8 +1,8 @@
import { ScrollingModule } from "@angular/cdk/scrolling";
import { NgModule } from "@angular/core";
+import { UserVerificationModule } from "../../../auth/shared/components/user-verification";
import { LooseComponentsModule, SharedModule } from "../../../shared";
-import { UserVerificationModule } from "../../../shared/components/user-verification";
import { EnrollMasterPasswordReset } from "./enroll-master-password-reset.component";
diff --git a/apps/web/src/app/auth/settings/deauthorize-sessions.component.ts b/apps/web/src/app/auth/settings/deauthorize-sessions.component.ts
index fe758024cc..6c64933629 100644
--- a/apps/web/src/app/auth/settings/deauthorize-sessions.component.ts
+++ b/apps/web/src/app/auth/settings/deauthorize-sessions.component.ts
@@ -1,7 +1,7 @@
import { Component } from "@angular/core";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
-import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction";
+import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
diff --git a/apps/web/src/app/auth/settings/two-factor-authenticator.component.ts b/apps/web/src/app/auth/settings/two-factor-authenticator.component.ts
index fadf03b32e..29cc6df156 100644
--- a/apps/web/src/app/auth/settings/two-factor-authenticator.component.ts
+++ b/apps/web/src/app/auth/settings/two-factor-authenticator.component.ts
@@ -2,7 +2,7 @@ import { Component, OnDestroy, OnInit } from "@angular/core";
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
-import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction";
+import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
import { UpdateTwoFactorAuthenticatorRequest } from "@bitwarden/common/auth/models/request/update-two-factor-authenticator.request";
import { TwoFactorAuthenticatorResponse } from "@bitwarden/common/auth/models/response/two-factor-authenticator.response";
diff --git a/apps/web/src/app/auth/settings/two-factor-base.component.ts b/apps/web/src/app/auth/settings/two-factor-base.component.ts
index 95257421f8..d60da177a5 100644
--- a/apps/web/src/app/auth/settings/two-factor-base.component.ts
+++ b/apps/web/src/app/auth/settings/two-factor-base.component.ts
@@ -2,7 +2,7 @@ import { Directive, EventEmitter, Output } from "@angular/core";
import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
-import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction";
+import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
import { VerificationType } from "@bitwarden/common/auth/enums/verification-type";
import { SecretVerificationRequest } from "@bitwarden/common/auth/models/request/secret-verification.request";
diff --git a/apps/web/src/app/auth/settings/two-factor-duo.component.ts b/apps/web/src/app/auth/settings/two-factor-duo.component.ts
index 81d6ed859e..354f58f7f2 100644
--- a/apps/web/src/app/auth/settings/two-factor-duo.component.ts
+++ b/apps/web/src/app/auth/settings/two-factor-duo.component.ts
@@ -2,7 +2,7 @@ import { Component } from "@angular/core";
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
-import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction";
+import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
import { UpdateTwoFactorDuoRequest } from "@bitwarden/common/auth/models/request/update-two-factor-duo.request";
import { TwoFactorDuoResponse } from "@bitwarden/common/auth/models/response/two-factor-duo.response";
diff --git a/apps/web/src/app/auth/settings/two-factor-email.component.ts b/apps/web/src/app/auth/settings/two-factor-email.component.ts
index f0140dd245..8a7976a19e 100644
--- a/apps/web/src/app/auth/settings/two-factor-email.component.ts
+++ b/apps/web/src/app/auth/settings/two-factor-email.component.ts
@@ -2,7 +2,7 @@ import { Component } from "@angular/core";
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
-import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction";
+import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
import { TwoFactorEmailRequest } from "@bitwarden/common/auth/models/request/two-factor-email.request";
import { UpdateTwoFactorEmailRequest } from "@bitwarden/common/auth/models/request/update-two-factor-email.request";
diff --git a/apps/web/src/app/auth/settings/two-factor-verify.component.ts b/apps/web/src/app/auth/settings/two-factor-verify.component.ts
index e460a8cbd6..71a7772c8e 100644
--- a/apps/web/src/app/auth/settings/two-factor-verify.component.ts
+++ b/apps/web/src/app/auth/settings/two-factor-verify.component.ts
@@ -1,7 +1,7 @@
import { Component, EventEmitter, Input, Output } from "@angular/core";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
-import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction";
+import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
import { VerificationType } from "@bitwarden/common/auth/enums/verification-type";
import { SecretVerificationRequest } from "@bitwarden/common/auth/models/request/secret-verification.request";
diff --git a/apps/web/src/app/auth/settings/two-factor-webauthn.component.ts b/apps/web/src/app/auth/settings/two-factor-webauthn.component.ts
index 8e57e6e152..d528e81a8c 100644
--- a/apps/web/src/app/auth/settings/two-factor-webauthn.component.ts
+++ b/apps/web/src/app/auth/settings/two-factor-webauthn.component.ts
@@ -2,7 +2,7 @@ import { Component, NgZone } from "@angular/core";
import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
-import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction";
+import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
import { SecretVerificationRequest } from "@bitwarden/common/auth/models/request/secret-verification.request";
import { UpdateTwoFactorWebAuthnDeleteRequest } from "@bitwarden/common/auth/models/request/update-two-factor-web-authn-delete.request";
diff --git a/apps/web/src/app/auth/settings/two-factor-yubikey.component.ts b/apps/web/src/app/auth/settings/two-factor-yubikey.component.ts
index 4f6be97813..b9d2bd69f8 100644
--- a/apps/web/src/app/auth/settings/two-factor-yubikey.component.ts
+++ b/apps/web/src/app/auth/settings/two-factor-yubikey.component.ts
@@ -2,7 +2,7 @@ import { Component } from "@angular/core";
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
-import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction";
+import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
import { UpdateTwoFactorYubioOtpRequest } from "@bitwarden/common/auth/models/request/update-two-factor-yubio-otp.request";
import { TwoFactorYubiKeyResponse } from "@bitwarden/common/auth/models/response/two-factor-yubi-key.response";
diff --git a/apps/web/src/app/shared/components/user-verification/index.ts b/apps/web/src/app/auth/shared/components/user-verification/index.ts
similarity index 100%
rename from apps/web/src/app/shared/components/user-verification/index.ts
rename to apps/web/src/app/auth/shared/components/user-verification/index.ts
index 9fe21e309c..4fde4e67a2 100644
--- a/apps/web/src/app/shared/components/user-verification/index.ts
+++ b/apps/web/src/app/auth/shared/components/user-verification/index.ts
@@ -1,3 +1,3 @@
export * from "./user-verification.module";
-export * from "./user-verification-prompt.component";
export * from "./user-verification.component";
+export * from "./user-verification-prompt.component";
diff --git a/apps/web/src/app/auth/shared/components/user-verification/user-verification-prompt.component.html b/apps/web/src/app/auth/shared/components/user-verification/user-verification-prompt.component.html
new file mode 100644
index 0000000000..8001b6b0d6
--- /dev/null
+++ b/apps/web/src/app/auth/shared/components/user-verification/user-verification-prompt.component.html
@@ -0,0 +1,20 @@
+
diff --git a/apps/web/src/app/auth/shared/components/user-verification/user-verification-prompt.component.ts b/apps/web/src/app/auth/shared/components/user-verification/user-verification-prompt.component.ts
new file mode 100644
index 0000000000..2abacd3e8a
--- /dev/null
+++ b/apps/web/src/app/auth/shared/components/user-verification/user-verification-prompt.component.ts
@@ -0,0 +1,60 @@
+import { DialogConfig, DialogRef, DIALOG_DATA } from "@angular/cdk/dialog";
+import { Component, Inject } from "@angular/core";
+import { FormBuilder } from "@angular/forms";
+
+import { UserVerificationPromptComponent as BaseUserVerificationPrompt } from "@bitwarden/angular/auth/components/user-verification-prompt.component";
+import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
+import { ModalConfig } from "@bitwarden/angular/services/modal.service";
+import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
+import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
+import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
+
+export interface UserVerificationPromptParams {
+ confirmDescription: string;
+ confirmButtonText: string;
+ modalTitle: string;
+}
+
+@Component({
+ templateUrl: "user-verification-prompt.component.html",
+})
+export class UserVerificationPromptComponent extends BaseUserVerificationPrompt {
+ constructor(
+ @Inject(DIALOG_DATA) data: UserVerificationPromptParams,
+ private dialogRef: DialogRef,
+ userVerificationService: UserVerificationService,
+ formBuilder: FormBuilder,
+ platformUtilsService: PlatformUtilsService,
+ i18nService: I18nService
+ ) {
+ // TODO: Remove when BaseUserVerificationPrompt has support for CL
+ const modalConfig: ModalConfig = { data };
+ super(
+ null,
+ modalConfig,
+ userVerificationService,
+ formBuilder,
+ platformUtilsService,
+ i18nService
+ );
+ }
+
+ override close(success: boolean) {
+ this.dialogRef.close(success);
+ }
+}
+
+/**
+ * Strongly typed helper to open a UserVerificationPrompt
+ * @param dialogService Instance of the dialog service that will be used to open the dialog
+ * @param config Configuration for the dialog
+ */
+export const openUserVerificationPrompt = (
+ dialogService: DialogServiceAbstraction,
+ config: DialogConfig
+) => {
+ return dialogService.open(
+ UserVerificationPromptComponent,
+ config
+ );
+};
diff --git a/apps/web/src/app/auth/shared/components/user-verification/user-verification.component.html b/apps/web/src/app/auth/shared/components/user-verification/user-verification.component.html
new file mode 100644
index 0000000000..a15ce41738
--- /dev/null
+++ b/apps/web/src/app/auth/shared/components/user-verification/user-verification.component.html
@@ -0,0 +1,41 @@
+
+
+ {{ "masterPass" | i18n }}
+
+
+ {{ "confirmIdentity" | i18n }}
+
+
+
+
+
+
+
+
+ {{ "codeSent" | i18n }}
+
+
+
+
+ {{ "verificationCode" | i18n }}
+
+ {{ "confirmIdentity" | i18n }}
+
+
diff --git a/apps/web/src/app/shared/components/user-verification/user-verification.component.ts b/apps/web/src/app/auth/shared/components/user-verification/user-verification.component.ts
similarity index 100%
rename from apps/web/src/app/shared/components/user-verification/user-verification.component.ts
rename to apps/web/src/app/auth/shared/components/user-verification/user-verification.component.ts
diff --git a/apps/web/src/app/shared/components/user-verification/user-verification.module.ts b/apps/web/src/app/auth/shared/components/user-verification/user-verification.module.ts
similarity index 68%
rename from apps/web/src/app/shared/components/user-verification/user-verification.module.ts
rename to apps/web/src/app/auth/shared/components/user-verification/user-verification.module.ts
index de6b32f7fe..2287b76ae5 100644
--- a/apps/web/src/app/shared/components/user-verification/user-verification.module.ts
+++ b/apps/web/src/app/auth/shared/components/user-verification/user-verification.module.ts
@@ -1,12 +1,13 @@
import { NgModule } from "@angular/core";
+import { FormsModule, ReactiveFormsModule } from "@angular/forms";
-import { SharedModule } from "../../shared.module";
+import { SharedModule } from "../../../../shared/shared.module";
import { UserVerificationPromptComponent } from "./user-verification-prompt.component";
import { UserVerificationComponent } from "./user-verification.component";
@NgModule({
- imports: [SharedModule],
+ imports: [SharedModule, FormsModule, ReactiveFormsModule],
declarations: [UserVerificationComponent, UserVerificationPromptComponent],
exports: [UserVerificationComponent, UserVerificationPromptComponent],
})
diff --git a/apps/web/src/app/auth/update-password.component.ts b/apps/web/src/app/auth/update-password.component.ts
index d1d0ea8071..6c8e81fb4b 100644
--- a/apps/web/src/app/auth/update-password.component.ts
+++ b/apps/web/src/app/auth/update-password.component.ts
@@ -4,8 +4,8 @@ import { Router } from "@angular/router";
import { UpdatePasswordComponent as BaseUpdatePasswordComponent } from "@bitwarden/angular/auth/components/update-password.component";
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
-import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction";
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
+import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
diff --git a/apps/web/src/app/billing/organizations/billing-sync-api-key.component.ts b/apps/web/src/app/billing/organizations/billing-sync-api-key.component.ts
index 9bbcdf9333..8386747170 100644
--- a/apps/web/src/app/billing/organizations/billing-sync-api-key.component.ts
+++ b/apps/web/src/app/billing/organizations/billing-sync-api-key.component.ts
@@ -2,10 +2,10 @@ import { Component } from "@angular/core";
import { ModalConfig } from "@bitwarden/angular/services/modal.service";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
-import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction";
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
import { OrganizationApiKeyType } from "@bitwarden/common/admin-console/enums";
import { OrganizationApiKeyRequest } from "@bitwarden/common/admin-console/models/request/organization-api-key.request";
+import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { ApiKeyResponse } from "@bitwarden/common/auth/models/response/api-key.response";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
diff --git a/apps/web/src/app/billing/organizations/organization-billing.module.ts b/apps/web/src/app/billing/organizations/organization-billing.module.ts
index 8d3dbecd7b..590069cd85 100644
--- a/apps/web/src/app/billing/organizations/organization-billing.module.ts
+++ b/apps/web/src/app/billing/organizations/organization-billing.module.ts
@@ -1,7 +1,7 @@
import { NgModule } from "@angular/core";
+import { UserVerificationModule } from "../../auth/shared/components/user-verification";
import { LooseComponentsModule, SharedModule } from "../../shared";
-import { UserVerificationModule } from "../../shared/components/user-verification";
import { AdjustSubscription } from "./adjust-subscription.component";
import { BillingSyncApiKeyComponent } from "./billing-sync-api-key.component";
diff --git a/apps/web/src/app/settings/api-key.component.ts b/apps/web/src/app/settings/api-key.component.ts
index 2360a84e01..bdb74845c4 100644
--- a/apps/web/src/app/settings/api-key.component.ts
+++ b/apps/web/src/app/settings/api-key.component.ts
@@ -1,6 +1,6 @@
import { Component } from "@angular/core";
-import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction";
+import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { SecretVerificationRequest } from "@bitwarden/common/auth/models/request/secret-verification.request";
import { ApiKeyResponse } from "@bitwarden/common/auth/models/response/api-key.response";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
diff --git a/apps/web/src/app/settings/purge-vault.component.ts b/apps/web/src/app/settings/purge-vault.component.ts
index 23b7513268..83e8c2a8df 100644
--- a/apps/web/src/app/settings/purge-vault.component.ts
+++ b/apps/web/src/app/settings/purge-vault.component.ts
@@ -2,7 +2,7 @@ import { Component, Input } from "@angular/core";
import { Router } from "@angular/router";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
-import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction";
+import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
diff --git a/apps/web/src/app/shared/components/user-verification/user-verification-prompt.component.html b/apps/web/src/app/shared/components/user-verification/user-verification-prompt.component.html
deleted file mode 100644
index 10a137c51e..0000000000
--- a/apps/web/src/app/shared/components/user-verification/user-verification-prompt.component.html
+++ /dev/null
@@ -1,26 +0,0 @@
-
diff --git a/apps/web/src/app/shared/components/user-verification/user-verification-prompt.component.ts b/apps/web/src/app/shared/components/user-verification/user-verification-prompt.component.ts
deleted file mode 100644
index 4b24b446a8..0000000000
--- a/apps/web/src/app/shared/components/user-verification/user-verification-prompt.component.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import { Component } from "@angular/core";
-
-import { UserVerificationPromptComponent as BaseUserVerificationPrompt } from "@bitwarden/angular/auth/components/user-verification-prompt.component";
-
-@Component({
- templateUrl: "user-verification-prompt.component.html",
-})
-export class UserVerificationPromptComponent extends BaseUserVerificationPrompt {}
diff --git a/apps/web/src/app/shared/components/user-verification/user-verification.component.html b/apps/web/src/app/shared/components/user-verification/user-verification.component.html
deleted file mode 100644
index b90c6074d8..0000000000
--- a/apps/web/src/app/shared/components/user-verification/user-verification.component.html
+++ /dev/null
@@ -1,46 +0,0 @@
-
-
-
- {{ "confirmIdentity" | i18n }}
-
-
-
-
-
-
-
- {{ "codeSent" | i18n }}
-
-
-
-
-
-
- {{ "confirmIdentity" | i18n }}
-
-
diff --git a/apps/web/src/app/shared/loose-components.module.ts b/apps/web/src/app/shared/loose-components.module.ts
index c17cf5c76b..498f3af6d8 100644
--- a/apps/web/src/app/shared/loose-components.module.ts
+++ b/apps/web/src/app/shared/loose-components.module.ts
@@ -43,6 +43,7 @@ import { TwoFactorVerifyComponent } from "../auth/settings/two-factor-verify.com
import { TwoFactorWebAuthnComponent } from "../auth/settings/two-factor-webauthn.component";
import { TwoFactorYubiKeyComponent } from "../auth/settings/two-factor-yubikey.component";
import { VerifyEmailComponent } from "../auth/settings/verify-email.component";
+import { UserVerificationModule } from "../auth/shared/components/user-verification";
import { SsoComponent } from "../auth/sso.component";
import { TwoFactorOptionsComponent } from "../auth/two-factor-options.component";
import { TwoFactorComponent } from "../auth/two-factor.component";
@@ -108,7 +109,6 @@ import { AttachmentsComponent as OrgAttachmentsComponent } from "../vault/org-va
import { CollectionsComponent as OrgCollectionsComponent } from "../vault/org-vault/collections.component";
import { AccountFingerprintComponent } from "./components/account-fingerprint/account-fingerprint.component";
-import { UserVerificationModule } from "./components/user-verification";
import { SharedModule } from "./shared.module";
// Please do not add to this list of declarations - we should refactor these into modules when doing so makes sense until there are none left.
@@ -230,6 +230,7 @@ import { SharedModule } from "./shared.module";
LowKdfComponent,
],
exports: [
+ UserVerificationModule,
PremiumBadgeComponent,
AcceptEmergencyComponent,
AcceptOrganizationComponent,
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 71c25bbb7c..9d57f83f2a 100644
--- a/apps/web/src/app/tools/import-export/export.component.ts
+++ b/apps/web/src/app/tools/import-export/export.component.ts
@@ -1,12 +1,12 @@
import { Component } from "@angular/core";
import { UntypedFormBuilder } from "@angular/forms";
+import { firstValueFrom } from "rxjs";
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
-import { ModalService } from "@bitwarden/angular/services/modal.service";
import { ExportComponent as BaseExportComponent } from "@bitwarden/angular/tools/export/components/export.component";
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
-import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction";
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
+import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { EncryptedExportType } from "@bitwarden/common/enums";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
@@ -15,7 +15,7 @@ import { LogService } from "@bitwarden/common/platform/abstractions/log.service"
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { VaultExportServiceAbstraction } from "@bitwarden/exporter/vault-export";
-import { UserVerificationPromptComponent } from "../../shared/components/user-verification";
+import { openUserVerificationPrompt } from "../../auth/shared/components/user-verification";
@Component({
selector: "app-export",
@@ -37,7 +37,6 @@ export class ExportComponent extends BaseExportComponent {
userVerificationService: UserVerificationService,
formBuilder: UntypedFormBuilder,
fileDownloadService: FileDownloadService,
- private modalService: ModalService,
dialogService: DialogServiceAbstraction
) {
super(
@@ -101,8 +100,7 @@ export class ExportComponent extends BaseExportComponent {
confirmDescription = "encExportKeyWarningDesc";
}
- const ref = this.modalService.open(UserVerificationPromptComponent, {
- allowMultipleModals: true,
+ const ref = openUserVerificationPrompt(this.dialogService, {
data: {
confirmDescription: confirmDescription,
confirmButtonText: "exportVault",
@@ -114,7 +112,7 @@ export class ExportComponent extends BaseExportComponent {
return;
}
- return ref.onClosedPromise();
+ return firstValueFrom(ref.closed);
}
get isFileEncryptedExport() {
diff --git a/apps/web/src/locales/en/messages.json b/apps/web/src/locales/en/messages.json
index 0c542aeb4f..4cfc078661 100644
--- a/apps/web/src/locales/en/messages.json
+++ b/apps/web/src/locales/en/messages.json
@@ -2658,6 +2658,12 @@
"failedLogin2fa": {
"message": "Login attempt failed with incorrect two-step login."
},
+ "incorrectPassword": {
+ "message": "Incorrect password"
+ },
+ "incorrectCode": {
+ "message": "Incorrect code"
+ },
"exportedVault": {
"message": "Vault exported"
},
diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/access/access-tokens.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/access/access-tokens.component.ts
index 4e088c5a3c..e7e3c17fca 100644
--- a/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/access/access-tokens.component.ts
+++ b/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/access/access-tokens.component.ts
@@ -1,12 +1,12 @@
import { Component, OnInit } from "@angular/core";
import { ActivatedRoute } from "@angular/router";
-import { combineLatestWith, Observable, startWith, switchMap } from "rxjs";
+import { combineLatestWith, firstValueFrom, Observable, startWith, switchMap } from "rxjs";
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
import { ModalService } from "@bitwarden/angular/services/modal.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
-import { UserVerificationPromptComponent } from "@bitwarden/web-vault/app/shared/components/user-verification";
+import { openUserVerificationPrompt } from "@bitwarden/web-vault/app/auth/shared/components/user-verification";
import { AccessTokenView } from "../models/view/access-token.view";
@@ -75,8 +75,7 @@ export class AccessTokenComponent implements OnInit {
}
private verifyUser() {
- const ref = this.modalService.open(UserVerificationPromptComponent, {
- allowMultipleModals: true,
+ const ref = openUserVerificationPrompt(this.dialogService, {
data: {
confirmDescription: "revokeAccessTokenDesc",
confirmButtonText: "revokeAccessToken",
@@ -88,7 +87,7 @@ export class AccessTokenComponent implements OnInit {
return;
}
- return ref.onClosedPromise();
+ return firstValueFrom(ref.closed);
}
private async getAccessTokens(): Promise {
diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/settings/porting/sm-export.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/settings/porting/sm-export.component.ts
index 492207415a..9939e122e9 100644
--- a/bitwarden_license/bit-web/src/app/secrets-manager/settings/porting/sm-export.component.ts
+++ b/bitwarden_license/bit-web/src/app/secrets-manager/settings/porting/sm-export.component.ts
@@ -1,15 +1,15 @@
import { Component, OnDestroy, OnInit } from "@angular/core";
import { FormControl, FormGroup, Validators } from "@angular/forms";
import { ActivatedRoute } from "@angular/router";
-import { Subject, switchMap, takeUntil } from "rxjs";
+import { firstValueFrom, Subject, switchMap, takeUntil } from "rxjs";
-import { ModalService } from "@bitwarden/angular/services/modal.service";
+import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
-import { UserVerificationPromptComponent } from "@bitwarden/web-vault/app/shared/components/user-verification";
+import { openUserVerificationPrompt } from "@bitwarden/web-vault/app/auth/shared/components/user-verification";
import { SecretsManagerPortingApiService } from "../services/sm-porting-api.service";
import { SecretsManagerPortingService } from "../services/sm-porting.service";
@@ -42,7 +42,7 @@ export class SecretsManagerExportComponent implements OnInit, OnDestroy {
private smPortingService: SecretsManagerPortingService,
private fileDownloadService: FileDownloadService,
private logService: LogService,
- private modalService: ModalService,
+ private dialogService: DialogServiceAbstraction,
private secretsManagerApiService: SecretsManagerPortingApiService
) {}
@@ -98,8 +98,7 @@ export class SecretsManagerExportComponent implements OnInit, OnDestroy {
}
private verifyUser() {
- const ref = this.modalService.open(UserVerificationPromptComponent, {
- allowMultipleModals: true,
+ const ref = openUserVerificationPrompt(this.dialogService, {
data: {
confirmDescription: "exportWarningDesc",
confirmButtonText: "exportVault",
@@ -111,6 +110,6 @@ export class SecretsManagerExportComponent implements OnInit, OnDestroy {
return;
}
- return ref.onClosedPromise();
+ return firstValueFrom(ref.closed);
}
}
diff --git a/libs/angular/src/auth/components/update-password.component.ts b/libs/angular/src/auth/components/update-password.component.ts
index f4773ee961..8acfe9485f 100644
--- a/libs/angular/src/auth/components/update-password.component.ts
+++ b/libs/angular/src/auth/components/update-password.component.ts
@@ -2,9 +2,9 @@ import { Directive } from "@angular/core";
import { Router } from "@angular/router";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
-import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction";
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
import { MasterPasswordPolicyOptions } from "@bitwarden/common/admin-console/models/domain/master-password-policy-options";
+import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { VerificationType } from "@bitwarden/common/auth/enums/verification-type";
import { PasswordRequest } from "@bitwarden/common/auth/models/request/password.request";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
diff --git a/libs/angular/src/auth/components/update-temp-password.component.ts b/libs/angular/src/auth/components/update-temp-password.component.ts
index 3964f3c22b..be27659d07 100644
--- a/libs/angular/src/auth/components/update-temp-password.component.ts
+++ b/libs/angular/src/auth/components/update-temp-password.component.ts
@@ -2,9 +2,9 @@ import { Directive } from "@angular/core";
import { Router } from "@angular/router";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
-import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction";
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
import { MasterPasswordPolicyOptions } from "@bitwarden/common/admin-console/models/domain/master-password-policy-options";
+import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { VerificationType } from "@bitwarden/common/auth/enums/verification-type";
import { ForceResetPasswordReason } from "@bitwarden/common/auth/models/domain/force-reset-password-reason";
import { PasswordRequest } from "@bitwarden/common/auth/models/request/password.request";
diff --git a/libs/angular/src/auth/components/user-verification-prompt.component.ts b/libs/angular/src/auth/components/user-verification-prompt.component.ts
index 1a10c96cf5..1b0a1dbed8 100644
--- a/libs/angular/src/auth/components/user-verification-prompt.component.ts
+++ b/libs/angular/src/auth/components/user-verification-prompt.component.ts
@@ -1,9 +1,10 @@
import { Directive } from "@angular/core";
-import { FormBuilder, FormControl } from "@angular/forms";
+import { FormBuilder } from "@angular/forms";
-import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction";
+import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
+import { Verification } from "@bitwarden/common/types/verification";
import { ModalRef } from "../../components/modal/modal.ref";
import { ModalConfig } from "../../services/modal.service";
@@ -16,7 +17,12 @@ export class UserVerificationPromptComponent {
confirmDescription = this.config.data.confirmDescription;
confirmButtonText = this.config.data.confirmButtonText;
modalTitle = this.config.data.modalTitle;
- secret = new FormControl();
+
+ formGroup = this.formBuilder.group({
+ secret: this.formBuilder.control(null),
+ });
+
+ protected invalidSecret = false;
constructor(
private modalRef: ModalRef,
@@ -27,19 +33,31 @@ export class UserVerificationPromptComponent {
private i18nService: I18nService
) {}
- async submit() {
- try {
- //Incorrect secret will throw an invalid password error.
- await this.userVerificationService.verifyUser(this.secret.value);
- } catch (e) {
- this.platformUtilsService.showToast(
- "error",
- this.i18nService.t("error"),
- this.i18nService.t("invalidMasterPassword")
- );
+ get secret() {
+ return this.formGroup.controls.secret;
+ }
+
+ submit = async () => {
+ this.formGroup.markAllAsTouched();
+
+ if (this.formGroup.invalid) {
return;
}
- this.modalRef.close(true);
+ try {
+ //Incorrect secret will throw an invalid password error.
+ await this.userVerificationService.verifyUser(this.secret.value);
+ this.invalidSecret = false;
+ } catch (e) {
+ this.invalidSecret = true;
+ this.platformUtilsService.showToast("error", this.i18nService.t("error"), e.message);
+ return;
+ }
+
+ this.close(true);
+ };
+
+ close(success: boolean) {
+ this.modalRef.close(success);
}
}
diff --git a/libs/angular/src/auth/components/user-verification.component.ts b/libs/angular/src/auth/components/user-verification.component.ts
index 5f9d62c3dc..9dfed5b924 100644
--- a/libs/angular/src/auth/components/user-verification.component.ts
+++ b/libs/angular/src/auth/components/user-verification.component.ts
@@ -1,9 +1,11 @@
-import { Directive, OnInit } from "@angular/core";
-import { ControlValueAccessor, FormControl } from "@angular/forms";
+import { Directive, EventEmitter, Input, OnDestroy, OnInit, Output } from "@angular/core";
+import { ControlValueAccessor, FormControl, Validators } from "@angular/forms";
+import { Subject, takeUntil } from "rxjs";
-import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction";
import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service";
+import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { VerificationType } from "@bitwarden/common/auth/enums/verification-type";
+import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { Verification } from "@bitwarden/common/types/verification";
@@ -17,29 +19,65 @@ import { Verification } from "@bitwarden/common/types/verification";
selector: "app-user-verification",
})
// eslint-disable-next-line rxjs-angular/prefer-takeuntil
-export class UserVerificationComponent implements ControlValueAccessor, OnInit {
- usesKeyConnector = false;
+export class UserVerificationComponent implements ControlValueAccessor, OnInit, OnDestroy {
+ private _invalidSecret = false;
+ @Input()
+ get invalidSecret() {
+ return this._invalidSecret;
+ }
+ set invalidSecret(value: boolean) {
+ this._invalidSecret = value;
+ this.invalidSecretChange.emit(value);
+
+ // ISSUE: This is pretty hacky but unfortunately there is no way of knowing if the parent
+ // control has been marked as touched, see: https://github.com/angular/angular/issues/10887
+ // When that functionality has been added we should also look into forwarding reactive form
+ // controls errors so that we don't need a separate input/output `invalidSecret`.
+ if (value) {
+ this.secret.markAsTouched();
+ }
+ this.secret.updateValueAndValidity({ emitEvent: false });
+ }
+ @Output() invalidSecretChange = new EventEmitter();
+
+ usesKeyConnector = true;
disableRequestOTP = false;
sentCode = false;
- secret = new FormControl("");
+ secret = new FormControl("", [
+ Validators.required,
+ () => {
+ if (this.invalidSecret) {
+ return {
+ invalidSecret: {
+ message: this.usesKeyConnector
+ ? this.i18nService.t("incorrectCode")
+ : this.i18nService.t("incorrectPassword"),
+ },
+ };
+ }
+ },
+ ]);
private onChange: (value: Verification) => void;
+ private destroy$ = new Subject();
constructor(
private keyConnectorService: KeyConnectorService,
- private userVerificationService: UserVerificationService
+ private userVerificationService: UserVerificationService,
+ private i18nService: I18nService
) {}
async ngOnInit() {
this.usesKeyConnector = await this.keyConnectorService.getUsesKeyConnector();
this.processChanges(this.secret.value);
- // eslint-disable-next-line rxjs-angular/prefer-takeuntil
- this.secret.valueChanges.subscribe((secret: string) => this.processChanges(secret));
+ this.secret.valueChanges
+ .pipe(takeUntil(this.destroy$))
+ .subscribe((secret: string) => this.processChanges(secret));
}
- async requestOTP() {
+ requestOTP = async () => {
if (this.usesKeyConnector) {
this.disableRequestOTP = true;
try {
@@ -49,7 +87,7 @@ export class UserVerificationComponent implements ControlValueAccessor, OnInit {
this.disableRequestOTP = false;
}
}
- }
+ };
writeValue(obj: any): void {
this.secret.setValue(obj);
@@ -72,7 +110,14 @@ export class UserVerificationComponent implements ControlValueAccessor, OnInit {
}
}
- private processChanges(secret: string) {
+ ngOnDestroy(): void {
+ this.destroy$.next();
+ this.destroy$.complete();
+ }
+
+ protected processChanges(secret: string) {
+ this.invalidSecret = false;
+
if (this.onChange == null) {
return;
}
diff --git a/libs/angular/src/services/jslib-services.module.ts b/libs/angular/src/services/jslib-services.module.ts
index 87ede0f2b9..aa9117e32d 100644
--- a/libs/angular/src/services/jslib-services.module.ts
+++ b/libs/angular/src/services/jslib-services.module.ts
@@ -19,8 +19,6 @@ import { OrganizationUserService } from "@bitwarden/common/abstractions/organiza
import { SearchService as SearchServiceAbstraction } from "@bitwarden/common/abstractions/search.service";
import { SettingsService as SettingsServiceAbstraction } from "@bitwarden/common/abstractions/settings.service";
import { TotpService as TotpServiceAbstraction } from "@bitwarden/common/abstractions/totp.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 { VaultTimeoutService as VaultTimeoutServiceAbstraction } from "@bitwarden/common/abstractions/vaultTimeout/vaultTimeout.service";
import { VaultTimeoutSettingsService as VaultTimeoutSettingsServiceAbstraction } from "@bitwarden/common/abstractions/vaultTimeout/vaultTimeoutSettings.service";
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
@@ -49,6 +47,8 @@ import { KeyConnectorService as KeyConnectorServiceAbstraction } from "@bitwarde
import { LoginService as LoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/login.service";
import { TokenService as TokenServiceAbstraction } from "@bitwarden/common/auth/abstractions/token.service";
import { TwoFactorService as TwoFactorServiceAbstraction } from "@bitwarden/common/auth/abstractions/two-factor.service";
+import { UserVerificationApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/user-verification/user-verification-api.service.abstraction";
+import { UserVerificationService as UserVerificationServiceAbstraction } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { AccountApiServiceImplementation } from "@bitwarden/common/auth/services/account-api.service";
import { AccountServiceImplementation } from "@bitwarden/common/auth/services/account.service";
import { AuthService } from "@bitwarden/common/auth/services/auth.service";
diff --git a/libs/angular/src/tools/export/components/export.component.ts b/libs/angular/src/tools/export/components/export.component.ts
index d7d3a1fc4c..595a6ebdfd 100644
--- a/libs/angular/src/tools/export/components/export.component.ts
+++ b/libs/angular/src/tools/export/components/export.component.ts
@@ -3,9 +3,9 @@ import { UntypedFormBuilder, Validators } from "@angular/forms";
import { merge, startWith, Subject, takeUntil } from "rxjs";
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
-import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification/userVerification.service.abstraction";
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
import { PolicyType } from "@bitwarden/common/admin-console/enums";
+import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { EncryptedExportType, EventType } from "@bitwarden/common/enums";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
diff --git a/libs/common/src/abstractions/userVerification/userVerification-api.service.abstraction.ts b/libs/common/src/auth/abstractions/user-verification/user-verification-api.service.abstraction.ts
similarity index 69%
rename from libs/common/src/abstractions/userVerification/userVerification-api.service.abstraction.ts
rename to libs/common/src/auth/abstractions/user-verification/user-verification-api.service.abstraction.ts
index 78e4099eee..b861ce4471 100644
--- a/libs/common/src/abstractions/userVerification/userVerification-api.service.abstraction.ts
+++ b/libs/common/src/auth/abstractions/user-verification/user-verification-api.service.abstraction.ts
@@ -1,4 +1,4 @@
-import { VerifyOTPRequest } from "../../auth/models/request/verify-otp.request";
+import { VerifyOTPRequest } from "../../models/request/verify-otp.request";
export abstract class UserVerificationApiServiceAbstraction {
postAccountVerifyOTP: (request: VerifyOTPRequest) => Promise;
diff --git a/libs/common/src/abstractions/userVerification/userVerification.service.abstraction.ts b/libs/common/src/auth/abstractions/user-verification/user-verification.service.abstraction.ts
similarity index 66%
rename from libs/common/src/abstractions/userVerification/userVerification.service.abstraction.ts
rename to libs/common/src/auth/abstractions/user-verification/user-verification.service.abstraction.ts
index dcfd52bf05..09e4063434 100644
--- a/libs/common/src/abstractions/userVerification/userVerification.service.abstraction.ts
+++ b/libs/common/src/auth/abstractions/user-verification/user-verification.service.abstraction.ts
@@ -1,5 +1,5 @@
-import { SecretVerificationRequest } from "../../auth/models/request/secret-verification.request";
-import { Verification } from "../../types/verification";
+import { Verification } from "../../../types/verification";
+import { SecretVerificationRequest } from "../../models/request/secret-verification.request";
export abstract class UserVerificationService {
buildRequest: (
diff --git a/libs/common/src/auth/services/account-api.service.ts b/libs/common/src/auth/services/account-api.service.ts
index 05ec1b8453..270ec1a201 100644
--- a/libs/common/src/auth/services/account-api.service.ts
+++ b/libs/common/src/auth/services/account-api.service.ts
@@ -1,9 +1,9 @@
import { ApiService } from "../../abstractions/api.service";
-import { UserVerificationService } from "../../abstractions/userVerification/userVerification.service.abstraction";
import { LogService } from "../../platform/abstractions/log.service";
import { Verification } from "../../types/verification";
import { AccountApiService } from "../abstractions/account-api.service";
import { InternalAccountService } from "../abstractions/account.service";
+import { UserVerificationService } from "../abstractions/user-verification/user-verification.service.abstraction";
export class AccountApiServiceImplementation implements AccountApiService {
constructor(
diff --git a/libs/common/src/auth/services/user-verification/user-verification-api.service.ts b/libs/common/src/auth/services/user-verification/user-verification-api.service.ts
index 1e0d9b2c57..0f0eb16e92 100644
--- a/libs/common/src/auth/services/user-verification/user-verification-api.service.ts
+++ b/libs/common/src/auth/services/user-verification/user-verification-api.service.ts
@@ -1,5 +1,5 @@
import { ApiService } from "../../../abstractions/api.service";
-import { UserVerificationApiServiceAbstraction } from "../../../abstractions/userVerification/userVerification-api.service.abstraction";
+import { UserVerificationApiServiceAbstraction } from "../../abstractions/user-verification/user-verification-api.service.abstraction";
import { VerifyOTPRequest } from "../../models/request/verify-otp.request";
export class UserVerificationApiService implements UserVerificationApiServiceAbstraction {
diff --git a/libs/common/src/auth/services/user-verification/user-verification.service.ts b/libs/common/src/auth/services/user-verification/user-verification.service.ts
index 085c6ac572..0be8d3e729 100644
--- a/libs/common/src/auth/services/user-verification/user-verification.service.ts
+++ b/libs/common/src/auth/services/user-verification/user-verification.service.ts
@@ -1,8 +1,8 @@
-import { UserVerificationApiServiceAbstraction } from "../../../abstractions/userVerification/userVerification-api.service.abstraction";
-import { UserVerificationService as UserVerificationServiceAbstraction } from "../../../abstractions/userVerification/userVerification.service.abstraction";
import { CryptoService } from "../../../platform/abstractions/crypto.service";
import { I18nService } from "../../../platform/abstractions/i18n.service";
import { Verification } from "../../../types/verification";
+import { UserVerificationApiServiceAbstraction } from "../../abstractions/user-verification/user-verification-api.service.abstraction";
+import { UserVerificationService as UserVerificationServiceAbstraction } from "../../abstractions/user-verification/user-verification.service.abstraction";
import { VerificationType } from "../../enums/verification-type";
import { SecretVerificationRequest } from "../../models/request/secret-verification.request";
import { VerifyOTPRequest } from "../../models/request/verify-otp.request";
diff --git a/libs/components/src/form-field/form-field.component.ts b/libs/components/src/form-field/form-field.component.ts
index 9553641188..6fcb4090dd 100644
--- a/libs/components/src/form-field/form-field.component.ts
+++ b/libs/components/src/form-field/form-field.component.ts
@@ -1,8 +1,11 @@
+import { coerceBooleanProperty } from "@angular/cdk/coercion";
import {
AfterContentChecked,
Component,
ContentChild,
ContentChildren,
+ HostBinding,
+ Input,
QueryList,
ViewChild,
} from "@angular/core";
@@ -17,9 +20,6 @@ import { BitSuffixDirective } from "./suffix.directive";
@Component({
selector: "bit-form-field",
templateUrl: "./form-field.component.html",
- host: {
- class: "tw-mb-6 tw-block",
- },
})
export class BitFormFieldComponent implements AfterContentChecked {
@ContentChild(BitFormFieldControl) input: BitFormFieldControl;
@@ -30,6 +30,19 @@ export class BitFormFieldComponent implements AfterContentChecked {
@ContentChildren(BitPrefixDirective) prefixChildren: QueryList;
@ContentChildren(BitSuffixDirective) suffixChildren: QueryList;
+ private _disableMargin = false;
+ @Input() set disableMargin(value: boolean | "") {
+ this._disableMargin = coerceBooleanProperty(value);
+ }
+ get disableMargin() {
+ return this._disableMargin;
+ }
+
+ @HostBinding("class")
+ get classList() {
+ return ["tw-block"].concat(this.disableMargin ? [] : ["tw-mb-6"]);
+ }
+
ngAfterContentChecked(): void {
if (this.error) {
this.input.ariaDescribedBy = this.error.id;