mirror of
https://github.com/bitwarden/web
synced 2025-12-06 00:03:28 +00:00
494 lines
17 KiB
HTML
494 lines
17 KiB
HTML
<div class="page-header d-flex">
|
|
<h1>{{ "singleSignOn" | i18n }}</h1>
|
|
</div>
|
|
|
|
<ng-container *ngIf="loading">
|
|
<i
|
|
class="bwi bwi-spinner bwi-spin text-muted"
|
|
title="{{ 'loading' | i18n }}"
|
|
aria-hidden="true"
|
|
></i>
|
|
<span class="sr-only">{{ "loading" | i18n }}</span>
|
|
</ng-container>
|
|
|
|
<form
|
|
#form
|
|
(ngSubmit)="submit()"
|
|
[formGroup]="data"
|
|
[appApiAction]="formPromise"
|
|
*ngIf="!loading"
|
|
ngNativeValidate
|
|
>
|
|
<p>
|
|
{{ "ssoPolicyHelpStart" | i18n }}
|
|
<a routerLink="../policies">{{ "ssoPolicyHelpLink" | i18n }}</a>
|
|
{{ "ssoPolicyHelpEnd" | i18n }}
|
|
<br />
|
|
{{ "ssoPolicyHelpKeyConnector" | i18n }}
|
|
</p>
|
|
|
|
<div class="form-group">
|
|
<div class="form-check">
|
|
<input
|
|
class="form-check-input"
|
|
type="checkbox"
|
|
id="enabled"
|
|
[formControl]="enabled"
|
|
name="Enabled"
|
|
/>
|
|
<label class="form-check-label" for="enabled">{{ "allowSso" | i18n }}</label>
|
|
</div>
|
|
<small class="form-text text-muted">{{ "allowSsoDesc" | i18n }}</small>
|
|
</div>
|
|
|
|
<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">
|
|
{{ "keyConnector" | i18n }}
|
|
<a
|
|
target="_blank"
|
|
rel="noopener"
|
|
appA11yTitle="{{ 'learnMore' | i18n }}"
|
|
href="https://bitwarden.com/help/about-key-connector/"
|
|
>
|
|
<i class="bwi bwi-question-circle" aria-hidden="true"></i>
|
|
</a>
|
|
<small>{{ "memberDecryptionKeyConnectorDesc" | i18n }}</small>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<ng-container *ngIf="data.value.keyConnectorEnabled">
|
|
<app-callout type="warning" [useAlertRole]="true">
|
|
{{ "keyConnectorWarning" | i18n }}
|
|
</app-callout>
|
|
|
|
<div class="form-group">
|
|
<label for="keyConnectorUrl">{{ "keyConnectorUrl" | i18n }}</label>
|
|
<div class="input-group">
|
|
<input
|
|
class="form-control"
|
|
formControlName="keyConnectorUrl"
|
|
id="keyConnectorUrl"
|
|
required
|
|
/>
|
|
<div class="input-group-append">
|
|
<button
|
|
type="button"
|
|
class="btn btn-outline-secondary"
|
|
(click)="validateKeyConnectorUrl()"
|
|
[disabled]="!enableTestKeyConnector"
|
|
>
|
|
<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>
|
|
</div>
|
|
</div>
|
|
<ng-container *ngIf="keyConnectorUrl.pristine && !keyConnectorUrl.pending">
|
|
<div class="text-danger" *ngIf="keyConnectorUrl.hasError('invalidUrl')" role="alert">
|
|
<i class="bwi bwi-exclamation-circle" aria-hidden="true"></i>
|
|
{{ "keyConnectorTestFail" | i18n }}
|
|
</div>
|
|
<div class="text-success" *ngIf="!keyConnectorUrl.hasError('invalidUrl')" role="alert">
|
|
<i class="bwi bwi-check-circle" aria-hidden="true"></i>
|
|
{{ "keyConnectorTestSuccess" | i18n }}
|
|
</div>
|
|
</ng-container>
|
|
</div>
|
|
</ng-container>
|
|
|
|
<div class="form-group">
|
|
<label for="type">{{ "type" | i18n }}</label>
|
|
<select class="form-control" id="type" formControlName="configType">
|
|
<option [ngValue]="0" disabled>{{ "selectType" | i18n }}</option>
|
|
<option [ngValue]="1">OpenID Connect</option>
|
|
<option [ngValue]="2">SAML 2.0</option>
|
|
</select>
|
|
</div>
|
|
|
|
<!-- OIDC -->
|
|
<div *ngIf="data.value.configType == 1">
|
|
<div class="config-section">
|
|
<h2>{{ "openIdConnectConfig" | i18n }}</h2>
|
|
<div class="form-group">
|
|
<label>{{ "callbackPath" | i18n }}</label>
|
|
<div class="input-group">
|
|
<input class="form-control" readonly [value]="callbackPath" />
|
|
<div class="input-group-append">
|
|
<button
|
|
type="button"
|
|
class="btn btn-outline-secondary"
|
|
appA11yTitle="{{ 'copyValue' | i18n }}"
|
|
(click)="copy(callbackPath)"
|
|
>
|
|
<i class="bwi bwi-lg bwi-clone" aria-hidden="true"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>{{ "signedOutCallbackPath" | i18n }}</label>
|
|
<div class="input-group">
|
|
<input class="form-control" readonly [value]="signedOutCallbackPath" />
|
|
<div class="input-group-append">
|
|
<button
|
|
type="button"
|
|
class="btn btn-outline-secondary"
|
|
appA11yTitle="{{ 'copyValue' | i18n }}"
|
|
(click)="copy(signedOutCallbackPath)"
|
|
>
|
|
<i class="bwi bwi-lg bwi-clone" aria-hidden="true"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="authority">{{ "authority" | i18n }}</label>
|
|
<input class="form-control" formControlName="authority" id="authority" />
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="clientId">{{ "clientId" | i18n }}</label>
|
|
<input class="form-control" formControlName="clientId" id="clientId" />
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="clientSecret">{{ "clientSecret" | i18n }}</label>
|
|
<input class="form-control" formControlName="clientSecret" id="clientSecret" />
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="metadataAddress">{{ "metadataAddress" | i18n }}</label>
|
|
<input class="form-control" formControlName="metadataAddress" id="metadataAddress" />
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="redirectBehavior">{{ "oidcRedirectBehavior" | i18n }}</label>
|
|
<select class="form-control" formControlName="redirectBehavior" id="redirectBehavior">
|
|
<option [ngValue]="0">Redirect GET</option>
|
|
<option [ngValue]="1">Form POST</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<div class="form-check">
|
|
<input
|
|
class="form-check-input"
|
|
type="checkbox"
|
|
id="getClaimsFromUserInfoEndpoint"
|
|
formControlName="getClaimsFromUserInfoEndpoint"
|
|
/>
|
|
<label class="form-check-label" for="getClaimsFromUserInfoEndpoint">
|
|
{{ "getClaimsFromUserInfoEndpoint" | i18n }}
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="additionalScopes">{{ "additionalScopes" | i18n }}</label>
|
|
<input class="form-control" formControlName="additionalScopes" id="additionalScopes" />
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="additionalUserIdClaimTypes">{{ "additionalUserIdClaimTypes" | i18n }}</label>
|
|
<input
|
|
class="form-control"
|
|
formControlName="additionalUserIdClaimTypes"
|
|
id="additionalUserIdClaimTypes"
|
|
/>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="additionalEmailClaimTypes">{{ "additionalEmailClaimTypes" | i18n }}</label>
|
|
<input
|
|
class="form-control"
|
|
formControlName="additionalEmailClaimTypes"
|
|
id="additionalEmailClaimTypes"
|
|
/>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="additionalNameClaimTypes">{{ "additionalNameClaimTypes" | i18n }}</label>
|
|
<input
|
|
class="form-control"
|
|
formControlName="additionalNameClaimTypes"
|
|
id="additionalNameClaimTypes"
|
|
/>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="acrValues">{{ "acrValues" | i18n }}</label>
|
|
<input class="form-control" formControlName="acrValues" id="acrValues" />
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="expectedReturnAcrValue">{{ "expectedReturnAcrValue" | i18n }}</label>
|
|
<input
|
|
class="form-control"
|
|
formControlName="expectedReturnAcrValue"
|
|
id="expectedReturnAcrValue"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div *ngIf="data.value.configType == 2">
|
|
<!-- SAML2 SP -->
|
|
<div class="config-section">
|
|
<h2>{{ "samlSpConfig" | i18n }}</h2>
|
|
<div class="form-group">
|
|
<label>{{ "spEntityId" | i18n }}</label>
|
|
<div class="input-group">
|
|
<input class="form-control" readonly [value]="spEntityId" />
|
|
<div class="input-group-append">
|
|
<button
|
|
type="button"
|
|
class="btn btn-outline-secondary"
|
|
appA11yTitle="{{ 'copyValue' | i18n }}"
|
|
(click)="copy(spEntityId)"
|
|
>
|
|
<i class="bwi bwi-lg bwi-clone" aria-hidden="true"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>{{ "spMetadataUrl" | i18n }}</label>
|
|
<div class="input-group">
|
|
<input class="form-control" readonly [value]="spMetadataUrl" />
|
|
<div class="input-group-append">
|
|
<button
|
|
type="button"
|
|
class="btn btn-outline-secondary"
|
|
appA11yTitle="{{ 'launch' | i18n }}"
|
|
(click)="launchUri(spMetadataUrl)"
|
|
>
|
|
<i class="bwi bwi-lg bwi-external-link" aria-hidden="true"></i>
|
|
</button>
|
|
<button
|
|
type="button"
|
|
class="btn btn-outline-secondary"
|
|
appA11yTitle="{{ 'copyValue' | i18n }}"
|
|
(click)="copy(spMetadataUrl)"
|
|
>
|
|
<i class="bwi bwi-lg bwi-clone" aria-hidden="true"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>{{ "spAcsUrl" | i18n }}</label>
|
|
<div class="input-group">
|
|
<input class="form-control" readonly [value]="spAcsUrl" />
|
|
<div class="input-group-append">
|
|
<button
|
|
type="button"
|
|
class="btn btn-outline-secondary"
|
|
appA11yTitle="{{ 'copyValue' | i18n }}"
|
|
(click)="copy(spAcsUrl)"
|
|
>
|
|
<i class="bwi bwi-lg bwi-clone" aria-hidden="true"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="spNameIdFormat">{{ "spNameIdFormat" | i18n }}</label>
|
|
<select class="form-control" formControlName="spNameIdFormat" id="spNameIdFormat">
|
|
<option [ngValue]="0">Not Configured</option>
|
|
<option [ngValue]="1">Unspecified</option>
|
|
<option [ngValue]="2">Email Address</option>
|
|
<option [ngValue]="3">X.509 Subject Name</option>
|
|
<option [ngValue]="4">Windows Domain Qualified Name</option>
|
|
<option [ngValue]="5">Kerberos Principal Name</option>
|
|
<option [ngValue]="6">Entity Identifier</option>
|
|
<option [ngValue]="7">Persistent</option>
|
|
<option [ngValue]="8">Transient</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="spOutboundSigningAlgorithm">{{ "spOutboundSigningAlgorithm" | i18n }}</label>
|
|
<select
|
|
class="form-control"
|
|
formControlName="spOutboundSigningAlgorithm"
|
|
id="spOutboundSigningAlgorithm"
|
|
>
|
|
<option *ngFor="let o of samlSigningAlgorithms" [ngValue]="o">{{ o }}</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="spSigningBehavior">{{ "spSigningBehavior" | i18n }}</label>
|
|
<select class="form-control" formControlName="spSigningBehavior" id="spSigningBehavior">
|
|
<option [ngValue]="0">If IdP Wants Authn Requests Signed</option>
|
|
<option [ngValue]="1">Always</option>
|
|
<option [ngValue]="3">Never</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="spMinIncomingSigningAlgorithm">{{
|
|
"spMinIncomingSigningAlgorithm" | i18n
|
|
}}</label>
|
|
<select
|
|
class="form-control"
|
|
formControlName="spMinIncomingSigningAlgorithm"
|
|
id="spMinIncomingSigningAlgorithm"
|
|
>
|
|
<option *ngFor="let o of samlSigningAlgorithms" [ngValue]="o">{{ o }}</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<div class="form-check">
|
|
<input
|
|
class="form-check-input"
|
|
type="checkbox"
|
|
id="spWantAssertionsSigned"
|
|
formControlName="spWantAssertionsSigned"
|
|
/>
|
|
<label class="form-check-label" for="spWantAssertionsSigned">
|
|
{{ "spWantAssertionsSigned" | i18n }}
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<div class="form-check">
|
|
<input
|
|
class="form-check-input"
|
|
type="checkbox"
|
|
id="spValidateCertificates"
|
|
formControlName="spValidateCertificates"
|
|
/>
|
|
<label class="form-check-label" for="spValidateCertificates">
|
|
{{ "spValidateCertificates" | i18n }}
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- SAML2 IDP -->
|
|
<div class="config-section">
|
|
<h2>{{ "samlIdpConfig" | i18n }}</h2>
|
|
|
|
<div class="form-group">
|
|
<label for="idpEntityId">{{ "idpEntityId" | i18n }}</label>
|
|
<input class="form-control" formControlName="idpEntityId" id="idpEntityId" />
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="idpBindingType">{{ "idpBindingType" | i18n }}</label>
|
|
<select class="form-control" formControlName="idpBindingType" id="idpBindingType">
|
|
<option [ngValue]="1">Redirect</option>
|
|
<option [ngValue]="2">HTTP POST</option>
|
|
<option [ngValue]="4">Artifact</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="idpSingleSignOnServiceUrl">{{ "idpSingleSignOnServiceUrl" | i18n }}</label>
|
|
<input
|
|
class="form-control"
|
|
formControlName="idpSingleSignOnServiceUrl"
|
|
id="idpSingleSignOnServiceUrl"
|
|
/>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="idpSingleLogoutServiceUrl">{{ "idpSingleLogoutServiceUrl" | i18n }}</label>
|
|
<input
|
|
class="form-control"
|
|
formControlName="idpSingleLogoutServiceUrl"
|
|
id="idpSingleLogoutServiceUrl"
|
|
/>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="idpArtifactResolutionServiceUrl">{{
|
|
"idpArtifactResolutionServiceUrl" | i18n
|
|
}}</label>
|
|
<input
|
|
class="form-control"
|
|
formControlName="idpArtifactResolutionServiceUrl"
|
|
id="idpArtifactResolutionServiceUrl"
|
|
/>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="idpX509PublicCert">{{ "idpX509PublicCert" | i18n }}</label>
|
|
<textarea
|
|
formControlName="idpX509PublicCert"
|
|
class="form-control form-control-sm text-monospace"
|
|
rows="6"
|
|
id="idpX509PublicCert"
|
|
></textarea>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="idpOutboundSigningAlgorithm">{{ "idpOutboundSigningAlgorithm" | i18n }}</label>
|
|
<select
|
|
class="form-control"
|
|
formControlName="idpOutboundSigningAlgorithm"
|
|
id="idpOutboundSigningAlgorithm"
|
|
>
|
|
<option *ngFor="let o of samlSigningAlgorithms" [ngValue]="o">{{ o }}</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group" [hidden]="true">
|
|
<!--TODO: Unhide once Unsolicited IdP Response is supported-->
|
|
<div class="form-check">
|
|
<input
|
|
class="form-check-input"
|
|
type="checkbox"
|
|
id="idpAllowUnsolicitedAuthnResponse"
|
|
formControlName="idpAllowUnsolicitedAuthnResponse"
|
|
/>
|
|
<label class="form-check-label" for="idpAllowUnsolicitedAuthnResponse">
|
|
{{ "idpAllowUnsolicitedAuthnResponse" | i18n }}
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<div class="form-check">
|
|
<input
|
|
class="form-check-input"
|
|
type="checkbox"
|
|
id="idpDisableOutboundLogoutRequests"
|
|
formControlName="idpDisableOutboundLogoutRequests"
|
|
/>
|
|
<label class="form-check-label" for="idpDisableOutboundLogoutRequests">
|
|
{{ "idpDisableOutboundLogoutRequests" | i18n }}
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<div class="form-check">
|
|
<input
|
|
class="form-check-input"
|
|
type="checkbox"
|
|
id="idpWantAuthnRequestsSigned"
|
|
formControlName="idpWantAuthnRequestsSigned"
|
|
/>
|
|
<label class="form-check-label" for="idpWantAuthnRequestsSigned">
|
|
{{ "idpWantAuthnRequestsSigned" | i18n }}
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<button type="submit" class="btn btn-primary btn-submit" [disabled]="form.loading">
|
|
<i class="bwi bwi-spinner bwi-spin" title="{{ 'loading' | i18n }}" aria-hidden="true"></i>
|
|
<span>{{ "save" | i18n }}</span>
|
|
</button>
|
|
</form>
|