mirror of
https://github.com/bitwarden/browser
synced 2025-12-06 00:13:28 +00:00
[PM-20540] Deep-link refactor to fix SSO deep links (#14587)
* PM-20540 - TwoFactorAuthComponent - Refactor determineDefaultSuccessRoute to rely on user's auth status as the loginStrategyService's state is cleared after successful AuthN * PM-20540 - DeepLinkGuard - Refactor to exempt login-initiated so that TDE + unlock with MP + deep link works. * doc: Add documentation and change folder structure. * test: add test for new excluded route. --------- Co-authored-by: Jared Snider <jsnider@bitwarden.com>
This commit is contained in:
@@ -16,8 +16,10 @@ import {
|
||||
} from "@bitwarden/auth/common";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
|
||||
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
|
||||
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
||||
import { AuthenticationType } from "@bitwarden/common/auth/enums/authentication-type";
|
||||
import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
|
||||
import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason";
|
||||
@@ -72,6 +74,7 @@ describe("TwoFactorAuthComponent", () => {
|
||||
let mockEnvService: MockProxy<EnvironmentService>;
|
||||
let mockLoginSuccessHandlerService: MockProxy<LoginSuccessHandlerService>;
|
||||
let mockTwoFactorAuthCompCacheService: MockProxy<TwoFactorAuthComponentCacheService>;
|
||||
let mockAuthService: MockProxy<AuthService>;
|
||||
|
||||
let mockUserDecryptionOpts: {
|
||||
noMasterPassword: UserDecryptionOptions;
|
||||
@@ -106,6 +109,7 @@ describe("TwoFactorAuthComponent", () => {
|
||||
mockDialogService = mock<DialogService>();
|
||||
mockToastService = mock<ToastService>();
|
||||
mockTwoFactorAuthCompService = mock<TwoFactorAuthComponentService>();
|
||||
mockAuthService = mock<AuthService>();
|
||||
|
||||
mockEnvService = mock<EnvironmentService>();
|
||||
mockLoginSuccessHandlerService = mock<LoginSuccessHandlerService>();
|
||||
@@ -204,6 +208,7 @@ describe("TwoFactorAuthComponent", () => {
|
||||
provide: TwoFactorAuthComponentCacheService,
|
||||
useValue: mockTwoFactorAuthCompCacheService,
|
||||
},
|
||||
{ provide: AuthService, useValue: mockAuthService },
|
||||
],
|
||||
});
|
||||
|
||||
@@ -295,6 +300,7 @@ describe("TwoFactorAuthComponent", () => {
|
||||
|
||||
it("navigates to the component's defined success route (vault is default) when the login is successful", async () => {
|
||||
mockLoginStrategyService.logInTwoFactor.mockResolvedValue(new AuthResult());
|
||||
mockAuthService.activeAccountStatus$ = new BehaviorSubject(AuthenticationStatus.Unlocked);
|
||||
|
||||
// Act
|
||||
await component.submit("testToken");
|
||||
@@ -316,13 +322,14 @@ describe("TwoFactorAuthComponent", () => {
|
||||
async (authType, expectedRoute) => {
|
||||
mockLoginStrategyService.logInTwoFactor.mockResolvedValue(new AuthResult());
|
||||
currentAuthTypeSubject.next(authType);
|
||||
mockAuthService.activeAccountStatus$ = new BehaviorSubject(AuthenticationStatus.Locked);
|
||||
|
||||
// Act
|
||||
await component.submit("testToken");
|
||||
|
||||
// Assert
|
||||
expect(mockRouter.navigate).toHaveBeenCalledTimes(1);
|
||||
expect(mockRouter.navigate).toHaveBeenCalledWith(["lock"], {
|
||||
expect(mockRouter.navigate).toHaveBeenCalledWith([expectedRoute], {
|
||||
queryParams: {
|
||||
identifier: component.orgSsoIdentifier,
|
||||
},
|
||||
|
||||
@@ -24,9 +24,10 @@ import {
|
||||
LoginSuccessHandlerService,
|
||||
} from "@bitwarden/auth/common";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
|
||||
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
|
||||
import { AuthenticationType } from "@bitwarden/common/auth/enums/authentication-type";
|
||||
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
||||
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
|
||||
import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
|
||||
import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason";
|
||||
@@ -167,6 +168,7 @@ export class TwoFactorAuthComponent implements OnInit, OnDestroy {
|
||||
private environmentService: EnvironmentService,
|
||||
private loginSuccessHandlerService: LoginSuccessHandlerService,
|
||||
private twoFactorAuthComponentCacheService: TwoFactorAuthComponentCacheService,
|
||||
private authService: AuthService,
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
@@ -507,8 +509,8 @@ export class TwoFactorAuthComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
private async determineDefaultSuccessRoute(): Promise<string> {
|
||||
const authType = await firstValueFrom(this.loginStrategyService.currentAuthType$);
|
||||
if (authType == AuthenticationType.Sso || authType == AuthenticationType.UserApiKey) {
|
||||
const activeAccountStatus = await firstValueFrom(this.authService.activeAccountStatus$);
|
||||
if (activeAccountStatus === AuthenticationStatus.Locked) {
|
||||
return "lock";
|
||||
}
|
||||
|
||||
|
||||
@@ -391,7 +391,7 @@ export class Utils {
|
||||
return str == null || typeof str !== "string" || str.trim() === "";
|
||||
}
|
||||
|
||||
static isNullOrEmpty(str: string): boolean {
|
||||
static isNullOrEmpty(str: string | null): boolean {
|
||||
return str == null || typeof str !== "string" || str == "";
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user