1
0
mirror of https://github.com/bitwarden/browser synced 2026-03-01 11:01:17 +00:00

add defensive checks for forceSetPasswordReason

This commit is contained in:
rr-bw
2025-11-13 11:39:28 -08:00
parent 1536f93dd3
commit 3757c063f3
3 changed files with 79 additions and 4 deletions

View File

@@ -267,6 +267,29 @@ describe("DefaultAuthRequestAnsweringService", () => {
// Assert
expect(messagingService.send).toHaveBeenCalledTimes(1);
});
it("should NOT process pending auth requests when switching to an Unlocked user who is required to set/change their master password", async () => {
// Arrange
masterPasswordService.forceSetPasswordReason$.mockReturnValue(
of(ForceSetPasswordReason.WeakMasterPassword),
);
authStatusForSubjects.set(otherUserId, new BehaviorSubject(AuthenticationStatus.Unlocked));
pendingRequestMarkers = [{ userId: otherUserId, receivedAtMs: Date.now() }];
pendingAuthRequestsState.getAll$.mockReturnValue(of(pendingRequestMarkers));
// Act
sut.setupUnlockListenersForProcessingAuthRequests(destroy$);
activeAccount$.next({
id: otherUserId,
email: "other@example.com",
emailVerified: true,
name: "Other",
});
// Assert
await new Promise((resolve) => setTimeout(resolve, 0));
expect(messagingService.send).not.toHaveBeenCalled();
});
});
describe("authentication status transitions", () => {
@@ -380,6 +403,24 @@ describe("DefaultAuthRequestAnsweringService", () => {
expect(messagingService.send).toHaveBeenCalledTimes(2);
expect(messagingService.send).toHaveBeenCalledWith("openLoginApproval");
});
it("should NOT process pending auth requests when active account transitions to Unlocked but is required to set/change their master password", async () => {
// Arrange
masterPasswordService.forceSetPasswordReason$.mockReturnValue(
of(ForceSetPasswordReason.WeakMasterPassword),
);
activeAccountStatus$.next(AuthenticationStatus.Locked);
pendingRequestMarkers = [{ userId, receivedAtMs: Date.now() }];
pendingAuthRequestsState.getAll$.mockReturnValue(of(pendingRequestMarkers));
// Act
sut.setupUnlockListenersForProcessingAuthRequests(destroy$);
activeAccountStatus$.next(AuthenticationStatus.Unlocked);
// Assert
await new Promise((resolve) => setTimeout(resolve, 0));
expect(messagingService.send).not.toHaveBeenCalled();
});
});
describe("subscription cleanup", () => {

View File

@@ -103,6 +103,16 @@ export class DefaultAuthRequestAnsweringService implements AuthRequestAnsweringS
* approval dialog.
*/
private async processPendingAuthRequests(): Promise<void> {
const activeUserId = await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId));
// Only continue if the active user is not required to set/change their master password
const forceSetPasswordReason = await firstValueFrom(
this.masterPasswordService.forceSetPasswordReason$(activeUserId),
);
if (forceSetPasswordReason !== ForceSetPasswordReason.None) {
return;
}
// Prune any stale pending requests (older than 15 minutes)
// This comes from GlobalSettings.cs
// public TimeSpan UserRequestExpiration { get; set; } = TimeSpan.FromMinutes(15);
@@ -114,7 +124,6 @@ export class DefaultAuthRequestAnsweringService implements AuthRequestAnsweringS
(await firstValueFrom(this.pendingAuthRequestsState.getAll$())) ?? [];
if (pendingAuthRequestsInState.length > 0) {
const activeUserId = await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId));
const pendingAuthRequestsForActiveUser = pendingAuthRequestsInState.some(
(e) => e.userId === activeUserId,
);