diff --git a/apps/web/src/app/auth/core/services/login/web-login-component.service.ts b/apps/web/src/app/auth/core/services/login/web-login-component.service.ts
index c644f26dd90..36e7143ccd0 100644
--- a/apps/web/src/app/auth/core/services/login/web-login-component.service.ts
+++ b/apps/web/src/app/auth/core/services/login/web-login-component.service.ts
@@ -98,7 +98,7 @@ export class WebLoginComponentService
const enforcedPasswordPolicyOptions = await firstValueFrom(
this.accountService.activeAccount$.pipe(
getUserId,
- switchMap((userId) => this.policyService.masterPasswordPolicyOptions$(userId)),
+ switchMap((userId) => this.policyService.masterPasswordPolicyOptions$(userId, policies)),
),
);
diff --git a/apps/web/src/app/auth/settings/security/password-settings/password-settings.component.html b/apps/web/src/app/auth/settings/security/password-settings/password-settings.component.html
index 94cf08b5871..e5fb7142a1a 100644
--- a/apps/web/src/app/auth/settings/security/password-settings/password-settings.component.html
+++ b/apps/web/src/app/auth/settings/security/password-settings/password-settings.component.html
@@ -3,7 +3,6 @@
-
{{ "loggedOutWarning" | i18n }}
diff --git a/apps/web/src/app/oss-routing.module.ts b/apps/web/src/app/oss-routing.module.ts
index 2c3664284d2..c1592efea4a 100644
--- a/apps/web/src/app/oss-routing.module.ts
+++ b/apps/web/src/app/oss-routing.module.ts
@@ -155,8 +155,10 @@ const routes: Routes = [
},
],
data: {
- pageIcon: undefined,
+ pageIcon: LockIcon,
+ pageTitle: { key: "updateMasterPassword" },
hideFooter: true,
+ maxWidth: "lg",
} satisfies AnonLayoutWrapperData,
},
],
@@ -168,7 +170,7 @@ const routes: Routes = [
canActivate: [
canAccessFeature(
FeatureFlag.PM16117_ChangeExistingPasswordRefactor,
- false,
+ true,
"/change-password",
false,
),
@@ -182,7 +184,7 @@ const routes: Routes = [
canActivate: [
canAccessFeature(
FeatureFlag.PM16117_ChangeExistingPasswordRefactor,
- false,
+ true,
"/change-password",
false,
),
diff --git a/apps/web/src/locales/en/messages.json b/apps/web/src/locales/en/messages.json
index 3bf3ab91c78..034a08bdf52 100644
--- a/apps/web/src/locales/en/messages.json
+++ b/apps/web/src/locales/en/messages.json
@@ -1788,6 +1788,9 @@
"loggedOutWarning": {
"message": "Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour."
},
+ "changePasswordWarning": {
+ "message": "After changing your password, you will need to log in with your new password. Active sessions on other devices will be logged out within one hour."
+ },
"emailChanged": {
"message": "Email saved"
},
diff --git a/libs/auth/src/angular/anon-layout/anon-layout-wrapper.component.ts b/libs/auth/src/angular/anon-layout/anon-layout-wrapper.component.ts
index c0b072fd8f1..5ae2fdbf347 100644
--- a/libs/auth/src/angular/anon-layout/anon-layout-wrapper.component.ts
+++ b/libs/auth/src/angular/anon-layout/anon-layout-wrapper.component.ts
@@ -34,7 +34,7 @@ export interface AnonLayoutWrapperData {
/**
* Optional flag to set the max-width of the page. Defaults to 'md' if not provided.
*/
- maxWidth?: "md" | "3xl";
+ maxWidth?: "sm" | "md" | "lg" | "xl" | "2xl" | "3xl";
/**
* Optional flag to set the max-width of the title area. Defaults to null if not provided.
*/
diff --git a/libs/auth/src/angular/anon-layout/anon-layout.component.html b/libs/auth/src/angular/anon-layout/anon-layout.component.html
index 1e16dba82cc..439087f902a 100644
--- a/libs/auth/src/angular/anon-layout/anon-layout.component.html
+++ b/libs/auth/src/angular/anon-layout/anon-layout.component.html
@@ -37,7 +37,14 @@
}
diff --git a/libs/auth/src/angular/change-password/change-password.component.ts b/libs/auth/src/angular/change-password/change-password.component.ts
index 9cfb78d994b..85d421072b1 100644
--- a/libs/auth/src/angular/change-password/change-password.component.ts
+++ b/libs/auth/src/angular/change-password/change-password.component.ts
@@ -5,25 +5,15 @@ import { firstValueFrom } from "rxjs";
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 { Account, AccountService } from "@bitwarden/common/auth/abstractions/account.service";
-import { MasterPasswordApiService } from "@bitwarden/common/auth/abstractions/master-password-api.service.abstraction";
import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason";
-import { PasswordRequest } from "@bitwarden/common/auth/models/request/password.request";
-import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/key-management/master-password/abstractions/master-password.service.abstraction";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
-import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
import { SyncService } from "@bitwarden/common/platform/sync";
import { UserId } from "@bitwarden/common/types/guid";
-import { UserKey } from "@bitwarden/common/types/key";
import { DialogService, ToastService, Translation } from "@bitwarden/components";
-import { KeyService } from "@bitwarden/key-management";
import { I18nPipe } from "@bitwarden/ui-common";
-// import {
-// AcceptOrganizationInviteService
-// } from "@bitwarden/web-vault/src/app/auth/organization-invite/accept-organization.service";
-// import { RouterService } from "@bitwarden/web-vault/src/app/core";
import {
InputPasswordComponent,
@@ -48,18 +38,15 @@ export class ChangePasswordComponent implements OnInit {
masterPasswordPolicyOptions?: MasterPasswordPolicyOptions;
initializing = true;
submitting = false;
- userkeyRotationV2 = false;
formPromise?: Promise
;
- secondaryButtonText?: Translation = undefined;
forceSetPasswordReason: ForceSetPasswordReason = ForceSetPasswordReason.None;
+ warningText?: Translation;
constructor(
private accountService: AccountService,
private changePasswordService: ChangePasswordService,
private configService: ConfigService,
private i18nService: I18nService,
- private keyService: KeyService,
- private masterPasswordApiService: MasterPasswordApiService,
private masterPasswordService: InternalMasterPasswordServiceAbstraction,
private messagingService: MessagingService,
private policyService: PolicyService,
@@ -72,8 +59,6 @@ export class ChangePasswordComponent implements OnInit {
) {}
async ngOnInit() {
- this.userkeyRotationV2 = await this.configService.getFeatureFlag(FeatureFlag.UserKeyRotationV2);
-
this.activeAccount = await firstValueFrom(this.accountService.activeAccount$);
this.activeUserId = this.activeAccount?.id;
this.email = this.activeAccount?.email;
@@ -90,26 +75,10 @@ export class ChangePasswordComponent implements OnInit {
this.masterPasswordService.forceSetPasswordReason$(this.activeUserId),
);
- if (
- this.forceSetPasswordReason === ForceSetPasswordReason.AdminForcePasswordReset ||
- this.forceSetPasswordReason === ForceSetPasswordReason.WeakMasterPassword
- ) {
- this.secondaryButtonText = { key: "cancel" };
- } else {
- this.secondaryButtonText = undefined;
- }
-
this.initializing = false;
- }
- async performSecondaryAction() {
- if (
- this.forceSetPasswordReason === ForceSetPasswordReason.AdminForcePasswordReset ||
- this.forceSetPasswordReason === ForceSetPasswordReason.WeakMasterPassword
- ) {
- await this.logOut();
- } else {
- await this.cancel();
+ if (this.masterPasswordPolicyOptions?.enforceOnLogin) {
+ this.warningText = { key: "masterPasswordInvalidWarning" };
}
}
@@ -126,24 +95,9 @@ export class ChangePasswordComponent implements OnInit {
}
}
- async cancel() {
- // clearing the login redirect url so that the user
- // does not join the organization if they cancel
- // await this.routerService.getAndClearLoginRedirectUrl();
- // await this.acceptOrganizationInviteService.clearOrganizationInvitation();
- // await this.router.navigate(["/vault"]);
- }
-
async handlePasswordFormSubmit(passwordInputResult: PasswordInputResult) {
this.submitting = true;
- if (this.userkeyRotationV2) {
- await this.submitNew(passwordInputResult);
- } else {
- await this.submitOld(passwordInputResult);
- }
- }
- private async submitNew(passwordInputResult: PasswordInputResult) {
try {
if (passwordInputResult.rotateUserKey) {
if (this.activeAccount == null) {
@@ -187,83 +141,4 @@ export class ChangePasswordComponent implements OnInit {
this.submitting = false;
}
}
-
- private async submitOld(passwordInputResult: PasswordInputResult) {
- if (!this.activeUserId) {
- throw new Error("userId not found");
- }
-
- if (passwordInputResult.currentServerMasterKeyHash == null) {
- throw new Error("currentServerMasterKeyHash not found");
- }
-
- if (passwordInputResult.rotateUserKey) {
- await this.syncService.fullSync(true);
- }
-
- let newMasterKeyEncryptedUserKey: [UserKey, EncString] | null = null;
-
- const userKey = await this.keyService.getUserKey();
- if (userKey == null) {
- newMasterKeyEncryptedUserKey = await this.keyService.makeUserKey(
- passwordInputResult.newMasterKey,
- );
- } else {
- newMasterKeyEncryptedUserKey = await this.keyService.encryptUserKeyWithMasterKey(
- passwordInputResult.newMasterKey,
- );
- }
-
- const request = new PasswordRequest();
- request.masterPasswordHash = passwordInputResult.currentServerMasterKeyHash;
- request.newMasterPasswordHash = passwordInputResult.newServerMasterKeyHash;
- request.masterPasswordHint = passwordInputResult.newPasswordHint;
- request.key = newMasterKeyEncryptedUserKey[1].encryptedString as string;
-
- try {
- if (passwordInputResult.rotateUserKey) {
- this.formPromise = this.masterPasswordApiService.postPassword(request).then(async () => {
- // we need to save this for local masterkey verification during rotation
- await this.masterPasswordService.setMasterKeyHash(
- passwordInputResult.newLocalMasterKeyHash,
- this.activeUserId as UserId,
- );
- await this.masterPasswordService.setMasterKey(
- passwordInputResult.newMasterKey,
- this.activeUserId as UserId,
- );
- return this.updateKey(passwordInputResult.newPassword);
- });
- } else {
- this.formPromise = this.masterPasswordApiService.postPassword(request);
- }
-
- await this.formPromise;
-
- this.toastService.showToast({
- variant: "success",
- title: this.i18nService.t("masterPasswordChanged"),
- message: this.i18nService.t("logBackIn"),
- });
-
- this.messagingService.send("logout");
- } catch {
- this.toastService.showToast({
- variant: "error",
- title: "",
- message: this.i18nService.t("errorOccurred"),
- });
- }
- }
-
- private async updateKey(newPassword: string) {
- if (this.activeAccount == null) {
- throw new Error("activeAccount not found");
- }
-
- await this.changePasswordService.rotateUserKeyAndEncryptedDataLegacy(
- newPassword,
- this.activeAccount,
- );
- }
}
diff --git a/libs/auth/src/angular/input-password/input-password.component.html b/libs/auth/src/angular/input-password/input-password.component.html
index 8955a7b40b1..d7742a97876 100644
--- a/libs/auth/src/angular/input-password/input-password.component.html
+++ b/libs/auth/src/angular/input-password/input-password.component.html
@@ -1,4 +1,6 @@