mirror of
https://github.com/bitwarden/browser
synced 2025-12-16 16:23:44 +00:00
docs(redirect-guard): [BEEEP] Document redirectGuard (#15196)
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
export * from "./auth.guard";
|
export * from "./auth.guard";
|
||||||
export * from "./active-auth.guard";
|
export * from "./active-auth.guard";
|
||||||
export * from "./lock.guard";
|
export * from "./lock.guard";
|
||||||
export * from "./redirect.guard";
|
export * from "./redirect/redirect.guard";
|
||||||
export * from "./tde-decryption-required.guard";
|
export * from "./tde-decryption-required.guard";
|
||||||
export * from "./unauth.guard";
|
export * from "./unauth.guard";
|
||||||
|
|||||||
53
libs/angular/src/auth/guards/redirect/README.md
Normal file
53
libs/angular/src/auth/guards/redirect/README.md
Normal 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`** → redirect to `/login`
|
||||||
|
- **`AuthenticationStatus.Unlocked`** → redirect to `/vault`
|
||||||
|
- **`AuthenticationStatus.Locked`**
|
||||||
|
- **TDE Locked State** → 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** → 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"})],
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -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
|
* TODO: This should return Observable<boolean | UrlTree> once we can get rid of all the promises
|
||||||
*/
|
*/
|
||||||
export function redirectGuard(overrides: Partial<RedirectRoutes> = {}): CanActivateFn {
|
export function redirectGuard(overrides: Partial<RedirectRoutes> = {}): CanActivateFn {
|
||||||
const routes = { ...defaultRoutes, ...overrides };
|
const routes = { ...defaultRoutes, ...overrides };
|
||||||
|
|
||||||
return async (route) => {
|
return async (route) => {
|
||||||
const authService = inject(AuthService);
|
const authService = inject(AuthService);
|
||||||
const keyService = inject(KeyService);
|
const keyService = inject(KeyService);
|
||||||
@@ -41,16 +43,21 @@ export function redirectGuard(overrides: Partial<RedirectRoutes> = {}): CanActiv
|
|||||||
|
|
||||||
const authStatus = await authService.getAuthStatus();
|
const authStatus = await authService.getAuthStatus();
|
||||||
|
|
||||||
|
// Logged Out
|
||||||
if (authStatus === AuthenticationStatus.LoggedOut) {
|
if (authStatus === AuthenticationStatus.LoggedOut) {
|
||||||
return router.createUrlTree([routes.loggedOut], { queryParams: route.queryParams });
|
return router.createUrlTree([routes.loggedOut], { queryParams: route.queryParams });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unlocked
|
||||||
if (authStatus === AuthenticationStatus.Unlocked) {
|
if (authStatus === AuthenticationStatus.Unlocked) {
|
||||||
return router.createUrlTree([routes.loggedIn], { queryParams: route.queryParams });
|
return router.createUrlTree([routes.loggedIn], { queryParams: route.queryParams });
|
||||||
}
|
}
|
||||||
|
|
||||||
// If locked, TDE is enabled, and the user hasn't decrypted yet, then redirect to the
|
// Locked: TDE Locked State
|
||||||
// login decryption options component.
|
// - 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 tdeEnabled = await firstValueFrom(deviceTrustService.supportsDeviceTrust$);
|
||||||
const userId = await firstValueFrom(accountService.activeAccount$.pipe(getUserId));
|
const userId = await firstValueFrom(accountService.activeAccount$.pipe(getUserId));
|
||||||
const everHadUserKey = await firstValueFrom(keyService.everHadUserKey$(userId));
|
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 });
|
return router.createUrlTree([routes.notDecrypted], { queryParams: route.queryParams });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Locked: Standard Locked State
|
||||||
if (authStatus === AuthenticationStatus.Locked) {
|
if (authStatus === AuthenticationStatus.Locked) {
|
||||||
return router.createUrlTree([routes.locked], { queryParams: route.queryParams });
|
return router.createUrlTree([routes.locked], { queryParams: route.queryParams });
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user