mirror of
https://github.com/bitwarden/browser
synced 2026-02-16 16:59:30 +00:00
* Implement automatic kdf upgrades * Fix kdf config not being updated * Update legacy kdf state on master password unlock sync * Fix cli build * Fix * Deduplicate prompts * Fix dismiss time * Fix default kdf setting * Fix build * Undo changes * Fix test * Fix prettier * Fix test * Update libs/angular/src/key-management/encrypted-migration/encrypted-migrations-scheduler.service.ts Co-authored-by: Maciej Zieniuk <167752252+mzieniukbw@users.noreply.github.com> * Update libs/common/src/key-management/master-password/abstractions/master-password.service.abstraction.ts Co-authored-by: Maciej Zieniuk <167752252+mzieniukbw@users.noreply.github.com> * Update libs/angular/src/key-management/encrypted-migration/encrypted-migrations-scheduler.service.ts Co-authored-by: Maciej Zieniuk <167752252+mzieniukbw@users.noreply.github.com> * Only sync when there is at least one migration * Relative imports * Add tech debt comment * Resolve inconsistent prefix * Clean up * Update docs * Use default PBKDF2 iteratinos instead of custom threshold * Undo type check * Fix build * Add comment * Cleanup * Cleanup * Address component feedback * Use isnullorwhitespace * Fix tests * Allow migration only on vault * Fix tests * Run prettier * Fix tests * Prevent await race condition * Fix min and default values in kdf migration * Run sync only when a migration was run * Update libs/common/src/key-management/encrypted-migrator/default-encrypted-migrator.ts Co-authored-by: Maciej Zieniuk <167752252+mzieniukbw@users.noreply.github.com> * Fix link not being blue * Fix later button on browser --------- Co-authored-by: Maciej Zieniuk <167752252+mzieniukbw@users.noreply.github.com>
160 lines
6.3 KiB
TypeScript
160 lines
6.3 KiB
TypeScript
// FIXME: Update this file to be type safe and remove this and next line
|
|
// @ts-strict-ignore
|
|
import { firstValueFrom } from "rxjs";
|
|
|
|
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
|
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
|
import { VerificationType } from "@bitwarden/common/auth/enums/verification-type";
|
|
import { MasterPasswordVerification } from "@bitwarden/common/auth/types/verification";
|
|
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
|
import { CryptoFunctionService } from "@bitwarden/common/key-management/crypto/abstractions/crypto-function.service";
|
|
import { EncryptedMigrator } from "@bitwarden/common/key-management/encrypted-migrator/encrypted-migrator.abstraction";
|
|
import { KeyConnectorService } from "@bitwarden/common/key-management/key-connector/abstractions/key-connector.service";
|
|
import { MasterPasswordUnlockService } from "@bitwarden/common/key-management/master-password/abstractions/master-password-unlock.service";
|
|
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/key-management/master-password/abstractions/master-password.service.abstraction";
|
|
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
|
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
|
import { ConsoleLogService } from "@bitwarden/common/platform/services/console-log.service";
|
|
import { MasterKey } from "@bitwarden/common/types/key";
|
|
import { KeyService } from "@bitwarden/key-management";
|
|
|
|
import { Response } from "../../models/response";
|
|
import { MessageResponse } from "../../models/response/message.response";
|
|
import { I18nService } from "../../platform/services/i18n.service";
|
|
import { CliUtils } from "../../utils";
|
|
import { ConvertToKeyConnectorCommand } from "../convert-to-key-connector.command";
|
|
|
|
export class UnlockCommand {
|
|
constructor(
|
|
private accountService: AccountService,
|
|
private masterPasswordService: InternalMasterPasswordServiceAbstraction,
|
|
private keyService: KeyService,
|
|
private userVerificationService: UserVerificationService,
|
|
private cryptoFunctionService: CryptoFunctionService,
|
|
private logService: ConsoleLogService,
|
|
private keyConnectorService: KeyConnectorService,
|
|
private environmentService: EnvironmentService,
|
|
private organizationApiService: OrganizationApiServiceAbstraction,
|
|
private logout: () => Promise<void>,
|
|
private i18nService: I18nService,
|
|
private encryptedMigrator: EncryptedMigrator,
|
|
private masterPasswordUnlockService: MasterPasswordUnlockService,
|
|
private configService: ConfigService,
|
|
) {}
|
|
|
|
async run(password: string, cmdOptions: Record<string, any>) {
|
|
const normalizedOptions = new Options(cmdOptions);
|
|
const passwordResult = await CliUtils.getPassword(password, normalizedOptions, this.logService);
|
|
|
|
if (passwordResult instanceof Response) {
|
|
return passwordResult;
|
|
} else {
|
|
password = passwordResult;
|
|
}
|
|
|
|
await this.setNewSessionKey();
|
|
const activeAccount = await firstValueFrom(this.accountService.activeAccount$);
|
|
if (activeAccount == null) {
|
|
return Response.error("No active account found");
|
|
}
|
|
const userId = activeAccount.id;
|
|
|
|
if (
|
|
await firstValueFrom(
|
|
this.configService.getFeatureFlag$(FeatureFlag.UnlockWithMasterPasswordUnlockData),
|
|
)
|
|
) {
|
|
try {
|
|
const userKey = await this.masterPasswordUnlockService.unlockWithMasterPassword(
|
|
password,
|
|
userId,
|
|
);
|
|
|
|
await this.keyService.setUserKey(userKey, userId);
|
|
} catch (e) {
|
|
return Response.error(e.message);
|
|
}
|
|
} else {
|
|
const email = activeAccount.email;
|
|
const verification = {
|
|
type: VerificationType.MasterPassword,
|
|
secret: password,
|
|
} as MasterPasswordVerification;
|
|
|
|
let masterKey: MasterKey;
|
|
try {
|
|
const response = await this.userVerificationService.verifyUserByMasterPassword(
|
|
verification,
|
|
userId,
|
|
email,
|
|
);
|
|
masterKey = response.masterKey;
|
|
} catch (e) {
|
|
// verification failure throws
|
|
return Response.error(e.message);
|
|
}
|
|
|
|
const userKey = await this.masterPasswordService.decryptUserKeyWithMasterKey(
|
|
masterKey,
|
|
userId,
|
|
);
|
|
await this.keyService.setUserKey(userKey, userId);
|
|
}
|
|
|
|
if (await firstValueFrom(this.keyConnectorService.convertAccountRequired$)) {
|
|
const convertToKeyConnectorCommand = new ConvertToKeyConnectorCommand(
|
|
userId,
|
|
this.keyConnectorService,
|
|
this.environmentService,
|
|
this.organizationApiService,
|
|
this.logout,
|
|
this.i18nService,
|
|
);
|
|
const convertResponse = await convertToKeyConnectorCommand.run();
|
|
if (!convertResponse.success) {
|
|
return convertResponse;
|
|
}
|
|
}
|
|
|
|
await this.encryptedMigrator.runMigrations(userId, password);
|
|
|
|
return this.successResponse();
|
|
}
|
|
|
|
private async setNewSessionKey() {
|
|
const key = await this.cryptoFunctionService.randomBytes(64);
|
|
process.env.BW_SESSION = Utils.fromBufferToB64(key);
|
|
}
|
|
|
|
private async successResponse() {
|
|
const res = new MessageResponse(
|
|
"Your vault is now unlocked!",
|
|
"\n" +
|
|
"To unlock your vault, set your session key to the `BW_SESSION` environment variable. ex:\n" +
|
|
'$ export BW_SESSION="' +
|
|
process.env.BW_SESSION +
|
|
'"\n' +
|
|
'> $env:BW_SESSION="' +
|
|
process.env.BW_SESSION +
|
|
'"\n\n' +
|
|
"You can also pass the session key to any command with the `--session` option. ex:\n" +
|
|
"$ bw list items --session " +
|
|
process.env.BW_SESSION,
|
|
);
|
|
res.raw = process.env.BW_SESSION;
|
|
return Response.success(res);
|
|
}
|
|
}
|
|
|
|
class Options {
|
|
passwordEnv: string;
|
|
passwordFile: string;
|
|
|
|
constructor(passedOptions: Record<string, any>) {
|
|
this.passwordEnv = passedOptions?.passwordenv || passedOptions?.passwordEnv;
|
|
this.passwordFile = passedOptions?.passwordfile || passedOptions?.passwordFile;
|
|
}
|
|
}
|