diff --git a/apps/web/src/locales/en/messages.json b/apps/web/src/locales/en/messages.json
index cedd3fc3596..a3dc4ac455a 100644
--- a/apps/web/src/locales/en/messages.json
+++ b/apps/web/src/locales/en/messages.json
@@ -10567,5 +10567,8 @@
},
"cannotCreateCollection": {
"message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections."
+ },
+ "confirmKeyConnectorDomain": {
+ "message": "Confirm Key Connector domain"
}
}
diff --git a/libs/angular/src/auth/components/sso.component.ts b/libs/angular/src/auth/components/sso.component.ts
index 8c19e1d7e11..da3fc0c550b 100644
--- a/libs/angular/src/auth/components/sso.component.ts
+++ b/libs/angular/src/auth/components/sso.component.ts
@@ -222,6 +222,7 @@ export class SsoComponent implements OnInit {
}
if (authResult.requiresKeyConnectorDomainConfirmation != null) {
+ this.logService.debug("Key Connector domain confirmation required");
return await this.handleKeyConnectorDomainConfirmation(
authResult.requiresKeyConnectorDomainConfirmation,
authResult.userId,
@@ -436,11 +437,12 @@ export class SsoComponent implements OnInit {
kdfMemory?: number;
kdfParallelism?: number;
keyConnectorUrl: string;
+ organizationId: string;
},
userId: UserId,
) {
await this.router.navigate(["confirm-key-connector-domain"], {
- state: {
+ queryParams: {
...request,
userId,
},
diff --git a/libs/auth/src/angular/sso/sso.component.ts b/libs/auth/src/angular/sso/sso.component.ts
index 5d3fd689dd6..af1cb0f0428 100644
--- a/libs/auth/src/angular/sso/sso.component.ts
+++ b/libs/auth/src/angular/sso/sso.component.ts
@@ -36,6 +36,7 @@ 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 { UserId } from "@bitwarden/common/types/guid";
import {
AsyncActionsModule,
ButtonModule,
@@ -46,6 +47,7 @@ import {
ToastService,
} from "@bitwarden/components";
import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy";
+import { KdfType } from "@bitwarden/key-management";
import { SsoClientType, SsoComponentService } from "./sso-component.service";
@@ -433,6 +435,14 @@ export class SsoComponent implements OnInit {
return await this.handleTwoFactorRequired(orgSsoIdentifier);
}
+ if (authResult.requiresKeyConnectorDomainConfirmation != null) {
+ this.logService.warning("Key Connector domain confirmation required");
+ return await this.handleKeyConnectorDomainConfirmation(
+ authResult.requiresKeyConnectorDomainConfirmation,
+ authResult.userId,
+ );
+ }
+
// Everything after the 2FA check is considered a successful login
// Just have to figure out where to send the user
await this.loginSuccessHandlerService.run(authResult.userId);
@@ -638,4 +648,23 @@ export class SsoComponent implements OnInit {
this.identifierFormControl.setValue(storedIdentifier);
}
}
+
+ private async handleKeyConnectorDomainConfirmation(
+ request: {
+ kdf: KdfType;
+ kdfIterations: number;
+ kdfMemory?: number;
+ kdfParallelism?: number;
+ keyConnectorUrl: string;
+ organizationId: string;
+ },
+ userId: UserId,
+ ) {
+ await this.router.navigate(["confirm-key-connector-domain"], {
+ queryParams: {
+ ...request,
+ userId,
+ },
+ });
+ }
}
diff --git a/libs/key-management-ui/src/key-connector/confirm-key-connector-domain.component.html b/libs/key-management-ui/src/key-connector/confirm-key-connector-domain.component.html
index 7c89b545c5a..902df06cc0f 100644
--- a/libs/key-management-ui/src/key-connector/confirm-key-connector-domain.component.html
+++ b/libs/key-management-ui/src/key-connector/confirm-key-connector-domain.component.html
@@ -1 +1,32 @@
-
+@if (loading) {
+
+
+
+} @else {
+
+
{{ "confirmKeyConnectorDomain" | i18n }}.
+
{{ "keyConnectorDomain" | i18n }}:
+
{{ keyConnectorUrl }}
+
+
+
+
+}
diff --git a/libs/key-management-ui/src/key-connector/confirm-key-connector-domain.component.ts b/libs/key-management-ui/src/key-connector/confirm-key-connector-domain.component.ts
index ef244015986..ac1cadbe4a5 100644
--- a/libs/key-management-ui/src/key-connector/confirm-key-connector-domain.component.ts
+++ b/libs/key-management-ui/src/key-connector/confirm-key-connector-domain.component.ts
@@ -1,18 +1,14 @@
import { CommonModule } from "@angular/common";
-import { Component, OnDestroy, OnInit } from "@angular/core";
-import { ReactiveFormsModule } from "@angular/forms";
-import { ActivatedRoute, Router } from "@angular/router";
-import { Subject } from "rxjs";
+import { Component, OnInit } from "@angular/core";
+import { ActivatedRoute, Router, RouterModule } from "@angular/router";
import { JslibModule } from "@bitwarden/angular/jslib.module";
-import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { KeyConnectorService } from "@bitwarden/common/key-management/key-connector/abstractions/key-connector.service";
-import {
- AsyncActionsModule,
- ButtonModule,
- FormFieldModule,
- IconButtonModule,
-} from "@bitwarden/components";
+import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
+import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
+import { UserId } from "@bitwarden/common/types/guid";
+import { AsyncActionsModule, ButtonModule, IconButtonModule } from "@bitwarden/components";
+import { KdfType } from "@bitwarden/key-management";
@Component({
selector: "confirm-key-connector-domain",
@@ -21,38 +17,92 @@ import {
imports: [
CommonModule,
JslibModule,
- ReactiveFormsModule,
ButtonModule,
- FormFieldModule,
AsyncActionsModule,
IconButtonModule,
+ RouterModule,
],
})
-export class ConfirmKeyConnectorDomainComponent implements OnInit, OnDestroy {
- private destroy$ = new Subject();
+export class ConfirmKeyConnectorDomainComponent implements OnInit {
+ protected loading = true;
+ protected keyConnectorUrl!: string;
+ private userId!: UserId;
+ private organizationId!: string;
+ private kdf!: KdfType;
+ private kdfIterations!: number;
+ private kdfMemory?: number;
+ private kdfParallelism?: number;
constructor(
private route: ActivatedRoute,
private router: Router,
- private accountService: AccountService,
+ private logService: LogService,
private keyConnectorService: KeyConnectorService,
- ) {
- // TODO
- // this.accountService.activeAccount$.pipe(takeUntil(this.destroy$)).subscribe((account) => {
- // console.log("[confirm-key-connector-domain]: account", account);
- // });
- }
+ private messagingService: MessagingService,
+ ) {}
- ngOnInit() {
- throw new Error("Method not implemented.");
- }
+ async ngOnInit() {
+ const userId = this.route.snapshot.queryParamMap.get("userId") as UserId | null;
+ const organizationId = this.route.snapshot.queryParamMap.get("organizationId");
+ const keyConnectorUrl = this.route.snapshot.queryParamMap.get("keyConnectorUrl");
+ const kdf = Number.parseInt(this.route.snapshot.queryParamMap.get("kdf") ?? "");
+ const kdfIterations = Number.parseInt(
+ this.route.snapshot.queryParamMap.get("kdfIterations") ?? "",
+ );
+ const kdfMemory = Number.parseInt(this.route.snapshot.queryParamMap.get("kdfMemory") ?? "");
+ const kdfParallelism = Number.parseInt(
+ this.route.snapshot.queryParamMap.get("kdfParallelism") ?? "",
+ );
- ngOnDestroy() {
- this.destroy$.next();
- this.destroy$.complete();
+ this.logService.info(
+ "[confirm-key-connector-domain] userId %s, organizationId %s, keyConnectorUrl %s, kdf %s, kdfIterations %s, kdfMemory %s, kdfParallelism %s",
+ userId,
+ organizationId,
+ keyConnectorUrl,
+ KdfType[kdf],
+ kdfIterations,
+ kdfMemory,
+ kdfParallelism,
+ );
+
+ if (
+ userId == null ||
+ organizationId == null ||
+ keyConnectorUrl == null ||
+ Number.isNaN(kdf) ||
+ !kdfIterations
+ ) {
+ this.logService.info("[confirm-key-connector-domain] missing required parameters");
+ this.messagingService.send("logout");
+ return;
+ }
+
+ this.keyConnectorUrl = keyConnectorUrl;
+ this.userId = userId;
+ this.organizationId = organizationId;
+ this.kdf = kdf;
+ this.kdfIterations = kdfIterations;
+ this.kdfMemory = kdfMemory ? kdfMemory : undefined;
+ this.kdfParallelism = kdfParallelism ? kdfParallelism : undefined;
+
+ this.loading = false;
}
confirm = async () => {
- // this.keyConnectorService.convertNewSsoUserToKeyConnector();
+ await this.keyConnectorService.convertNewSsoUserToKeyConnector(
+ this.organizationId,
+ this.userId,
+ this.keyConnectorUrl,
+ this.kdf,
+ this.kdfIterations,
+ this.kdfMemory,
+ this.kdfParallelism,
+ );
+
+ this.messagingService.send("loggedIn");
+ };
+
+ cancel = async () => {
+ this.messagingService.send("logout");
};
}