mirror of
https://github.com/bitwarden/browser
synced 2026-02-28 10:33:31 +00:00
Merge remote-tracking branch 'origin' into auth/pm-18720/change-password-component-non-dialog-v3
This commit is contained in:
@@ -6,3 +6,4 @@ export * from "./user-decryption-options.service.abstraction";
|
||||
export * from "./auth-request.service.abstraction";
|
||||
export * from "./login-approval-component.service.abstraction";
|
||||
export * from "./login-success-handler.service";
|
||||
export * from "./logout.service";
|
||||
|
||||
19
libs/auth/src/common/abstractions/logout.service.ts
Normal file
19
libs/auth/src/common/abstractions/logout.service.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
|
||||
import { LogoutReason } from "../types";
|
||||
|
||||
export interface NewActiveUser {
|
||||
userId: UserId;
|
||||
authenticationStatus: AuthenticationStatus;
|
||||
}
|
||||
|
||||
export abstract class LogoutService {
|
||||
/**
|
||||
* Logs out the user.
|
||||
* @param userId The user id.
|
||||
* @param logoutReason The optional reason for logging out.
|
||||
* @returns The new active user or undefined if there isn't a new active account.
|
||||
*/
|
||||
abstract logout(userId: UserId, logoutReason?: LogoutReason): Promise<NewActiveUser | undefined>;
|
||||
}
|
||||
@@ -166,7 +166,7 @@ describe("AuthRequestLoginStrategy", () => {
|
||||
decMasterKeyHash,
|
||||
mockUserId,
|
||||
);
|
||||
expect(keyService.setMasterKeyEncryptedUserKey).toHaveBeenCalledWith(
|
||||
expect(masterPasswordService.mock.setMasterKeyEncryptedUserKey).toHaveBeenCalledWith(
|
||||
tokenResponse.key,
|
||||
mockUserId,
|
||||
);
|
||||
@@ -194,7 +194,7 @@ describe("AuthRequestLoginStrategy", () => {
|
||||
expect(masterPasswordService.mock.setMasterKeyHash).not.toHaveBeenCalled();
|
||||
|
||||
// setMasterKeyEncryptedUserKey, setUserKey, and setPrivateKey should still be called
|
||||
expect(keyService.setMasterKeyEncryptedUserKey).toHaveBeenCalledWith(
|
||||
expect(masterPasswordService.mock.setMasterKeyEncryptedUserKey).toHaveBeenCalledWith(
|
||||
tokenResponse.key,
|
||||
mockUserId,
|
||||
);
|
||||
|
||||
@@ -95,7 +95,9 @@ export class AuthRequestLoginStrategy extends LoginStrategy {
|
||||
const authRequestCredentials = this.cache.value.authRequestCredentials;
|
||||
// User now may or may not have a master password
|
||||
// but set the master key encrypted user key if it exists regardless
|
||||
await this.keyService.setMasterKeyEncryptedUserKey(response.key, userId);
|
||||
if (response.key) {
|
||||
await this.masterPasswordService.setMasterKeyEncryptedUserKey(response.key, userId);
|
||||
}
|
||||
|
||||
if (authRequestCredentials.decryptedUserKey) {
|
||||
await this.keyService.setUserKey(authRequestCredentials.decryptedUserKey, userId);
|
||||
|
||||
@@ -202,7 +202,10 @@ describe("PasswordLoginStrategy", () => {
|
||||
localHashedPassword,
|
||||
userId,
|
||||
);
|
||||
expect(keyService.setMasterKeyEncryptedUserKey).toHaveBeenCalledWith(tokenResponse.key, userId);
|
||||
expect(masterPasswordService.mock.setMasterKeyEncryptedUserKey).toHaveBeenCalledWith(
|
||||
tokenResponse.key,
|
||||
userId,
|
||||
);
|
||||
expect(keyService.setUserKey).toHaveBeenCalledWith(userKey, userId);
|
||||
expect(keyService.setPrivateKey).toHaveBeenCalledWith(tokenResponse.privateKey, userId);
|
||||
});
|
||||
|
||||
@@ -127,7 +127,10 @@ export class PasswordLoginStrategy extends LoginStrategy {
|
||||
if (this.encryptionKeyMigrationRequired(response)) {
|
||||
return;
|
||||
}
|
||||
await this.keyService.setMasterKeyEncryptedUserKey(response.key, userId);
|
||||
|
||||
if (response.key) {
|
||||
await this.masterPasswordService.setMasterKeyEncryptedUserKey(response.key, userId);
|
||||
}
|
||||
|
||||
const masterKey = await firstValueFrom(this.masterPasswordService.masterKey$(userId));
|
||||
if (masterKey) {
|
||||
|
||||
@@ -196,8 +196,11 @@ describe("SsoLoginStrategy", () => {
|
||||
await ssoLoginStrategy.logIn(credentials);
|
||||
|
||||
// Assert
|
||||
expect(keyService.setMasterKeyEncryptedUserKey).toHaveBeenCalledTimes(1);
|
||||
expect(keyService.setMasterKeyEncryptedUserKey).toHaveBeenCalledWith(tokenResponse.key, userId);
|
||||
expect(masterPasswordService.mock.setMasterKeyEncryptedUserKey).toHaveBeenCalledTimes(1);
|
||||
expect(masterPasswordService.mock.setMasterKeyEncryptedUserKey).toHaveBeenCalledWith(
|
||||
tokenResponse.key,
|
||||
userId,
|
||||
);
|
||||
});
|
||||
|
||||
describe("Trusted Device Decryption", () => {
|
||||
|
||||
@@ -185,7 +185,10 @@ export class SsoLoginStrategy extends LoginStrategy {
|
||||
|
||||
if (masterKeyEncryptedUserKey) {
|
||||
// set the master key encrypted user key if it exists
|
||||
await this.keyService.setMasterKeyEncryptedUserKey(masterKeyEncryptedUserKey, userId);
|
||||
await this.masterPasswordService.setMasterKeyEncryptedUserKey(
|
||||
masterKeyEncryptedUserKey,
|
||||
userId,
|
||||
);
|
||||
}
|
||||
|
||||
const userDecryptionOptions = tokenResponse?.userDecryptionOptions;
|
||||
|
||||
@@ -176,7 +176,10 @@ describe("UserApiLoginStrategy", () => {
|
||||
|
||||
await apiLogInStrategy.logIn(credentials);
|
||||
|
||||
expect(keyService.setMasterKeyEncryptedUserKey).toHaveBeenCalledWith(tokenResponse.key, userId);
|
||||
expect(masterPasswordService.mock.setMasterKeyEncryptedUserKey).toHaveBeenCalledWith(
|
||||
tokenResponse.key,
|
||||
userId,
|
||||
);
|
||||
expect(keyService.setPrivateKey).toHaveBeenCalledWith(tokenResponse.privateKey, userId);
|
||||
});
|
||||
|
||||
|
||||
@@ -63,7 +63,9 @@ export class UserApiLoginStrategy extends LoginStrategy {
|
||||
response: IdentityTokenResponse,
|
||||
userId: UserId,
|
||||
): Promise<void> {
|
||||
await this.keyService.setMasterKeyEncryptedUserKey(response.key, userId);
|
||||
if (response.key) {
|
||||
await this.masterPasswordService.setMasterKeyEncryptedUserKey(response.key, userId);
|
||||
}
|
||||
|
||||
if (response.apiUseKeyConnector) {
|
||||
const masterKey = await firstValueFrom(this.masterPasswordService.masterKey$(userId));
|
||||
|
||||
@@ -237,8 +237,8 @@ describe("WebAuthnLoginStrategy", () => {
|
||||
|
||||
// Assert
|
||||
// Master key encrypted user key should be set
|
||||
expect(keyService.setMasterKeyEncryptedUserKey).toHaveBeenCalledTimes(1);
|
||||
expect(keyService.setMasterKeyEncryptedUserKey).toHaveBeenCalledWith(
|
||||
expect(masterPasswordService.mock.setMasterKeyEncryptedUserKey).toHaveBeenCalledTimes(1);
|
||||
expect(masterPasswordService.mock.setMasterKeyEncryptedUserKey).toHaveBeenCalledWith(
|
||||
idTokenResponse.key,
|
||||
userId,
|
||||
);
|
||||
|
||||
@@ -66,7 +66,10 @@ export class WebAuthnLoginStrategy extends LoginStrategy {
|
||||
|
||||
if (masterKeyEncryptedUserKey) {
|
||||
// set the master key encrypted user key if it exists
|
||||
await this.keyService.setMasterKeyEncryptedUserKey(masterKeyEncryptedUserKey, userId);
|
||||
await this.masterPasswordService.setMasterKeyEncryptedUserKey(
|
||||
masterKeyEncryptedUserKey,
|
||||
userId,
|
||||
);
|
||||
}
|
||||
|
||||
const userDecryptionOptions = idTokenResponse?.userDecryptionOptions;
|
||||
|
||||
@@ -7,3 +7,4 @@ export * from "./auth-request/auth-request-api.service";
|
||||
export * from "./accounts/lock.service";
|
||||
export * from "./login-success-handler/default-login-success-handler.service";
|
||||
export * from "./sso-redirect/sso-url.service";
|
||||
export * from "./logout/default-logout.service";
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import { MockProxy, mock } from "jest-mock-extended";
|
||||
|
||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
|
||||
import { LogoutService } from "../../abstractions";
|
||||
import { LogoutReason } from "../../types";
|
||||
|
||||
import { DefaultLogoutService } from "./default-logout.service";
|
||||
|
||||
describe("DefaultLogoutService", () => {
|
||||
let logoutService: LogoutService;
|
||||
let messagingService: MockProxy<MessagingService>;
|
||||
|
||||
beforeEach(() => {
|
||||
messagingService = mock<MessagingService>();
|
||||
logoutService = new DefaultLogoutService(messagingService);
|
||||
});
|
||||
|
||||
it("instantiates", () => {
|
||||
expect(logoutService).not.toBeFalsy();
|
||||
});
|
||||
|
||||
describe("logout", () => {
|
||||
it("sends logout message without a logout reason when not provided", async () => {
|
||||
const userId = "1" as UserId;
|
||||
|
||||
await logoutService.logout(userId);
|
||||
|
||||
expect(messagingService.send).toHaveBeenCalledWith("logout", { userId });
|
||||
});
|
||||
|
||||
it("sends logout message with a logout reason when provided", async () => {
|
||||
const userId = "1" as UserId;
|
||||
const logoutReason: LogoutReason = "vaultTimeout";
|
||||
await logoutService.logout(userId, logoutReason);
|
||||
expect(messagingService.send).toHaveBeenCalledWith("logout", { userId, logoutReason });
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,14 @@
|
||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
|
||||
import { LogoutService, NewActiveUser } from "../../abstractions/logout.service";
|
||||
import { LogoutReason } from "../../types";
|
||||
|
||||
export class DefaultLogoutService implements LogoutService {
|
||||
constructor(protected messagingService: MessagingService) {}
|
||||
async logout(userId: UserId, logoutReason?: LogoutReason): Promise<NewActiveUser | undefined> {
|
||||
this.messagingService.send("logout", { userId, logoutReason });
|
||||
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user