1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-26 09:33:22 +00:00

Merged with master and fixed conflicts

This commit is contained in:
gbubemismith
2023-09-21 15:10:54 -04:00
100 changed files with 1300 additions and 906 deletions

View File

@@ -1,40 +1,51 @@
<label class="environment-selector-btn">
<div class="environment-selector-btn">
{{ "loggingInOn" | i18n }}:
<a
<button
type="button"
(click)="toggle(null)"
cdkOverlayOrigin
#trigger="cdkOverlayOrigin"
aria-haspopup="menu"
aria-haspopup="dialog"
aria-controls="cdk-overlay-container"
[ngSwitch]="selectedEnvironment"
>
<label *ngSwitchCase="ServerEnvironmentType.US" class="text-primary">{{
<span *ngSwitchCase="ServerEnvironmentType.US" class="text-primary">{{
"usDomain" | i18n
}}</label>
<label *ngSwitchCase="ServerEnvironmentType.EU" class="text-primary">{{
}}</span>
<span *ngSwitchCase="ServerEnvironmentType.EU" class="text-primary">{{
"euDomain" | i18n
}}</label>
<label *ngSwitchCase="ServerEnvironmentType.SelfHosted" class="text-primary">{{
}}</span>
<span *ngSwitchCase="ServerEnvironmentType.SelfHosted" class="text-primary">{{
"selfHostedServer" | i18n
}}</label>
}}</span>
<i class="bwi bwi-fw bwi-sm bwi-angle-down" aria-hidden="true"></i>
</a>
</label>
</button>
</div>
<ng-template
cdkConnectedOverlay
[cdkConnectedOverlayOrigin]="trigger"
(backdropClick)="close()"
(detach)="close()"
[cdkConnectedOverlayOpen]="isOpen"
[cdkConnectedOverlayPositions]="overlayPosition"
[cdkConnectedOverlayHasBackdrop]="true"
[cdkConnectedOverlayBackdropClass]="'cdk-overlay-transparent-backdrop'"
(backdropClick)="isOpen = false"
(detach)="close()"
>
<div class="box-content">
<div class="environment-selector-dialog" [@transformPanel]="'open'" role="dialog">
<div
class="environment-selector-dialog"
[@transformPanel]="'open'"
cdkTrapFocus
cdkTrapFocusAutoCapture
role="dialog"
aria-modal="true"
>
<button
type="button"
class="environment-selector-dialog-item"
(click)="toggle(ServerEnvironmentType.US)"
[attr.aria-pressed]="selectedEnvironment === ServerEnvironmentType.US ? 'true' : 'false'"
>
<i
class="bwi bwi-fw bwi-sm bwi-check"
@@ -51,6 +62,7 @@
type="button"
class="environment-selector-dialog-item"
(click)="toggle(ServerEnvironmentType.EU)"
[attr.aria-pressed]="selectedEnvironment === ServerEnvironmentType.EU ? 'true' : 'false'"
*ngIf="euServerFlagEnabled"
>
<i
@@ -68,6 +80,9 @@
type="button"
class="environment-selector-dialog-item"
(click)="toggle(ServerEnvironmentType.SelfHosted)"
[attr.aria-pressed]="
selectedEnvironment === ServerEnvironmentType.SelfHosted ? 'true' : 'false'
"
>
<i
class="bwi bwi-fw bwi-sm bwi-check"

View File

@@ -152,6 +152,8 @@ export class LoginComponent extends CaptchaProtectedComponent implements OnInit,
await this.loginService.saveEmailSettings();
if (this.handleCaptchaRequired(response)) {
return;
} else if (this.handleMigrateEncryptionKey(response)) {
return;
} else if (response.requiresTwoFactor) {
if (this.onSuccessfulLoginTwoFactorNavigate != null) {
this.onSuccessfulLoginTwoFactorNavigate();
@@ -283,6 +285,21 @@ export class LoginComponent extends CaptchaProtectedComponent implements OnInit,
await this.loginService.saveEmailSettings();
}
// Legacy accounts used the master key to encrypt data. Migration is required
// but only performed on web
protected handleMigrateEncryptionKey(result: AuthResult): boolean {
if (!result.requiresEncryptionKeyMigration) {
return false;
}
this.platformUtilsService.showToast(
"error",
this.i18nService.t("errorOccured"),
this.i18nService.t("encryptionKeyMigrationRequired")
);
return true;
}
private getErrorToastMessage() {
const error: AllValidationErrors = this.formValidationErrorService
.getFormValidationErrors(this.formGroup.controls)

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", () => {
[
ForceResetPasswordReason.AdminForcePasswordReset,
ForceResetPasswordReason.WeakMasterPassword,
// ForceResetPasswordReason.WeakMasterPassword, -- not possible in SSO flow as set client side
].forEach((forceResetPasswordReason) => {
const reasonString = ForceResetPasswordReason[forceResetPasswordReason];
let authResult;
@@ -449,7 +449,7 @@ describe("SsoComponent", () => {
describe("Force Master Password Reset scenarios", () => {
[
ForceResetPasswordReason.AdminForcePasswordReset,
ForceResetPasswordReason.WeakMasterPassword,
// ForceResetPasswordReason.WeakMasterPassword, -- not possible in SSO flow as set client side
].forEach((forceResetPasswordReason) => {
const reasonString = ForceResetPasswordReason[forceResetPasswordReason];

View File

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

View File

@@ -215,9 +215,24 @@ export class TwoFactorComponent extends CaptchaProtectedComponent implements OnI
await this.handleLoginResponse(authResult);
}
protected handleMigrateEncryptionKey(result: AuthResult): boolean {
if (!result.requiresEncryptionKeyMigration) {
return false;
}
this.platformUtilsService.showToast(
"error",
this.i18nService.t("errorOccured"),
this.i18nService.t("encryptionKeyMigrationRequired")
);
return true;
}
private async handleLoginResponse(authResult: AuthResult) {
if (this.handleCaptchaRequired(authResult)) {
return;
} else if (this.handleMigrateEncryptionKey(authResult)) {
return;
}
this.loginService.clearValues();
@@ -282,8 +297,10 @@ export class TwoFactorComponent extends CaptchaProtectedComponent implements OnI
return await this.handleChangePasswordRequired(orgIdentifier);
}
// Users can be forced to reset their password via an admin or org policy
// disallowing weak passwords
// Users can be forced to reset their password via an admin or org policy 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) {
return await this.handleForcePasswordReset(orgIdentifier);
}

View File

@@ -10,7 +10,10 @@ import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
import { ClientType } from "@bitwarden/common/enums";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
/**
* Only allow access to this route if the vault is locked.
@@ -25,9 +28,21 @@ export function lockGuard(): CanActivateFn {
const authService = inject(AuthService);
const cryptoService = inject(CryptoService);
const deviceTrustCryptoService = inject(DeviceTrustCryptoServiceAbstraction);
const platformUtilService = inject(PlatformUtilsService);
const messagingService = inject(MessagingService);
const router = inject(Router);
const userVerificationService = inject(UserVerificationService);
// If legacy user on web, redirect to migration page
if (await cryptoService.isLegacyUser()) {
if (platformUtilService.getClientType() === ClientType.Web) {
return router.createUrlTree(["migrate-legacy-encryption"]);
}
// Log out legacy users on other clients
messagingService.send("logout");
return false;
}
const authStatus = await authService.getAuthStatus();
if (authStatus !== AuthenticationStatus.Locked) {
return router.createUrlTree(["/"]);