diff --git a/apps/browser/src/_locales/en/messages.json b/apps/browser/src/_locales/en/messages.json index 4775d1f7af0..f5cab851631 100644 --- a/apps/browser/src/_locales/en/messages.json +++ b/apps/browser/src/_locales/en/messages.json @@ -1173,6 +1173,9 @@ "message": "Oh no! We couldn't save this. Try entering the details manually.", "description": "Detailed error message shown when saving login details fails." }, + "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." + }, "enableChangedPasswordNotification": { "message": "Ask to update existing login" }, diff --git a/apps/browser/src/popup/app-routing.module.ts b/apps/browser/src/popup/app-routing.module.ts index 3dde9f15fdb..7f0108ec109 100644 --- a/apps/browser/src/popup/app-routing.module.ts +++ b/apps/browser/src/popup/app-routing.module.ts @@ -15,6 +15,7 @@ import { tdeDecryptionRequiredGuard, unauthGuardFn, } from "@bitwarden/angular/auth/guards"; +import { canAccessFeature } from "@bitwarden/angular/platform/guard/feature-flag.guard"; import { AnonLayoutWrapperComponent, AnonLayoutWrapperData, @@ -40,7 +41,9 @@ import { DeviceVerificationIcon, UserLockIcon, VaultIcon, + ChangePasswordComponent, } from "@bitwarden/auth/angular"; +import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { LockComponent } from "@bitwarden/key-management-ui"; import { fido2AuthGuard } from "../auth/guards/fido2-auth.guard"; @@ -327,10 +330,22 @@ const routes: Routes = [ canActivate: [authGuard], data: { elevation: 1 } satisfies RouteDataProperties, }, + { + path: "change-password", + component: ChangePasswordComponent, + }, { path: "update-temp-password", component: UpdateTempPasswordComponent, - canActivate: [authGuard], + canActivate: [ + canAccessFeature( + FeatureFlag.PM16117_ChangeExistingPasswordRefactor, + true, + "/change-password", + false, + ), + authGuard, + ], data: { elevation: 1 } satisfies RouteDataProperties, }, { diff --git a/apps/web/src/app/oss-routing.module.ts b/apps/web/src/app/oss-routing.module.ts index 3a515b6af46..7aa4903955b 100644 --- a/apps/web/src/app/oss-routing.module.ts +++ b/apps/web/src/app/oss-routing.module.ts @@ -41,6 +41,7 @@ import { DeviceVerificationIcon, ChangePasswordComponent, } from "@bitwarden/auth/angular"; +import { RouteList } from "@bitwarden/auth/common"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { LockComponent } from "@bitwarden/key-management-ui"; import { VaultIcons } from "@bitwarden/vault"; @@ -147,7 +148,7 @@ const routes: Routes = [ component: AnonLayoutWrapperComponent, children: [ { - path: "change-password", + path: RouteList.AdminRecoveryChangePasswordRoute, children: [ { path: "", @@ -157,6 +158,31 @@ const routes: Routes = [ data: { pageIcon: LockIcon, pageTitle: { key: "updateMasterPassword" }, + pageSubtitle: { key: "accountRecoveryUpdateMasterPasswordSubtitle" }, + hideFooter: true, + maxWidth: "lg", + } satisfies AnonLayoutWrapperData, + }, + ], + data: { titleId: "updatePassword" } satisfies RouteDataProperties, + }, + { + path: "", + component: AnonLayoutWrapperComponent, + children: [ + { + path: RouteList.NonCompliantPasswordRoute, + children: [ + { + path: "", + component: ChangePasswordComponent, + }, + ], + data: { + pageIcon: LockIcon, + pageTitle: { key: "updateMasterPassword" }, + pageSubtitle: { key: "updateMasterPasswordSubtitle" }, + hideFooter: true, maxWidth: "lg", } satisfies AnonLayoutWrapperData, @@ -171,7 +197,7 @@ const routes: Routes = [ canAccessFeature( FeatureFlag.PM16117_ChangeExistingPasswordRefactor, false, - "/change-password", + RouteList.AdminRecoveryChangePasswordRoute, false, ), authGuard, @@ -179,13 +205,13 @@ const routes: Routes = [ data: { titleId: "updateTempPassword" } satisfies RouteDataProperties, }, { - path: "update-password", + path: RouteList.OLDNonCompliantPasswordOnLogin, component: UpdatePasswordComponent, canActivate: [ canAccessFeature( FeatureFlag.PM16117_ChangeExistingPasswordRefactor, false, - "/change-password", + RouteList.NonCompliantPasswordRoute, false, ), authGuard, diff --git a/apps/web/src/locales/en/messages.json b/apps/web/src/locales/en/messages.json index 034a08bdf52..e23a433b23f 100644 --- a/apps/web/src/locales/en/messages.json +++ b/apps/web/src/locales/en/messages.json @@ -6056,6 +6056,12 @@ "updateMasterPassword": { "message": "Update master password" }, + "accountRecoveryUpdateMasterPasswordSubtitle": { + "message": "Admins have recovered your account. Change you master password to continue." + }, + "updateMasterPasswordSubtitle": { + "message": "Your master password does not meet this organization’s requirements. Change your master password to continue." + }, "updateMasterPasswordWarning": { "message": "Your master password was recently changed by an administrator in your organization. In order to access the vault, you must update your master password now. 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." }, diff --git a/libs/angular/src/auth/guards/auth.guard.ts b/libs/angular/src/auth/guards/auth.guard.ts index 690db37d090..693a19e4f05 100644 --- a/libs/angular/src/auth/guards/auth.guard.ts +++ b/libs/angular/src/auth/guards/auth.guard.ts @@ -10,12 +10,15 @@ import { } from "@angular/router"; import { firstValueFrom } from "rxjs"; +import { RouteList } from "@bitwarden/auth/common"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service"; import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status"; import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason"; +import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { KeyConnectorService } from "@bitwarden/common/key-management/key-connector/abstractions/key-connector.service"; import { MasterPasswordServiceAbstraction } from "@bitwarden/common/key-management/master-password/abstractions/master-password.service.abstraction"; +import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; export const authGuard: CanActivateFn = async ( @@ -28,6 +31,7 @@ export const authGuard: CanActivateFn = async ( const keyConnectorService = inject(KeyConnectorService); const accountService = inject(AccountService); const masterPasswordService = inject(MasterPasswordServiceAbstraction); + const configService = inject(ConfigService); const authStatus = await authService.getAuthStatus(); @@ -65,12 +69,37 @@ export const authGuard: CanActivateFn = async ( return router.createUrlTree(["/set-password"]); } - if ( - forceSetPasswordReason !== ForceSetPasswordReason.None && - !routerState.url.includes("update-temp-password") - ) { - return router.createUrlTree(["/update-temp-password"]); + if (await configService.getFeatureFlag(FeatureFlag.PM16117_ChangeExistingPasswordRefactor)) { + // Check for force set password reason to properly navigate to the right component. + + if ( + forceSetPasswordReason === ForceSetPasswordReason.AdminForcePasswordReset && + !routerState.url.includes(RouteList.AdminRecoveryChangePasswordRoute) + ) { + return router.createUrlTree([`/${RouteList.AdminRecoveryChangePasswordRoute}`]); + } + + if ( + forceSetPasswordReason === ForceSetPasswordReason.WeakMasterPassword && + !routerState.url.includes(RouteList.NonCompliantPasswordRoute) + ) { + return router.createUrlTree([`/${RouteList.NonCompliantPasswordRoute}`]); + } + } else { + if ( + forceSetPasswordReason !== ForceSetPasswordReason.None && + !routerState.url.includes("update-temp-password") + ) { + return router.createUrlTree(["/update-temp-password"]); + } } + // if ( + // forceSetPasswordReason !== ForceSetPasswordReason.None && + // !routerState.url.includes("update-temp-password") + // ) { + // return router.createUrlTree(["/update-temp-password"]); + // } + return true; }; 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 439087f902a..f0b5668528b 100644 --- a/libs/auth/src/angular/anon-layout/anon-layout.component.html +++ b/libs/auth/src/angular/anon-layout/anon-layout.component.html @@ -32,7 +32,9 @@ -
{{ subtitle }}
+
+ {{ subtitle }} +