mirror of
https://github.com/bitwarden/browser.git
synced 2025-01-27 22:11:38 +01: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:
parent
d9e65aca14
commit
bb61b3df3a
@ -12,6 +12,7 @@ import {
|
||||
TrustedDeviceUserDecryptionOption,
|
||||
UserDecryptionOptions,
|
||||
UserDecryptionOptionsServiceAbstraction,
|
||||
LoginSuccessHandlerService,
|
||||
} from "@bitwarden/auth/common";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { OrgDomainApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization-domain/org-domain-api.service.abstraction";
|
||||
@ -35,7 +36,6 @@ import { LogService } from "@bitwarden/common/platform/abstractions/log.service"
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||
import {
|
||||
AsyncActionsModule,
|
||||
ButtonModule,
|
||||
@ -117,7 +117,7 @@ export class SsoComponent implements OnInit {
|
||||
private accountService: AccountService,
|
||||
private toastService: ToastService,
|
||||
private ssoComponentService: SsoComponentService,
|
||||
private syncService: SyncService,
|
||||
private loginSuccessHandlerService: LoginSuccessHandlerService,
|
||||
) {
|
||||
environmentService.environment$.pipe(takeUntilDestroyed()).subscribe((env) => {
|
||||
this.redirectUri = env.getWebVaultUrl() + "/sso-connector.html";
|
||||
@ -378,8 +378,7 @@ export class SsoComponent implements OnInit {
|
||||
|
||||
// Everything after the 2FA check is considered a successful login
|
||||
// Just have to figure out where to send the user
|
||||
|
||||
await this.syncService.fullSync(true);
|
||||
await this.loginSuccessHandlerService.run(authResult.userId);
|
||||
|
||||
// Save off the OrgSsoIdentifier for use in the TDE flows (or elsewhere)
|
||||
// - TDE login decryption options component
|
||||
|
@ -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,
|
||||
|
@ -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) => {
|
||||
|
Loading…
Reference in New Issue
Block a user