1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-12-21 16:18:28 +01:00

PM-3444 - TDE - Admin Acct Recovery should prompt users to change MP for non MP decryption flows (#6109)

* PM-3444 - SSO Login Strategy - Should setForcePasswordResetReason if server sends it down so that the auth.guard can direct the user accordingly after decryption

* PM-3444 - (1) Sso Comp - Adjust force password reset logic to handle the only scenario that can occur here - admin acct recovery - not weak mp (can't evaluate as user won't have entered it yet) (2) Add comments explaining the scenarios + update tests.

* PM-3444 - Update SSO Login strategy to only check for ForceResetPasswordReason.AdminForcePasswordReset as that's the only scenario that can happen here.

* PM-3444 - Finish updating tests to pass

* PM-3444 - Resolve PR feedback by updating ForceResetPasswordReason comments
This commit is contained in:
Jared Snider 2023-09-18 12:21:30 -04:00 committed by GitHub
parent 2e76bc40b9
commit 4a8741e7b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 22 additions and 7 deletions

View File

@ -352,7 +352,7 @@ describe("SsoComponent", () => {
describe("Given Trusted Device Encryption is enabled, user doesn't need to set a MP, and forcePasswordReset is required", () => { describe("Given Trusted Device Encryption is enabled, user doesn't need to set a MP, and forcePasswordReset is required", () => {
[ [
ForceResetPasswordReason.AdminForcePasswordReset, ForceResetPasswordReason.AdminForcePasswordReset,
ForceResetPasswordReason.WeakMasterPassword, // ForceResetPasswordReason.WeakMasterPassword, -- not possible in SSO flow as set client side
].forEach((forceResetPasswordReason) => { ].forEach((forceResetPasswordReason) => {
const reasonString = ForceResetPasswordReason[forceResetPasswordReason]; const reasonString = ForceResetPasswordReason[forceResetPasswordReason];
let authResult; let authResult;
@ -449,7 +449,7 @@ describe("SsoComponent", () => {
describe("Force Master Password Reset scenarios", () => { describe("Force Master Password Reset scenarios", () => {
[ [
ForceResetPasswordReason.AdminForcePasswordReset, ForceResetPasswordReason.AdminForcePasswordReset,
ForceResetPasswordReason.WeakMasterPassword, // ForceResetPasswordReason.WeakMasterPassword, -- not possible in SSO flow as set client side
].forEach((forceResetPasswordReason) => { ].forEach((forceResetPasswordReason) => {
const reasonString = ForceResetPasswordReason[forceResetPasswordReason]; const reasonString = ForceResetPasswordReason[forceResetPasswordReason];

View File

@ -226,9 +226,9 @@ export class SsoComponent {
return await this.handleChangePasswordRequired(orgIdentifier); return await this.handleChangePasswordRequired(orgIdentifier);
} }
// Users can be forced to reset their password via an admin or org policy // Users enrolled in admin acct recovery can be forced to set a new password after
// disallowing weak passwords // having the admin set a temp password for them
if (authResult.forcePasswordReset !== ForceResetPasswordReason.None) { if (authResult.forcePasswordReset == ForceResetPasswordReason.AdminForcePasswordReset) {
return await this.handleForcePasswordReset(orgIdentifier); return await this.handleForcePasswordReset(orgIdentifier);
} }

View File

@ -282,8 +282,10 @@ export class TwoFactorComponent extends CaptchaProtectedComponent implements OnI
return await this.handleChangePasswordRequired(orgIdentifier); return await this.handleChangePasswordRequired(orgIdentifier);
} }
// Users can be forced to reset their password via an admin or org policy // Users can be forced to reset their password via an admin or org policy disallowing weak passwords
// disallowing weak passwords // Note: this is different from SSO component login flow as a user can
// login with MP and then have to pass 2FA to finish login and we can actually
// evaluate if they have a weak password at this time.
if (authResult.forcePasswordReset !== ForceResetPasswordReason.None) { if (authResult.forcePasswordReset !== ForceResetPasswordReason.None) {
return await this.handleForcePasswordReset(orgIdentifier); return await this.handleForcePasswordReset(orgIdentifier);
} }

View File

@ -153,6 +153,7 @@ export abstract class LogInStrategy {
const result = new AuthResult(); const result = new AuthResult();
result.resetMasterPassword = response.resetMasterPassword; result.resetMasterPassword = response.resetMasterPassword;
// Convert boolean to enum
if (response.forcePasswordReset) { if (response.forcePasswordReset) {
result.forcePasswordReset = ForceResetPasswordReason.AdminForcePasswordReset; result.forcePasswordReset = ForceResetPasswordReason.AdminForcePasswordReset;
} }

View File

@ -14,6 +14,7 @@ import { DeviceTrustCryptoServiceAbstraction } from "../abstractions/device-trus
import { KeyConnectorService } from "../abstractions/key-connector.service"; import { KeyConnectorService } from "../abstractions/key-connector.service";
import { TokenService } from "../abstractions/token.service"; import { TokenService } from "../abstractions/token.service";
import { TwoFactorService } from "../abstractions/two-factor.service"; import { TwoFactorService } from "../abstractions/two-factor.service";
import { ForceResetPasswordReason } from "../models/domain/force-reset-password-reason";
import { SsoLogInCredentials } from "../models/domain/log-in-credentials"; import { SsoLogInCredentials } from "../models/domain/log-in-credentials";
import { SsoTokenRequest } from "../models/request/identity-token/sso-token.request"; import { SsoTokenRequest } from "../models/request/identity-token/sso-token.request";
import { IdentityTokenResponse } from "../models/response/identity-token.response"; import { IdentityTokenResponse } from "../models/response/identity-token.response";
@ -73,6 +74,11 @@ export class SsoLogInStrategy extends LogInStrategy {
this.email = ssoAuthResult.email; this.email = ssoAuthResult.email;
this.ssoEmail2FaSessionToken = ssoAuthResult.ssoEmail2FaSessionToken; this.ssoEmail2FaSessionToken = ssoAuthResult.ssoEmail2FaSessionToken;
// Auth guard currently handles redirects for this.
if (ssoAuthResult.forcePasswordReset == ForceResetPasswordReason.AdminForcePasswordReset) {
await this.stateService.setForcePasswordResetReason(ssoAuthResult.forcePasswordReset);
}
return ssoAuthResult; return ssoAuthResult;
} }

View File

@ -1,3 +1,7 @@
/*
* This enum is used to determine if a user should be forced to reset their password
* on login (server flag) or unlock via MP (client evaluation).
*/
export enum ForceResetPasswordReason { export enum ForceResetPasswordReason {
/** /**
* A password reset should not be forced. * A password reset should not be forced.
@ -6,12 +10,14 @@ export enum ForceResetPasswordReason {
/** /**
* Occurs when an organization admin forces a user to reset their password. * Occurs when an organization admin forces a user to reset their password.
* Communicated via server flag.
*/ */
AdminForcePasswordReset, AdminForcePasswordReset,
/** /**
* Occurs when a user logs in / unlocks their vault with a master password that does not meet an organization's * Occurs when a user logs in / unlocks their vault with a master password that does not meet an organization's
* master password policy that is enforced on login/unlock. * master password policy that is enforced on login/unlock.
* Only set client side b/c server can't evaluate MP.
*/ */
WeakMasterPassword, WeakMasterPassword,
} }