1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-15 15:53:27 +00:00

docs(redirect-guard): [BEEEP] Document redirectGuard (#15196)

This commit is contained in:
rr-bw
2025-06-18 10:12:21 -07:00
committed by GitHub
parent a659c0a32d
commit 9e76448188
3 changed files with 65 additions and 4 deletions

View File

@@ -1,6 +1,6 @@
export * from "./auth.guard";
export * from "./active-auth.guard";
export * from "./lock.guard";
export * from "./redirect.guard";
export * from "./redirect/redirect.guard";
export * from "./tde-decryption-required.guard";
export * from "./unauth.guard";

View File

@@ -0,0 +1,53 @@
# Redirect Guard
The `redirectGuard` redirects the user based on their `AuthenticationStatus`. It is applied to the root route (`/`).
<br>
### Order of Operations
The `redirectGuard` will redirect the user based on the following checks, _in order_:
- **`AuthenticationStatus.LoggedOut`** &rarr; redirect to `/login`
- **`AuthenticationStatus.Unlocked`** &rarr; redirect to `/vault`
- **`AuthenticationStatus.Locked`**
- **TDE Locked State** &rarr; redirect to `/login-initiated`
- A user is in a TDE Locked State if they meet all 3 of the following conditions
1. Auth status is `Locked`
2. TDE is enabled
3. User has never had a user key (that is, user has not unlocked/decrypted yet)
- **Standard Locked State** &rarr; redirect to `/lock`
<br>
| Order | AuthenticationStatus | Redirect To |
| ----- | ------------------------------------------------------------------------------- | ------------------ |
| 1 | `LoggedOut` | `/login` |
| 2 | `Unlocked` | `/vault` |
| 3 | **TDE Locked State** <br> `Locked` + <br> `tdeEnabled` + <br> `!everHadUserKey` | `/login-initiated` |
| 4 | **Standard Locked State** <br> `Locked` | `/lock` |
<br>
### Default Routes and Route Overrides
The default redirect routes are mapped to object properties:
```typescript
const defaultRoutes: RedirectRoutes = {
loggedIn: "/vault",
loggedOut: "/login",
locked: "/lock",
notDecrypted: "/login-initiated",
};
```
But when applying the guard to the root route, the developer can override specific redirect routes by passing in a custom object. This is useful for subtle differences in client-specific routing:
```typescript
// app-routing.module.ts (Browser Extension)
{
path: "",
canActivate: [redirectGuard({ loggedIn: "/tabs/current"})],
}
```

View File

@@ -25,12 +25,14 @@ const defaultRoutes: RedirectRoutes = {
};
/**
* Guard that consolidates all redirection logic, should be applied to root route.
* Redirects the user to the appropriate route based on their `AuthenticationStatus`.
* This guard should be applied to the root route.
*
* TODO: This should return Observable<boolean | UrlTree> once we can get rid of all the promises
*/
export function redirectGuard(overrides: Partial<RedirectRoutes> = {}): CanActivateFn {
const routes = { ...defaultRoutes, ...overrides };
return async (route) => {
const authService = inject(AuthService);
const keyService = inject(KeyService);
@@ -41,16 +43,21 @@ export function redirectGuard(overrides: Partial<RedirectRoutes> = {}): CanActiv
const authStatus = await authService.getAuthStatus();
// Logged Out
if (authStatus === AuthenticationStatus.LoggedOut) {
return router.createUrlTree([routes.loggedOut], { queryParams: route.queryParams });
}
// Unlocked
if (authStatus === AuthenticationStatus.Unlocked) {
return router.createUrlTree([routes.loggedIn], { queryParams: route.queryParams });
}
// If locked, TDE is enabled, and the user hasn't decrypted yet, then redirect to the
// login decryption options component.
// Locked: TDE Locked State
// - If user meets all 3 of the following conditions:
// 1. Auth status is Locked
// 2. TDE is enabled
// 3. User has never had a user key (has not decrypted yet)
const tdeEnabled = await firstValueFrom(deviceTrustService.supportsDeviceTrust$);
const userId = await firstValueFrom(accountService.activeAccount$.pipe(getUserId));
const everHadUserKey = await firstValueFrom(keyService.everHadUserKey$(userId));
@@ -64,6 +71,7 @@ export function redirectGuard(overrides: Partial<RedirectRoutes> = {}): CanActiv
return router.createUrlTree([routes.notDecrypted], { queryParams: route.queryParams });
}
// Locked: Standard Locked State
if (authStatus === AuthenticationStatus.Locked) {
return router.createUrlTree([routes.locked], { queryParams: route.queryParams });
}