1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-07 20:24:01 +00:00

confirm key connector domain command for cli

This commit is contained in:
Maciej Zieniuk
2025-04-11 18:17:52 +01:00
parent 16017e8d8c
commit 19869e59a7
4 changed files with 114 additions and 0 deletions

View File

@@ -34,6 +34,7 @@ import { KeyConnectorService } from "@bitwarden/common/key-management/key-connec
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
@@ -44,6 +45,7 @@ import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legac
import { KdfConfigService, KeyService } from "@bitwarden/key-management";
import { NodeUtils } from "@bitwarden/node/node-utils";
import { ConfirmKeyConnectorDomainCommand } from "../../key-management/confirm-key-connector-domain.command";
import { Response } from "../../models/response";
import { MessageResponse } from "../../models/response/message.response";
@@ -76,6 +78,7 @@ export class LoginCommand {
protected logoutCallback: () => Promise<void>,
protected kdfConfigService: KdfConfigService,
protected ssoUrlService: SsoUrlService,
protected i18nService: I18nService,
) {}
async run(email: string, password: string, options: OptionValues) {
@@ -356,6 +359,25 @@ export class LoginCommand {
);
}
if (response.requiresKeyConnectorDomainConfirmation != null) {
const command = new ConfirmKeyConnectorDomainCommand(
response.userId,
response.requiresKeyConnectorDomainConfirmation.organizationId,
response.requiresKeyConnectorDomainConfirmation.keyConnectorUrl,
response.requiresKeyConnectorDomainConfirmation.kdf,
response.requiresKeyConnectorDomainConfirmation.kdfIterations,
response.requiresKeyConnectorDomainConfirmation.kdfMemory,
response.requiresKeyConnectorDomainConfirmation.kdfParallelism,
this.keyConnectorService,
this.logoutCallback,
this.i18nService,
);
const confirmResponse = await command.run();
if (!confirmResponse.success) {
return confirmResponse;
}
}
// Run full sync before handling success response or password reset flows (to get Master Password Policies)
await this.syncService.fullSync(true);

View File

@@ -0,0 +1,76 @@
import * as inquirer from "inquirer";
import { KeyConnectorService } from "@bitwarden/common/key-management/key-connector/abstractions/key-connector.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { UserId } from "@bitwarden/common/types/guid";
import { KdfType } from "@bitwarden/key-management";
import { Response } from "../models/response";
import { MessageResponse } from "../models/response/message.response";
export class ConfirmKeyConnectorDomainCommand {
constructor(
private readonly userId: UserId,
private readonly organizationId: string,
private readonly keyConnectorUrl: string,
private readonly kdf: KdfType,
private readonly kdfIterations: number,
private readonly kdfMemory: number,
private readonly kdfParallelism: number,
private keyConnectorService: KeyConnectorService,
private logout: () => Promise<void>,
private i18nService: I18nService,
) {}
async run(): Promise<Response> {
// If no interaction available, alert user to use web vault
const canInteract = process.env.BW_NOINTERACTION !== "true";
if (!canInteract) {
await this.logout();
return Response.error(
new MessageResponse(
this.i18nService.t("organizationUsingKeyConnectorConfirmLoggedOut"),
null,
),
);
}
const answer: inquirer.Answers = await inquirer.createPromptModule({ output: process.stderr })({
type: "list",
name: "confirm",
message: this.i18nService.t("confirmKeyConnectorDomain", this.keyConnectorUrl),
choices: [
{
name: this.i18nService.t("confirm"),
value: "confirmed",
},
{
name: this.i18nService.t("logOut"),
value: "cancel",
},
],
});
if (answer.confirm === "confirmed") {
try {
await this.keyConnectorService.convertNewSsoUserToKeyConnector(
this.organizationId,
this.userId,
this.keyConnectorUrl,
this.kdf,
this.kdfIterations,
this.kdfMemory,
this.kdfParallelism,
);
} catch (e) {
await this.logout();
throw e;
}
return Response.success();
} else {
await this.logout();
return Response.error(this.i18nService.t("youHaveBeenLoggedOut"));
}
}
}

View File

@@ -212,5 +212,20 @@
},
"youHaveBeenLoggedOut": {
"message": "You have been logged out."
},
"organizationUsingKeyConnectorConfirmLoggedOut": {
"message": "An organization you are a member of is using Key Connector. In order to access the vault, you must confirm the Key Connector domain now via the web vault. You have been logged out."
},
"confirmKeyConnectorDomain": {
"message": "Please confirm the domain below with your organization administrator. Key Connector domain: $KEYCONNECTORDOMAIN$",
"placeholders": {
"keyConnectorDomain": {
"content": "$1",
"example": "Key Connector domain"
}
}
},
"confirm": {
"message": "Confirm"
}
}

View File

@@ -172,6 +172,7 @@ export class Program extends BaseProgram {
async () => await this.serviceContainer.logout(),
this.serviceContainer.kdfConfigService,
this.serviceContainer.ssoUrlService,
this.serviceContainer.i18nService,
);
const response = await command.run(email, password, options);
this.processResponse(response, true);