1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-22 11:13:46 +00:00

[PM-15940] Add regen to SSO login (#12643)

* Add loginSuccessHandlerService to SSO login component

* Update regen service to handle SSO login
This commit is contained in:
Thomas Avery
2025-01-08 16:41:02 -06:00
committed by GitHub
parent d9e65aca14
commit bb61b3df3a
3 changed files with 72 additions and 6 deletions

View File

@@ -153,6 +153,56 @@ describe("regenerateIfNeeded", () => {
expect(keyService.setPrivateKey).not.toHaveBeenCalled();
});
it("should not regenerate when user symmetric key is unavailable", async () => {
const mockVerificationResponse: VerifyAsymmetricKeysResponse = {
privateKeyDecryptable: true,
validPrivateKey: false,
};
setupVerificationResponse(mockVerificationResponse, sdkService);
keyService.userKey$.mockReturnValue(of(undefined as unknown as UserKey));
await sut.regenerateIfNeeded(userId);
expect(
userAsymmetricKeysRegenerationApiService.regenerateUserAsymmetricKeys,
).not.toHaveBeenCalled();
expect(keyService.setPrivateKey).not.toHaveBeenCalled();
});
it("should not regenerate when user's encrypted private key is unavailable", async () => {
const mockVerificationResponse: VerifyAsymmetricKeysResponse = {
privateKeyDecryptable: true,
validPrivateKey: false,
};
setupVerificationResponse(mockVerificationResponse, sdkService);
keyService.userEncryptedPrivateKey$.mockReturnValue(
of(undefined as unknown as EncryptedString),
);
await sut.regenerateIfNeeded(userId);
expect(
userAsymmetricKeysRegenerationApiService.regenerateUserAsymmetricKeys,
).not.toHaveBeenCalled();
expect(keyService.setPrivateKey).not.toHaveBeenCalled();
});
it("should not regenerate when user's public key is unavailable", async () => {
const mockVerificationResponse: VerifyAsymmetricKeysResponse = {
privateKeyDecryptable: true,
validPrivateKey: false,
};
setupVerificationResponse(mockVerificationResponse, sdkService);
apiService.getUserPublicKey.mockResolvedValue(undefined as any);
await sut.regenerateIfNeeded(userId);
expect(
userAsymmetricKeysRegenerationApiService.regenerateUserAsymmetricKeys,
).not.toHaveBeenCalled();
expect(keyService.setPrivateKey).not.toHaveBeenCalled();
});
it("should regenerate when private key is decryptable and invalid", async () => {
const mockVerificationResponse: VerifyAsymmetricKeysResponse = {
privateKeyDecryptable: true,

View File

@@ -49,14 +49,31 @@ export class DefaultUserAsymmetricKeysRegenerationService
}
private async shouldRegenerate(userId: UserId): Promise<boolean> {
const [userKey, userKeyEncryptedPrivateKey, publicKeyResponse] = await firstValueFrom(
const userKey = await firstValueFrom(this.keyService.userKey$(userId));
// For SSO logins from untrusted devices, the userKey will not be available, and the private key regeneration process should be skipped.
// In such cases, regeneration will occur on the following device login flow.
if (!userKey) {
this.logService.info(
"[UserAsymmetricKeyRegeneration] User symmetric key unavailable, skipping regeneration for the user.",
);
return false;
}
const [userKeyEncryptedPrivateKey, publicKeyResponse] = await firstValueFrom(
combineLatest([
this.keyService.userKey$(userId),
this.keyService.userEncryptedPrivateKey$(userId),
this.apiService.getUserPublicKey(userId),
]),
);
if (!userKeyEncryptedPrivateKey || !publicKeyResponse) {
this.logService.warning(
"[UserAsymmetricKeyRegeneration] User's asymmetric key initialization data is unavailable, skipping regeneration.",
);
return false;
}
const verificationResponse = await firstValueFrom(
this.sdkService.client$.pipe(
map((sdk) => {