1
0
mirror of https://github.com/bitwarden/browser synced 2026-01-05 18:13:26 +00:00
Files
browser/bitwarden_license/bit-web/src/app/auth/sso/sso.component.html
SmithThe4th 678ba04781 [PM-6532] Make Admin Console Single Sign on Settings Page Consistent With Others (#8550)
* added class to reduce width of fields

* moved class to form

* updated sso template to use bit container which already handles width
2024-04-03 18:58:19 -04:00

550 lines
18 KiB
HTML

<app-header></app-header>
<bit-container>
<ng-container *ngIf="loading">
<i
class="bwi bwi-spinner bwi-spin text-muted"
title="{{ 'loading' | i18n }}"
aria-hidden="true"
></i>
<span class="tw-sr-only">{{ "loading" | i18n }}</span>
</ng-container>
<form [formGroup]="ssoConfigForm" [bitSubmit]="submit" *ngIf="!loading">
<p>
{{ "ssoPolicyHelpStart" | i18n }}
<a routerLink="../policies">{{ "ssoPolicyHelpAnchor" | i18n }}</a>
{{ "ssoPolicyHelpEnd" | i18n }}
<br />
</p>
<!-- Root form -->
<ng-container>
<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>
<input bitInput type="text" formControlName="ssoIdentifier" />
<bit-hint>
{{ "ssoIdentifierHintPartOne" | i18n }}
<a routerLink="../domain-verification">{{ "domainVerification" | i18n }}</a>
</bit-hint>
</bit-form-field>
<hr />
<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"
rel="noreferrer"
appA11yTitle="{{ 'learnMore' | i18n }}"
href="https://bitwarden.com/help/about-key-connector/"
>
<i class="bwi bwi-question-circle" aria-hidden="true"></i>
</a>
</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"
>
<bit-label>
{{ "trustedDevices" | i18n }}
</bit-label>
<bit-hint>
{{ "memberDecryptionOptionTdeDescriptionPartOne" | i18n }}
<a routerLink="../policies">{{
"memberDecryptionOptionTdeDescriptionLinkOne" | i18n
}}</a>
{{ "memberDecryptionOptionTdeDescriptionPartTwo" | i18n }}
<a routerLink="../policies">{{
"memberDecryptionOptionTdeDescriptionLinkTwo" | i18n
}}</a>
{{ "memberDecryptionOptionTdeDescriptionPartThree" | i18n }}
<a routerLink="../policies">{{
"memberDecryptionOptionTdeDescriptionLinkThree" | i18n
}}</a>
{{ "memberDecryptionOptionTdeDescriptionPartFour" | i18n }}
</bit-hint>
</bit-radio-button>
</bit-radio-group>
<!-- Key Connector -->
<ng-container
*ngIf="
ssoConfigForm.value.memberDecryptionType === memberDecryptionType.KeyConnector &&
showKeyConnectorOptions
"
>
<app-callout type="warning" [useAlertRole]="true">
{{ "keyConnectorWarning" | i18n }}
</app-callout>
<bit-form-field>
<bit-label>{{ "keyConnectorUrl" | i18n }}</bit-label>
<input
bitInput
type="text"
required
formControlName="keyConnectorUrl"
appInputStripSpaces
(input)="haveTestedKeyConnector = false"
/>
<button
bitSuffix
bitButton
[disabled]="!enableTestKeyConnector"
type="button"
(click)="validateKeyConnectorUrl()"
>
<i
class="bwi bwi-spinner bwi-spin"
title="{{ 'loading' | i18n }}"
aria-hidden="true"
*ngIf="keyConnectorUrl.pending"
></i>
<span *ngIf="!keyConnectorUrl.pending">
{{ "keyConnectorTest" | i18n }}
</span>
</button>
<bit-hint
aria-live="polite"
*ngIf="haveTestedKeyConnector && !keyConnectorUrl.hasError('invalidUrl')"
>
<small class="text-success">
<i class="bwi bwi-check-circle" aria-hidden="true"></i>
{{ "keyConnectorTestSuccess" | i18n }}
</small>
</bit-hint>
</bit-form-field>
</ng-container>
<hr />
<bit-form-field>
<bit-label>{{ "type" | i18n }}</bit-label>
<select bitInput formControlName="configType">
<option *ngFor="let o of ssoTypeOptions" [ngValue]="o.value" disabled="{{ o.disabled }}">
{{ o.name }}
</option>
</select>
</bit-form-field>
</ng-container>
<!-- OIDC -->
<div
*ngIf="ssoConfigForm.get('configType').value === ssoType.OpenIdConnect"
[formGroup]="openIdForm"
>
<div class="config-section">
<h2 class="secondary-header">{{ "openIdConnectConfig" | i18n }}</h2>
<bit-form-field>
<bit-label>{{ "callbackPath" | i18n }}</bit-label>
<input bitInput disabled [value]="callbackPath" />
<button
bitIconButton="bwi-clone"
bitSuffix
type="button"
[appCopyClick]="callbackPath"
[appA11yTitle]="'copyValue' | i18n"
></button>
</bit-form-field>
<bit-form-field>
<bit-label>{{ "signedOutCallbackPath" | i18n }}</bit-label>
<input bitInput disabled [value]="signedOutCallbackPath" />
<button
bitIconButton="bwi-clone"
bitSuffix
type="button"
[appCopyClick]="signedOutCallbackPath"
[appA11yTitle]="'copyValue' | i18n"
></button>
</bit-form-field>
<bit-form-field>
<bit-label>{{ "authority" | i18n }}</bit-label>
<input bitInput type="text" formControlName="authority" appInputStripSpaces />
</bit-form-field>
<bit-form-field>
<bit-label>{{ "clientId" | i18n }}</bit-label>
<input bitInput type="text" formControlName="clientId" appInputStripSpaces />
</bit-form-field>
<bit-form-field>
<bit-label>{{ "clientSecret" | i18n }}</bit-label>
<input bitInput type="text" formControlName="clientSecret" appInputStripSpaces />
</bit-form-field>
<bit-form-field>
<bit-label>{{ "metadataAddress" | i18n }}</bit-label>
<input bitInput type="text" formControlName="metadataAddress" appInputStripSpaces />
<bit-hint>{{ "openIdAuthorityRequired" | i18n }}</bit-hint>
</bit-form-field>
<bit-form-field>
<bit-label>{{ "oidcRedirectBehavior" | i18n }}</bit-label>
<select bitInput formControlName="redirectBehavior">
<option
*ngFor="let o of connectRedirectOptions"
[ngValue]="o.value"
disabled="{{ o.disabled }}"
>
{{ o.name }}
</option>
</select>
</bit-form-field>
<bit-form-control>
<bit-label>{{ "getClaimsFromUserInfoEndpoint" | i18n }}</bit-label>
<input
bitCheckbox
type="checkbox"
formControlName="getClaimsFromUserInfoEndpoint"
id="getClaimsFromUserInfoEndpoint"
/>
</bit-form-control>
<!-- Optional customizations -->
<div
class="section-header d-flex flex-row align-items-center mt-3 mb-3"
(click)="toggleOpenIdCustomizations()"
>
<h3 class="mb-0 mr-2" id="customizations-header">
{{ "openIdOptionalCustomizations" | i18n }}
</h3>
<button
class="mb-1 btn btn-link"
type="button"
appStopClick
role="button"
aria-controls="customizations"
[attr.aria-expanded]="showOpenIdCustomizations"
aria-labelledby="customizations-header"
>
<i
class="bwi"
aria-hidden="true"
[ngClass]="{
'bwi-angle-right': !showOpenIdCustomizations,
'bwi-angle-down': showOpenIdCustomizations
}"
></i>
</button>
</div>
<div id="customizations" [hidden]="!showOpenIdCustomizations">
<bit-form-field>
<bit-label>{{ "additionalScopes" | i18n }}</bit-label>
<input bitInput type="text" formControlName="additionalScopes" />
<bit-hint>{{ "separateMultipleWithComma" | i18n }}</bit-hint>
</bit-form-field>
<bit-form-field>
<bit-label>{{ "additionalUserIdClaimTypes" | i18n }}</bit-label>
<input bitInput type="text" formControlName="additionalUserIdClaimTypes" />
<bit-hint>{{ "separateMultipleWithComma" | i18n }}</bit-hint>
</bit-form-field>
<bit-form-field>
<bit-label>{{ "additionalEmailClaimTypes" | i18n }}</bit-label>
<input bitInput type="text" formControlName="additionalEmailClaimTypes" />
<bit-hint>{{ "separateMultipleWithComma" | i18n }}</bit-hint>
</bit-form-field>
<bit-form-field>
<bit-label>{{ "additionalNameClaimTypes" | i18n }}</bit-label>
<input bitInput type="text" formControlName="additionalNameClaimTypes" />
<bit-hint>{{ "separateMultipleWithComma" | i18n }}</bit-hint>
</bit-form-field>
<bit-form-field>
<bit-label>{{ "acrValues" | i18n }}</bit-label>
<input bitInput type="text" formControlName="acrValues" />
<bit-hint>acr_values</bit-hint>
</bit-form-field>
<bit-form-field>
<bit-label>{{ "expectedReturnAcrValue" | i18n }}</bit-label>
<input bitInput type="text" formControlName="expectedReturnAcrValue" />
<bit-hint>acr_validaton</bit-hint>
</bit-form-field>
</div>
</div>
</div>
<!-- SAML2 SP -->
<div *ngIf="ssoConfigForm.get('configType').value === ssoType.Saml2" [formGroup]="samlForm">
<!-- SAML2 SP -->
<div class="config-section">
<h2 class="secondary-header">{{ "samlSpConfig" | i18n }}</h2>
<bit-form-control>
<bit-label>{{ "spUniqueEntityId" | i18n }}</bit-label>
<input
bitCheckbox
type="checkbox"
formControlName="spUniqueEntityId"
id="spUniqueEntityId"
/>
<bit-hint>{{ "spUniqueEntityIdDesc" | i18n }}</bit-hint>
</bit-form-control>
<bit-form-field *ngIf="ssoConfigForm.value.saml.spUniqueEntityId">
<bit-label>{{ "spEntityId" | i18n }}</bit-label>
<input bitInput disabled [value]="spEntityId" />
<button
bitIconButton="bwi-clone"
bitSuffix
type="button"
[appCopyClick]="spEntityId"
[appA11yTitle]="'copyValue' | i18n"
></button>
</bit-form-field>
<bit-form-field *ngIf="!ssoConfigForm.value.saml.spUniqueEntityId">
<bit-label>{{ "spEntityId" | i18n }}</bit-label>
<input bitInput disabled [value]="spEntityIdStatic" />
<button
bitIconButton="bwi-clone"
bitSuffix
type="button"
[appCopyClick]="spEntityIdStatic"
[appA11yTitle]="'copyValue' | i18n"
></button>
</bit-form-field>
<bit-form-field>
<bit-label>{{ "spMetadataUrl" | i18n }}</bit-label>
<input bitInput disabled [value]="spMetadataUrl" />
<button
bitButton
bitSuffix
type="button"
[appLaunchClick]="spMetadataUrl"
[appA11yTitle]="'launch' | i18n"
>
<i class="bwi bwi-lg bwi-external-link" aria-hidden="true"></i>
</button>
<button
bitIconButton="bwi-clone"
bitSuffix
type="button"
[appCopyClick]="spMetadataUrl"
[appA11yTitle]="'copyValue' | i18n"
></button>
</bit-form-field>
<bit-form-field>
<bit-label>{{ "spAcsUrl" | i18n }}</bit-label>
<input bitInput disabled [value]="spAcsUrl" />
<button
bitIconButton="bwi-clone"
bitSuffix
type="button"
[appCopyClick]="spAcsUrl"
[appA11yTitle]="'copyValue' | i18n"
></button>
</bit-form-field>
<bit-form-field>
<bit-label>{{ "spNameIdFormat" | i18n }}</bit-label>
<select bitInput formControlName="spNameIdFormat">
<option
*ngFor="let o of saml2NameIdFormatOptions"
[ngValue]="o.value"
disabled="{{ o.disabled }}"
>
{{ o.name }}
</option>
</select>
</bit-form-field>
<bit-form-field>
<bit-label>{{ "spOutboundSigningAlgorithm" | i18n }}</bit-label>
<select bitInput formControlName="spOutboundSigningAlgorithm">
<option
*ngFor="let o of samlSigningAlgorithmOptions"
[ngValue]="o.value"
disabled="{{ o.disabled }}"
>
{{ o.name }}
</option>
</select>
</bit-form-field>
<bit-form-field>
<bit-label>{{ "spSigningBehavior" | i18n }}</bit-label>
<select bitInput formControlName="spSigningBehavior">
<option
*ngFor="let o of saml2SigningBehaviourOptions"
[ngValue]="o.value"
disabled="{{ o.disabled }}"
>
{{ o.name }}
</option>
</select>
</bit-form-field>
<bit-form-field>
<bit-label>{{ "spMinIncomingSigningAlgorithm" | i18n }}</bit-label>
<select bitInput formControlName="spMinIncomingSigningAlgorithm">
<option
*ngFor="let o of samlSigningAlgorithmOptions"
[ngValue]="o.value"
disabled="{{ o.disabled }}"
>
{{ o.name }}
</option>
</select>
</bit-form-field>
<bit-form-control>
<bit-label>{{ "spWantAssertionsSigned" | i18n }}</bit-label>
<input
bitCheckbox
type="checkbox"
formControlName="spWantAssertionsSigned"
id="spWantAssertionsSigned"
/>
</bit-form-control>
<bit-form-control>
<bit-label>{{ "spValidateCertificates" | i18n }}</bit-label>
<input
bitCheckbox
type="checkbox"
formControlName="spValidateCertificates"
id="spValidateCertificates"
/>
</bit-form-control>
</div>
<!-- SAML2 IDP -->
<div class="config-section">
<h2 class="secondary-header">{{ "samlIdpConfig" | i18n }}</h2>
<bit-form-field>
<bit-label>{{ "idpEntityId" | i18n }}</bit-label>
<input bitInput type="text" formControlName="idpEntityId" />
</bit-form-field>
<bit-form-field>
<bit-label>{{ "idpBindingType" | i18n }}</bit-label>
<select bitInput formControlName="idpBindingType">
<option
*ngFor="let o of saml2BindingTypeOptions"
[ngValue]="o.value"
disabled="{{ o.disabled }}"
>
{{ o.name }}
</option>
</select>
</bit-form-field>
<bit-form-field>
<bit-label>{{ "idpSingleSignOnServiceUrl" | i18n }}</bit-label>
<input
bitInput
type="text"
formControlName="idpSingleSignOnServiceUrl"
appInputStripSpaces
/>
<bit-hint>{{ "idpSingleSignOnServiceUrlRequired" | i18n }}</bit-hint>
</bit-form-field>
<bit-form-field>
<bit-label>{{ "idpSingleLogoutServiceUrl" | i18n }}</bit-label>
<input
bitInput
type="text"
formControlName="idpSingleLogoutServiceUrl"
appInputStripSpaces
/>
</bit-form-field>
<bit-form-field>
<bit-label>{{ "idpX509PublicCert" | i18n }}</bit-label>
<textarea bitInput rows="6" formControlName="idpX509PublicCert"></textarea>
</bit-form-field>
<bit-form-field>
<bit-label>{{ "idpOutboundSigningAlgorithm" | i18n }}</bit-label>
<select bitInput formControlName="idpOutboundSigningAlgorithm">
<option
*ngFor="let o of samlSigningAlgorithmOptions"
[ngValue]="o.value"
disabled="{{ o.disabled }}"
>
{{ o.name }}
</option>
</select>
</bit-form-field>
<!--TODO: Uncomment once Unsolicited IdP Response is supported-->
<!-- <app-input-checkbox
controlId="idpAllowUnsolicitedAuthnResponse"
formControlName="idpAllowUnsolicitedAuthnResponse"
[label]="'idpAllowUnsolicitedAuthnResponse' | i18n"
></app-input-checkbox> -->
<bit-form-control>
<bit-label>{{ "idpAllowOutboundLogoutRequests" | i18n }}</bit-label>
<input
bitCheckbox
type="checkbox"
formControlName="idpAllowOutboundLogoutRequests"
id="idpAllowOutboundLogoutRequests"
/>
</bit-form-control>
<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 bitFormButton>
{{ "save" | i18n }}
</button>
<bit-error-summary [formGroup]="ssoConfigForm"></bit-error-summary>
</form>
</bit-container>