mirror of
https://github.com/bitwarden/browser.git
synced 2024-12-22 16:29:09 +01:00
[AC-1145] Add trusted devices option to encryption settings on sso config (#5383)
* [AC-1145] Add TDE feature flag * [AC-1145] Update sso-config to use new member decryption type and remove keyConnectorEnabled * [AC-1145] Add new TDE option to SSO config form and update to CL radio buttons * [AC-1145] Update checkboxes to CL checkboxes * [AC-1145] Fix messages.json warning * [AC-1145] Update to new form async actions * [AC-1145] Modify key connector option display logic to check for TDE feature flag * [AC-1145] Remove obsolete app-checkbox component * [AC-1145] Update TDE option description to refer to master password reset policy
This commit is contained in:
parent
a64cecff68
commit
ab4d8df2ae
@ -5218,9 +5218,6 @@
|
||||
"message": "to require all members to log in with SSO.",
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Use the require single-sign-on authentication policy to require all members to log in with SSO.'"
|
||||
},
|
||||
"ssoPolicyHelpKeyConnector": {
|
||||
"message": "The require SSO authentication and single organization policies are required to set up Key Connector decryption."
|
||||
},
|
||||
"memberDecryptionOption": {
|
||||
"message": "Member decryption options"
|
||||
},
|
||||
@ -5230,8 +5227,17 @@
|
||||
"keyConnector": {
|
||||
"message": "Key Connector"
|
||||
},
|
||||
"memberDecryptionKeyConnectorDesc": {
|
||||
"message": "Connect login with SSO to your self-hosted decryption key server. Using this option, members won’t need to use their master passwords to decrypt vault data. Contact Bitwarden Support for set up assistance."
|
||||
"memberDecryptionKeyConnectorDescStart": {
|
||||
"message": "Connect login with SSO to your self-hosted decryption key server. Using this option, members won’t need to use their master passwords to decrypt vault data. The",
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Connect login with SSO to your self-hosted decryption key server. Using this option, members won’t need to use their master passwords to decrypt vault data. The require SSO authentication and single organization policies are required to set up Key Connector decryption. Contact Bitwarden Support for set up assistance.'"
|
||||
},
|
||||
"memberDecryptionKeyConnectorDescLink": {
|
||||
"message": "require SSO authentication and single organization policies",
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Connect login with SSO to your self-hosted decryption key server. Using this option, members won’t need to use their master passwords to decrypt vault data. The require SSO authentication and single organization policies are required to set up Key Connector decryption. Contact Bitwarden Support for set up assistance.'"
|
||||
},
|
||||
"memberDecryptionKeyConnectorDescEnd": {
|
||||
"message": "are required to set up Key Connector decryption. Contact Bitwarden Support for set up assistance.",
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Connect login with SSO to your self-hosted decryption key server. Using this option, members won’t need to use their master passwords to decrypt vault data. The require SSO authentication and single organization policies are required to set up Key Connector decryption. Contact Bitwarden Support for set up assistance.'"
|
||||
},
|
||||
"keyConnectorPolicyRestriction": {
|
||||
"message": "\"Login with SSO and Key Connector Decryption\" is activated. This policy will only apply to owners and admins."
|
||||
@ -5535,7 +5541,7 @@
|
||||
},
|
||||
"lastSync": {
|
||||
"message": "Last sync",
|
||||
"Description": "Used as a prefix to indicate the last time a sync occured. Example \"Last sync 1968-11-16 00:00:00\""
|
||||
"description": "Used as a prefix to indicate the last time a sync occured. Example \"Last sync 1968-11-16 00:00:00\""
|
||||
},
|
||||
"sponsorshipsSynced": {
|
||||
"message": "Self-hosted sponsorships synced."
|
||||
@ -6781,5 +6787,20 @@
|
||||
},
|
||||
"updateKdfSettings": {
|
||||
"message": "Update KDF settings"
|
||||
},
|
||||
"trustedDeviceEncryption": {
|
||||
"message": "Trusted device encryption"
|
||||
},
|
||||
"memberDecryptionTdeDescStart": {
|
||||
"message": "Once authenticated, members will decrypt vault data using a key stored on their device. The",
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Once authenticated, members will decrypt vault data using a key stored on their device. The master password reset policy with automatic enrollment will turn on when this option is used.'"
|
||||
},
|
||||
"memberDecryptionTdeDescLink": {
|
||||
"message": "master password reset policy",
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Once authenticated, members will decrypt vault data using a key stored on their device. The master password reset policy with automatic enrollment will turn on when this option is used.'"
|
||||
},
|
||||
"memberDecryptionTdeDescEnd": {
|
||||
"message": "with automatic enrollment will turn on when this option is used.",
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Once authenticated, members will decrypt vault data using a key stored on their device. The master password reset policy with automatic enrollment will turn on when this option is used.'"
|
||||
}
|
||||
}
|
||||
|
@ -1,63 +0,0 @@
|
||||
import { Directive, Input, OnInit, Self } from "@angular/core";
|
||||
import { ControlValueAccessor, UntypedFormControl, NgControl, Validators } from "@angular/forms";
|
||||
|
||||
/** For use in the SSO Config Form only - will be deprecated by the Component Library */
|
||||
@Directive()
|
||||
export abstract class BaseCvaComponent implements ControlValueAccessor, OnInit {
|
||||
get describedById() {
|
||||
return this.showDescribedBy ? this.controlId + "Desc" : null;
|
||||
}
|
||||
|
||||
get showDescribedBy() {
|
||||
return this.helperText != null || this.controlDir.control.hasError("required");
|
||||
}
|
||||
|
||||
get isRequired() {
|
||||
return this.controlDir.control.hasValidator(Validators.required);
|
||||
}
|
||||
|
||||
@Input() label: string;
|
||||
@Input() controlId: string;
|
||||
@Input() helperText: string;
|
||||
|
||||
internalControl = new UntypedFormControl("");
|
||||
|
||||
protected onChange: any;
|
||||
protected onTouched: any;
|
||||
|
||||
constructor(@Self() public controlDir: NgControl) {
|
||||
this.controlDir.valueAccessor = this;
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.internalControl.valueChanges.subscribe(this.onValueChangesInternal);
|
||||
}
|
||||
|
||||
onBlurInternal() {
|
||||
this.onTouched();
|
||||
}
|
||||
|
||||
// CVA interfaces
|
||||
writeValue(value: string) {
|
||||
this.internalControl.setValue(value);
|
||||
}
|
||||
|
||||
registerOnChange(fn: any) {
|
||||
this.onChange = fn;
|
||||
}
|
||||
|
||||
registerOnTouched(fn: any) {
|
||||
this.onTouched = fn;
|
||||
}
|
||||
|
||||
setDisabledState(isDisabled: boolean) {
|
||||
if (isDisabled) {
|
||||
this.internalControl.disable();
|
||||
} else {
|
||||
this.internalControl.enable();
|
||||
}
|
||||
}
|
||||
|
||||
protected onValueChangesInternal: any = (value: string) => this.onChange(value);
|
||||
// End CVA interfaces
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
<div class="form-group">
|
||||
<div class="form-check">
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="checkbox"
|
||||
[attr.id]="controlId"
|
||||
[attr.aria-describedby]="describedById"
|
||||
[formControl]="internalControl"
|
||||
(blur)="onBlurInternal()"
|
||||
/>
|
||||
<label class="form-check-label" [attr.for]="controlId">{{ label }}</label>
|
||||
</div>
|
||||
<small *ngIf="showDescribedBy" [attr.id]="describedById" class="form-text text-muted">{{
|
||||
helperText
|
||||
}}</small>
|
||||
</div>
|
@ -1,10 +0,0 @@
|
||||
import { Component } from "@angular/core";
|
||||
|
||||
import { BaseCvaComponent } from "./base-cva.component";
|
||||
|
||||
/** For use in the SSO Config Form only - will be deprecated by the Component Library */
|
||||
@Component({
|
||||
selector: "app-input-checkbox",
|
||||
templateUrl: "input-checkbox.component.html",
|
||||
})
|
||||
export class InputCheckboxComponent extends BaseCvaComponent {}
|
@ -4,7 +4,6 @@ import { SharedModule } from "@bitwarden/web-vault/app/shared/shared.module";
|
||||
|
||||
import { SsoComponent } from "../../auth/sso/sso.component";
|
||||
|
||||
import { InputCheckboxComponent } from "./components/input-checkbox.component";
|
||||
import { DomainAddEditDialogComponent } from "./manage/domain-verification/domain-add-edit-dialog/domain-add-edit-dialog.component";
|
||||
import { DomainVerificationComponent } from "./manage/domain-verification/domain-verification.component";
|
||||
import { ScimComponent } from "./manage/scim.component";
|
||||
@ -13,7 +12,6 @@ import { OrganizationsRoutingModule } from "./organizations-routing.module";
|
||||
@NgModule({
|
||||
imports: [SharedModule, OrganizationsRoutingModule],
|
||||
declarations: [
|
||||
InputCheckboxComponent,
|
||||
SsoComponent,
|
||||
ScimComponent,
|
||||
DomainVerificationComponent,
|
||||
|
@ -8,32 +8,24 @@
|
||||
title="{{ 'loading' | i18n }}"
|
||||
aria-hidden="true"
|
||||
></i>
|
||||
<span class="sr-only">{{ "loading" | i18n }}</span>
|
||||
<span class="tw-sr-only">{{ "loading" | i18n }}</span>
|
||||
</ng-container>
|
||||
|
||||
<form
|
||||
#form
|
||||
(ngSubmit)="submit()"
|
||||
[formGroup]="ssoConfigForm"
|
||||
[appApiAction]="formPromise"
|
||||
*ngIf="!loading"
|
||||
>
|
||||
<form [formGroup]="ssoConfigForm" [bitSubmit]="submit" *ngIf="!loading">
|
||||
<p>
|
||||
{{ "ssoPolicyHelpStart" | i18n }}
|
||||
<a routerLink="../policies">{{ "ssoPolicyHelpLink" | i18n }}</a>
|
||||
{{ "ssoPolicyHelpEnd" | i18n }}
|
||||
<br />
|
||||
{{ "ssoPolicyHelpKeyConnector" | i18n }}
|
||||
</p>
|
||||
|
||||
<!-- Root form -->
|
||||
<ng-container>
|
||||
<app-input-checkbox
|
||||
controlId="enabled"
|
||||
formControlName="enabled"
|
||||
[label]="'allowSso' | i18n"
|
||||
[helperText]="'allowSsoDesc' | i18n"
|
||||
></app-input-checkbox>
|
||||
<bit-form-control>
|
||||
<bit-label>{{ "allowSso" | i18n }}</bit-label>
|
||||
<input bitCheckbox type="checkbox" formControlName="enabled" id="enabled" />
|
||||
<bit-hint>{{ "allowSsoDesc" | i18n }}</bit-hint>
|
||||
</bit-form-control>
|
||||
|
||||
<bit-form-field>
|
||||
<bit-label>{{ "ssoIdentifier" | i18n }}</bit-label>
|
||||
@ -43,31 +35,25 @@
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="form-group">
|
||||
<label>{{ "memberDecryptionOption" | i18n }}</label>
|
||||
<div class="form-check form-check-block">
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="radio"
|
||||
id="memberDecryptionPass"
|
||||
[value]="false"
|
||||
formControlName="keyConnectorEnabled"
|
||||
/>
|
||||
<label class="form-check-label" for="memberDecryptionPass">
|
||||
{{ "masterPass" | i18n }}
|
||||
<small>{{ "memberDecryptionPassDesc" | i18n }}</small>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-check mt-2 form-check-block">
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="radio"
|
||||
id="memberDecryptionKey"
|
||||
[value]="true"
|
||||
formControlName="keyConnectorEnabled"
|
||||
[attr.disabled]="!organization.useKeyConnector || null"
|
||||
/>
|
||||
<label class="form-check-label" for="memberDecryptionKey">
|
||||
<bit-radio-group formControlName="memberDecryptionType">
|
||||
<bit-label>{{ "memberDecryptionOption" | i18n }}</bit-label>
|
||||
|
||||
<bit-radio-button
|
||||
class="tw-block"
|
||||
id="memberDecryptionPass"
|
||||
[value]="memberDecryptionType.MasterPassword"
|
||||
>
|
||||
<bit-label>{{ "masterPass" | i18n }}</bit-label>
|
||||
</bit-radio-button>
|
||||
|
||||
<bit-radio-button
|
||||
class="tw-block"
|
||||
id="memberDecryptionKey"
|
||||
[value]="memberDecryptionType.KeyConnector"
|
||||
[disabled]="!organization.useKeyConnector || null"
|
||||
*ngIf="showKeyConnectorOptions"
|
||||
>
|
||||
<bit-label>
|
||||
{{ "keyConnector" | i18n }}
|
||||
<a
|
||||
target="_blank"
|
||||
@ -77,13 +63,38 @@
|
||||
>
|
||||
<i class="bwi bwi-question-circle" aria-hidden="true"></i>
|
||||
</a>
|
||||
<small>{{ "memberDecryptionKeyConnectorDesc" | i18n }}</small>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</bit-label>
|
||||
<bit-hint>
|
||||
{{ "memberDecryptionKeyConnectorDescStart" | i18n }}
|
||||
<a routerLink="../policies">{{ "memberDecryptionKeyConnectorDescLink" | i18n }}</a>
|
||||
{{ "memberDecryptionKeyConnectorDescEnd" | i18n }}
|
||||
</bit-hint>
|
||||
</bit-radio-button>
|
||||
|
||||
<bit-radio-button
|
||||
class="tw-block"
|
||||
id="memberDecryptionTde"
|
||||
[value]="memberDecryptionType.TrustedDeviceEncryption"
|
||||
*ngIf="showTdeOptions"
|
||||
>
|
||||
<bit-label>
|
||||
{{ "trustedDeviceEncryption" | i18n }}
|
||||
</bit-label>
|
||||
<bit-hint>
|
||||
{{ "memberDecryptionTdeDescStart" | i18n }}
|
||||
<a routerLink="../policies">{{ "memberDecryptionTdeDescLink" | i18n }}</a>
|
||||
{{ "memberDecryptionTdeDescEnd" | i18n }}
|
||||
</bit-hint>
|
||||
</bit-radio-button>
|
||||
</bit-radio-group>
|
||||
|
||||
<!-- Key Connector -->
|
||||
<ng-container *ngIf="ssoConfigForm.get('keyConnectorEnabled').value">
|
||||
<ng-container
|
||||
*ngIf="
|
||||
ssoConfigForm.value.memberDecryptionType === memberDecryptionType.KeyConnector &&
|
||||
showKeyConnectorOptions
|
||||
"
|
||||
>
|
||||
<app-callout type="warning" [useAlertRole]="true">
|
||||
{{ "keyConnectorWarning" | i18n }}
|
||||
</app-callout>
|
||||
@ -205,11 +216,15 @@
|
||||
</select>
|
||||
</bit-form-field>
|
||||
|
||||
<app-input-checkbox
|
||||
controlId="getClaimsFromUserInfoEndpoint"
|
||||
formControlName="getClaimsFromUserInfoEndpoint"
|
||||
[label]="'getClaimsFromUserInfoEndpoint' | i18n"
|
||||
></app-input-checkbox>
|
||||
<bit-form-control>
|
||||
<bit-label>{{ "getClaimsFromUserInfoEndpoint" | i18n }}</bit-label>
|
||||
<input
|
||||
bitCheckbox
|
||||
type="checkbox"
|
||||
formControlName="getClaimsFromUserInfoEndpoint"
|
||||
id="getClaimsFromUserInfoEndpoint"
|
||||
/>
|
||||
</bit-form-control>
|
||||
|
||||
<!-- Optional customizations -->
|
||||
<div
|
||||
@ -381,17 +396,25 @@
|
||||
</select>
|
||||
</bit-form-field>
|
||||
|
||||
<app-input-checkbox
|
||||
controlId="spWantAssertionsSigned"
|
||||
formControlName="spWantAssertionsSigned"
|
||||
[label]="'spWantAssertionsSigned' | i18n"
|
||||
></app-input-checkbox>
|
||||
<bit-form-control>
|
||||
<bit-label>{{ "spWantAssertionsSigned" | i18n }}</bit-label>
|
||||
<input
|
||||
bitCheckbox
|
||||
type="checkbox"
|
||||
formControlName="spWantAssertionsSigned"
|
||||
id="spWantAssertionsSigned"
|
||||
/>
|
||||
</bit-form-control>
|
||||
|
||||
<app-input-checkbox
|
||||
controlId="spValidateCertificates"
|
||||
formControlName="spValidateCertificates"
|
||||
[label]="'spValidateCertificates' | i18n"
|
||||
></app-input-checkbox>
|
||||
<bit-form-control>
|
||||
<bit-label>{{ "spValidateCertificates" | i18n }}</bit-label>
|
||||
<input
|
||||
bitCheckbox
|
||||
type="checkbox"
|
||||
formControlName="spValidateCertificates"
|
||||
id="spValidateCertificates"
|
||||
/>
|
||||
</bit-form-control>
|
||||
</div>
|
||||
|
||||
<!-- SAML2 IDP -->
|
||||
@ -462,21 +485,29 @@
|
||||
[label]="'idpAllowUnsolicitedAuthnResponse' | i18n"
|
||||
></app-input-checkbox> -->
|
||||
|
||||
<app-input-checkbox
|
||||
controlId="idpAllowOutboundLogoutRequests"
|
||||
formControlName="idpAllowOutboundLogoutRequests"
|
||||
[label]="'idpAllowOutboundLogoutRequests' | i18n"
|
||||
></app-input-checkbox>
|
||||
<bit-form-control>
|
||||
<bit-label>{{ "idpAllowOutboundLogoutRequests" | i18n }}</bit-label>
|
||||
<input
|
||||
bitCheckbox
|
||||
type="checkbox"
|
||||
formControlName="idpAllowOutboundLogoutRequests"
|
||||
id="idpAllowOutboundLogoutRequests"
|
||||
/>
|
||||
</bit-form-control>
|
||||
|
||||
<app-input-checkbox
|
||||
controlId="idpWantAuthnRequestsSigned"
|
||||
formControlName="idpWantAuthnRequestsSigned"
|
||||
[label]="'idpSignAuthenticationRequests' | i18n"
|
||||
></app-input-checkbox>
|
||||
<bit-form-control>
|
||||
<bit-label>{{ "idpSignAuthenticationRequests" | i18n }}</bit-label>
|
||||
<input
|
||||
bitCheckbox
|
||||
type="checkbox"
|
||||
formControlName="idpWantAuthnRequestsSigned"
|
||||
id="idpWantAuthnRequestsSigned"
|
||||
/>
|
||||
</bit-form-control>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="submit" buttonType="primary" bitButton [loading]="form.loading">
|
||||
<button type="submit" buttonType="primary" bitButton bitFormButton>
|
||||
{{ "save" | i18n }}
|
||||
</button>
|
||||
<bit-error-summary [formGroup]="ssoConfigForm"></bit-error-summary>
|
||||
|
@ -12,12 +12,14 @@ import { concatMap, Subject, takeUntil } from "rxjs";
|
||||
import { SelectOptions } from "@bitwarden/angular/interfaces/selectOptions";
|
||||
import { ControlsOf } from "@bitwarden/angular/types/controls-of";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { ConfigServiceAbstraction } from "@bitwarden/common/abstractions/config/config.service.abstraction";
|
||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import {
|
||||
MemberDecryptionType,
|
||||
OpenIdConnectRedirectBehavior,
|
||||
Saml2BindingType,
|
||||
Saml2NameIdFormat,
|
||||
@ -28,6 +30,7 @@ import { SsoConfigApi } from "@bitwarden/common/auth/models/api/sso-config.api";
|
||||
import { OrganizationSsoRequest } from "@bitwarden/common/auth/models/request/organization-sso.request";
|
||||
import { OrganizationSsoResponse } from "@bitwarden/common/auth/models/response/organization-sso.response";
|
||||
import { SsoConfigView } from "@bitwarden/common/auth/models/view/sso-config.view";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { Utils } from "@bitwarden/common/misc/utils";
|
||||
|
||||
import { ssoTypeValidator } from "./sso-type.validator";
|
||||
@ -40,6 +43,7 @@ const defaultSigningAlgorithm = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha2
|
||||
})
|
||||
export class SsoComponent implements OnInit, OnDestroy {
|
||||
readonly ssoType = SsoType;
|
||||
readonly memberDecryptionType = MemberDecryptionType;
|
||||
|
||||
readonly ssoTypeOptions: SelectOptions[] = [
|
||||
{ name: this.i18nService.t("selectType"), value: SsoType.None, disabled: true },
|
||||
@ -83,6 +87,8 @@ export class SsoComponent implements OnInit, OnDestroy {
|
||||
];
|
||||
|
||||
private destroy$ = new Subject<void>();
|
||||
showTdeOptions = false;
|
||||
showKeyConnectorOptions = false;
|
||||
|
||||
showOpenIdCustomizations = false;
|
||||
|
||||
@ -90,7 +96,6 @@ export class SsoComponent implements OnInit, OnDestroy {
|
||||
haveTestedKeyConnector = false;
|
||||
organizationId: string;
|
||||
organization: Organization;
|
||||
formPromise: Promise<OrganizationSsoResponse>;
|
||||
|
||||
callbackPath: string;
|
||||
signedOutCallbackPath: string;
|
||||
@ -147,7 +152,7 @@ export class SsoComponent implements OnInit, OnDestroy {
|
||||
|
||||
protected ssoConfigForm = this.formBuilder.group<ControlsOf<SsoConfigView>>({
|
||||
configType: new FormControl(SsoType.None),
|
||||
keyConnectorEnabled: new FormControl(false),
|
||||
memberDecryptionType: new FormControl(MemberDecryptionType.MasterPassword),
|
||||
keyConnectorUrl: new FormControl(""),
|
||||
openId: this.openIdForm,
|
||||
saml: this.samlForm,
|
||||
@ -174,7 +179,8 @@ export class SsoComponent implements OnInit, OnDestroy {
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private i18nService: I18nService,
|
||||
private organizationService: OrganizationService,
|
||||
private organizationApiService: OrganizationApiServiceAbstraction
|
||||
private organizationApiService: OrganizationApiServiceAbstraction,
|
||||
private configService: ConfigServiceAbstraction
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
@ -223,6 +229,15 @@ export class SsoComponent implements OnInit, OnDestroy {
|
||||
takeUntil(this.destroy$)
|
||||
)
|
||||
.subscribe();
|
||||
|
||||
const tdeFeatureFlag = await this.configService.getFeatureFlagBool(
|
||||
FeatureFlag.TrustedDeviceEncryption
|
||||
);
|
||||
|
||||
this.showTdeOptions = tdeFeatureFlag && !this.platformUtilsService.isSelfHost();
|
||||
// If the tde flag is not enabled, continue showing the key connector options to keep the UI the same
|
||||
// Once the flag is removed, we can rely on the platformUtilsService.isSelfHost() check alone
|
||||
this.showKeyConnectorOptions = !tdeFeatureFlag || this.platformUtilsService.isSelfHost();
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
@ -244,10 +259,10 @@ export class SsoComponent implements OnInit, OnDestroy {
|
||||
this.loading = false;
|
||||
}
|
||||
|
||||
async submit() {
|
||||
submit = async () => {
|
||||
this.updateFormValidationState(this.ssoConfigForm);
|
||||
|
||||
if (this.ssoConfigForm.value.keyConnectorEnabled) {
|
||||
if (this.ssoConfigForm.value.memberDecryptionType === MemberDecryptionType.KeyConnector) {
|
||||
this.haveTestedKeyConnector = false;
|
||||
await this.validateKeyConnectorUrl();
|
||||
}
|
||||
@ -262,18 +277,11 @@ export class SsoComponent implements OnInit, OnDestroy {
|
||||
request.identifier = this.ssoIdentifierCtrl.value === "" ? null : this.ssoIdentifierCtrl.value;
|
||||
request.data = SsoConfigApi.fromView(this.ssoConfigForm.getRawValue());
|
||||
|
||||
this.formPromise = this.organizationApiService.updateSso(this.organizationId, request);
|
||||
const response = await this.organizationApiService.updateSso(this.organizationId, request);
|
||||
this.populateForm(response);
|
||||
|
||||
try {
|
||||
const response = await this.formPromise;
|
||||
this.populateForm(response);
|
||||
this.platformUtilsService.showToast("success", null, this.i18nService.t("ssoSettingsSaved"));
|
||||
} catch {
|
||||
// Logged by appApiAction, do nothing
|
||||
}
|
||||
|
||||
this.formPromise = null;
|
||||
}
|
||||
this.platformUtilsService.showToast("success", null, this.i18nService.t("ssoSettingsSaved"));
|
||||
};
|
||||
|
||||
async validateKeyConnectorUrl() {
|
||||
if (this.haveTestedKeyConnector) {
|
||||
@ -313,7 +321,7 @@ export class SsoComponent implements OnInit, OnDestroy {
|
||||
|
||||
get enableTestKeyConnector() {
|
||||
return (
|
||||
this.ssoConfigForm.get("keyConnectorEnabled").value &&
|
||||
this.ssoConfigForm.value?.memberDecryptionType === MemberDecryptionType.KeyConnector &&
|
||||
!Utils.isNullOrWhitespace(this.keyConnectorUrl?.value)
|
||||
);
|
||||
}
|
||||
|
@ -4,6 +4,12 @@ export enum SsoType {
|
||||
Saml2 = 2,
|
||||
}
|
||||
|
||||
export enum MemberDecryptionType {
|
||||
MasterPassword = 0,
|
||||
KeyConnector = 1,
|
||||
TrustedDeviceEncryption = 2,
|
||||
}
|
||||
|
||||
export enum OpenIdConnectRedirectBehavior {
|
||||
RedirectGet = 0,
|
||||
FormPost = 1,
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { BaseResponse } from "../../../models/response/base.response";
|
||||
import {
|
||||
MemberDecryptionType,
|
||||
OpenIdConnectRedirectBehavior,
|
||||
Saml2BindingType,
|
||||
Saml2NameIdFormat,
|
||||
@ -11,8 +12,8 @@ import { SsoConfigView } from "../view/sso-config.view";
|
||||
export class SsoConfigApi extends BaseResponse {
|
||||
static fromView(view: SsoConfigView, api = new SsoConfigApi()) {
|
||||
api.configType = view.configType;
|
||||
api.memberDecryptionType = view.memberDecryptionType;
|
||||
|
||||
api.keyConnectorEnabled = view.keyConnectorEnabled;
|
||||
api.keyConnectorUrl = view.keyConnectorUrl;
|
||||
|
||||
if (api.configType === SsoType.OpenIdConnect) {
|
||||
@ -52,8 +53,8 @@ export class SsoConfigApi extends BaseResponse {
|
||||
return api;
|
||||
}
|
||||
configType: SsoType;
|
||||
memberDecryptionType: MemberDecryptionType;
|
||||
|
||||
keyConnectorEnabled: boolean;
|
||||
keyConnectorUrl: string;
|
||||
|
||||
// OpenId
|
||||
@ -95,8 +96,8 @@ export class SsoConfigApi extends BaseResponse {
|
||||
}
|
||||
|
||||
this.configType = this.getResponseProperty("ConfigType");
|
||||
this.memberDecryptionType = this.getResponseProperty("MemberDecryptionType");
|
||||
|
||||
this.keyConnectorEnabled = this.getResponseProperty("KeyConnectorEnabled");
|
||||
this.keyConnectorUrl = this.getResponseProperty("KeyConnectorUrl");
|
||||
|
||||
this.authority = this.getResponseProperty("Authority");
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { View } from "../../../models/view/view";
|
||||
import {
|
||||
MemberDecryptionType,
|
||||
OpenIdConnectRedirectBehavior,
|
||||
Saml2BindingType,
|
||||
Saml2NameIdFormat,
|
||||
@ -14,7 +15,7 @@ export class SsoConfigView extends View {
|
||||
|
||||
configType: SsoType;
|
||||
|
||||
keyConnectorEnabled: boolean;
|
||||
memberDecryptionType: MemberDecryptionType;
|
||||
keyConnectorUrl: string;
|
||||
|
||||
openId: {
|
||||
@ -66,8 +67,8 @@ export class SsoConfigView extends View {
|
||||
}
|
||||
|
||||
this.configType = orgSsoResponse.data.configType;
|
||||
this.memberDecryptionType = orgSsoResponse.data.memberDecryptionType;
|
||||
|
||||
this.keyConnectorEnabled = orgSsoResponse.data.keyConnectorEnabled;
|
||||
this.keyConnectorUrl = orgSsoResponse.data.keyConnectorUrl;
|
||||
|
||||
if (this.configType === SsoType.OpenIdConnect) {
|
||||
|
@ -1,4 +1,5 @@
|
||||
export enum FeatureFlag {
|
||||
DisplayEuEnvironmentFlag = "display-eu-environment",
|
||||
DisplayLowKdfIterationWarningFlag = "display-kdf-iteration-warning",
|
||||
TrustedDeviceEncryption = "trusted-device-encryption",
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user