1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-07 12:13:45 +00:00
Files
browser/libs/angular/src/auth/guards/lock.guard.ts
Matt Gibson 46a3834f46 Add state for everHadUserKey (#7208)
* Migrate ever had user key

* Add DI for state providers

* Add state for everHadUserKey

* Use ever had user key migrator

Co-authored-by: SmithThe4th <gsmithwalter@gmail.com>
Co-authored-by: Carlos Gonçalves <LRNcardozoWDF@users.noreply.github.com>
Co-authored-by: Jason Ng <Jcory.ng@gmail.com>

* Fix test from merge

* Prefer stored observables to getters

getters create a new observable every time they're called, whereas one set in the constructor is created only once.

* Fix another merge issue

* Fix cli background build

---------

Co-authored-by: SmithThe4th <gsmithwalter@gmail.com>
Co-authored-by: Carlos Gonçalves <LRNcardozoWDF@users.noreply.github.com>
Co-authored-by: Jason Ng <Jcory.ng@gmail.com>
2024-01-10 11:51:45 -05:00

78 lines
3.2 KiB
TypeScript

import { inject } from "@angular/core";
import {
ActivatedRouteSnapshot,
CanActivateFn,
Router,
RouterStateSnapshot,
} from "@angular/router";
import { firstValueFrom } from "rxjs";
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.
* If TDE is enabled then the user must also have had a user key at some point.
* Otherwise redirect to root.
*
* TODO: This should return Observable<boolean | UrlTree> once we can remove all the promises
*/
export function lockGuard(): CanActivateFn {
return async (
activatedRouteSnapshot: ActivatedRouteSnapshot,
routerStateSnapshot: RouterStateSnapshot,
) => {
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);
const authStatus = await authService.getAuthStatus();
if (authStatus !== AuthenticationStatus.Locked) {
return router.createUrlTree(["/"]);
}
// 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;
}
// User is authN and in locked state.
const tdeEnabled = await deviceTrustCryptoService.supportsDeviceTrust();
// Create special exception which allows users to go from the login-initiated page to the lock page for the approve w/ MP flow
// The MP check is necessary to prevent direct manual navigation from other locked state pages for users who don't have a MP
if (
activatedRouteSnapshot.queryParams["from"] === "login-initiated" &&
tdeEnabled &&
(await userVerificationService.hasMasterPassword())
) {
return true;
}
// If authN user with TDE directly navigates to lock, kick them upwards so redirect guard can
// properly route them to the login decryption options component.
const everHadUserKey = await firstValueFrom(cryptoService.everHadUserKey$);
if (tdeEnabled && !everHadUserKey) {
return router.createUrlTree(["/"]);
}
return true;
};
}