1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-14 23:33:31 +00:00
Files
browser/libs/auth/src/common/login-strategies/user-api-login.strategy.ts
Todd Martin a049b553a6 Update decryptUserKeyWithMasterKey to requireUserId (#11560)
* Updated decryptUserKeyWithMasterKey to requireUserId

* Removed unintended extra character.

* Added dependency to LogService.

* Fixed unlock command.
2024-11-01 11:21:18 -04:00

123 lines
4.1 KiB
TypeScript

import { firstValueFrom, BehaviorSubject } from "rxjs";
import { Jsonify } from "type-fest";
import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service";
import { UserApiTokenRequest } from "@bitwarden/common/auth/models/request/identity-token/user-api-token.request";
import { IdentityTokenResponse } from "@bitwarden/common/auth/models/response/identity-token.response";
import { VaultTimeoutAction } from "@bitwarden/common/enums/vault-timeout-action.enum";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { UserId } from "@bitwarden/common/types/guid";
import { UserApiLoginCredentials } from "../models/domain/login-credentials";
import { CacheData } from "../services/login-strategies/login-strategy.state";
import { LoginStrategy, LoginStrategyData } from "./login.strategy";
export class UserApiLoginStrategyData implements LoginStrategyData {
tokenRequest: UserApiTokenRequest;
captchaBypassToken: string;
static fromJSON(obj: Jsonify<UserApiLoginStrategyData>): UserApiLoginStrategyData {
return Object.assign(new UserApiLoginStrategyData(), obj, {
tokenRequest: UserApiTokenRequest.fromJSON(obj.tokenRequest),
});
}
}
export class UserApiLoginStrategy extends LoginStrategy {
protected cache: BehaviorSubject<UserApiLoginStrategyData>;
constructor(
data: UserApiLoginStrategyData,
private environmentService: EnvironmentService,
private keyConnectorService: KeyConnectorService,
...sharedDeps: ConstructorParameters<typeof LoginStrategy>
) {
super(...sharedDeps);
this.cache = new BehaviorSubject(data);
}
override async logIn(credentials: UserApiLoginCredentials) {
const data = new UserApiLoginStrategyData();
data.tokenRequest = new UserApiTokenRequest(
credentials.clientId,
credentials.clientSecret,
await this.buildTwoFactor(),
await this.buildDeviceRequest(),
);
this.cache.next(data);
const [authResult] = await this.startLogIn();
return authResult;
}
protected override async setMasterKey(response: IdentityTokenResponse, userId: UserId) {
if (response.apiUseKeyConnector) {
const env = await firstValueFrom(this.environmentService.environment$);
const keyConnectorUrl = env.getKeyConnectorUrl();
await this.keyConnectorService.setMasterKeyFromUrl(keyConnectorUrl, userId);
}
}
protected override async setUserKey(
response: IdentityTokenResponse,
userId: UserId,
): Promise<void> {
await this.keyService.setMasterKeyEncryptedUserKey(response.key, userId);
if (response.apiUseKeyConnector) {
const masterKey = await firstValueFrom(this.masterPasswordService.masterKey$(userId));
if (masterKey) {
const userKey = await this.masterPasswordService.decryptUserKeyWithMasterKey(
masterKey,
userId,
);
await this.keyService.setUserKey(userKey, userId);
}
}
}
protected override async setPrivateKey(
response: IdentityTokenResponse,
userId: UserId,
): Promise<void> {
await this.keyService.setPrivateKey(
response.privateKey ?? (await this.createKeyPairForOldAccount(userId)),
userId,
);
}
// Overridden to save client ID and secret to token service
protected async saveAccountInformation(tokenResponse: IdentityTokenResponse): Promise<UserId> {
const userId = await super.saveAccountInformation(tokenResponse);
const vaultTimeoutAction = await firstValueFrom(
this.vaultTimeoutSettingsService.getVaultTimeoutActionByUserId$(userId),
);
const vaultTimeout = await firstValueFrom(
this.vaultTimeoutSettingsService.getVaultTimeoutByUserId$(userId),
);
const tokenRequest = this.cache.value.tokenRequest;
await this.tokenService.setClientId(
tokenRequest.clientId,
vaultTimeoutAction as VaultTimeoutAction,
vaultTimeout,
);
await this.tokenService.setClientSecret(
tokenRequest.clientSecret,
vaultTimeoutAction as VaultTimeoutAction,
vaultTimeout,
);
return userId;
}
exportCache(): CacheData {
return {
userApiKey: this.cache.value,
};
}
}