2021-04-01 13:39:59 +00:00
import { CryptoApi , FlowDesignationEnum , FlowsApi , OAuth2Provider , OAuth2ProviderClientTypeEnum , OAuth2ProviderIssuerModeEnum , OAuth2ProviderJwtAlgEnum , OAuth2ProviderSubModeEnum , PropertymappingsApi , ProvidersApi } from "authentik-api" ;
2021-04-03 17:26:43 +00:00
import { t } from "@lingui/macro" ;
2021-04-01 13:39:59 +00:00
import { customElement , property } from "lit-element" ;
import { html , TemplateResult } from "lit-html" ;
import { DEFAULT_CONFIG } from "../../../api/Config" ;
import { Form } from "../../../elements/forms/Form" ;
import { until } from "lit-html/directives/until" ;
import { ifDefined } from "lit-html/directives/if-defined" ;
import "../../../elements/forms/HorizontalFormElement" ;
2021-04-03 10:08:35 +00:00
import "../../../elements/forms/FormGroup" ;
2021-04-03 12:47:34 +00:00
import { first , randomString } from "../../../utils" ;
2021-04-01 13:39:59 +00:00
@customElement ( "ak-provider-oauth2-form" )
export class OAuth2ProviderFormPage extends Form < OAuth2Provider > {
set providerUUID ( value : number ) {
new ProvidersApi ( DEFAULT_CONFIG ) . providersOauth2Read ( {
id : value ,
} ) . then ( provider = > {
this . provider = provider ;
2021-04-03 12:52:12 +00:00
this . showClientSecret = provider . clientType === OAuth2ProviderClientTypeEnum . Confidential ;
2021-04-01 13:39:59 +00:00
} ) ;
}
@property ( { attribute : false } )
provider? : OAuth2Provider ;
2021-04-03 12:52:12 +00:00
@property ( { type : Boolean } )
showClientSecret = true ;
2021-04-01 13:39:59 +00:00
getSuccessMessage ( ) : string {
if ( this . provider ) {
2021-04-03 17:26:43 +00:00
return t ` Successfully updated provider. ` ;
2021-04-01 13:39:59 +00:00
} else {
2021-04-03 17:26:43 +00:00
return t ` Successfully created provider. ` ;
2021-04-01 13:39:59 +00:00
}
}
send = ( data : OAuth2Provider ) : Promise < OAuth2Provider > = > {
if ( this . provider ) {
return new ProvidersApi ( DEFAULT_CONFIG ) . providersOauth2Update ( {
id : this.provider.pk || 0 ,
data : data
} ) ;
} else {
return new ProvidersApi ( DEFAULT_CONFIG ) . providersOauth2Create ( {
data : data
} ) ;
}
} ;
renderForm ( ) : TemplateResult {
return html ` <form class="pf-c-form pf-m-horizontal">
< ak - form - element - horizontal
2021-04-03 17:26:43 +00:00
label = $ { t ` Name ` }
2021-04-01 13:39:59 +00:00
? required = $ { true }
name = "name" >
< input type = "text" value = "${ifDefined(this.provider?.name)}" class = "pf-c-form-control" required >
< / a k - f o r m - e l e m e n t - h o r i z o n t a l >
< ak - form - element - horizontal
2021-04-03 17:26:43 +00:00
label = $ { t ` Authorization flow ` }
2021-04-01 13:39:59 +00:00
? required = $ { true }
name = "authorizationFlow" >
< select class = "pf-c-form-control" >
$ { until ( new FlowsApi ( DEFAULT_CONFIG ) . flowsInstancesList ( {
ordering : "pk" ,
designation : FlowDesignationEnum.Authorization ,
} ) . then ( flows = > {
return flows . results . map ( flow = > {
2021-04-02 10:48:09 +00:00
return html ` <option value= ${ ifDefined ( flow . pk ) } ?selected= ${ this . provider ? . authorizationFlow === flow . pk } > ${ flow . name } ( ${ flow . slug } )</option> ` ;
2021-04-01 13:39:59 +00:00
} ) ;
2021-04-03 22:24:06 +00:00
} ) , html ` <option> ${ t ` Loading... ` } </option> ` ) }
2021-04-01 13:39:59 +00:00
< / select >
2021-04-03 17:26:43 +00:00
< p class = "pf-c-form__helper-text" > $ { t ` Flow used when authorizing this provider. ` } < / p >
2021-04-01 13:39:59 +00:00
< / a k - f o r m - e l e m e n t - h o r i z o n t a l >
2021-04-03 10:08:35 +00:00
< ak - form - group .expanded = $ { true } >
< span slot = "header" >
2021-04-03 17:26:43 +00:00
$ { t ` Protocol settings ` }
2021-04-03 10:08:35 +00:00
< / span >
< div slot = "body" class = "pf-c-form" >
< ak - form - element - horizontal
2021-04-03 17:26:43 +00:00
label = $ { t ` Client type ` }
2021-04-03 10:08:35 +00:00
? required = $ { true }
name = "clientType" >
2021-04-03 12:52:12 +00:00
< select class = "pf-c-form-control" @ change = $ { ( ev : Event ) = > {
const target = ev . target as HTMLSelectElement ;
if ( target . selectedOptions [ 0 ] . value === OAuth2ProviderClientTypeEnum . Public ) {
this . showClientSecret = false ;
} else {
this . showClientSecret = true ;
}
} } >
2021-04-03 10:08:35 +00:00
< option value = $ { OAuth2ProviderClientTypeEnum.Confidential } ? selected = $ { this.provider ? .clientType = = = OAuth2ProviderClientTypeEnum.Confidential } >
2021-04-03 17:26:43 +00:00
$ { t ` Confidential ` }
2021-04-03 10:08:35 +00:00
< / option >
< option value = $ { OAuth2ProviderClientTypeEnum.Public } ? selected = $ { this.provider ? .clientType = = = OAuth2ProviderClientTypeEnum.Public } >
2021-04-03 17:26:43 +00:00
$ { t ` Public ` }
2021-04-03 10:08:35 +00:00
< / option >
< / select >
2021-04-03 17:26:43 +00:00
< p class = "pf-c-form__helper-text" > $ { t ` Confidential clients are capable of maintaining the confidentiality of their credentials. Public clients are incapable. ` } < / p >
2021-04-03 10:08:35 +00:00
< / a k - f o r m - e l e m e n t - h o r i z o n t a l >
< ak - form - element - horizontal
2021-04-03 17:26:43 +00:00
label = $ { t ` Client ID ` }
2021-04-03 10:08:35 +00:00
? required = $ { true }
name = "clientId" >
2021-04-03 12:47:34 +00:00
< input type = "text" value = "${first(this.provider?.clientId, randomString(40))}" class = "pf-c-form-control" required >
2021-04-03 10:08:35 +00:00
< / a k - f o r m - e l e m e n t - h o r i z o n t a l >
< ak - form - element - horizontal
2021-04-03 12:52:12 +00:00
? hidden = $ { ! this . showClientSecret }
2021-04-03 17:26:43 +00:00
label = $ { t ` Client Secret ` }
2021-04-03 10:08:35 +00:00
name = "clientSecret" >
2021-04-03 12:47:34 +00:00
< input type = "text" value = "${first(this.provider?.clientSecret, randomString(128))}" class = "pf-c-form-control" >
2021-04-03 10:08:35 +00:00
< / a k - f o r m - e l e m e n t - h o r i z o n t a l >
< ak - form - element - horizontal
2021-04-03 17:26:43 +00:00
label = $ { t ` Redirect URIs ` }
2021-04-03 10:08:35 +00:00
name = "redirectUris" >
< textarea class = "pf-c-form-control" > $ { this . provider ? . redirectUris } < / textarea >
< / a k - f o r m - e l e m e n t - h o r i z o n t a l >
2021-04-01 13:39:59 +00:00
< / div >
2021-04-03 10:08:35 +00:00
< / a k - f o r m - g r o u p >
< ak - form - group >
< span slot = "header" >
2021-04-03 17:26:43 +00:00
$ { t ` Advanced protocol settings ` }
2021-04-03 10:08:35 +00:00
< / span >
< div slot = "body" class = "pf-c-form" >
< ak - form - element - horizontal
2021-04-03 17:26:43 +00:00
label = $ { t ` Token validity ` }
2021-04-03 10:08:35 +00:00
? required = $ { true }
name = "tokenValidity" >
< input type = "text" value = "${this.provider?.tokenValidity || " minutes = 10 " } " class = "pf-c-form-control" required >
< / a k - f o r m - e l e m e n t - h o r i z o n t a l >
< ak - form - element - horizontal
2021-04-03 17:26:43 +00:00
label = $ { t ` JWT Algorithm ` }
2021-04-03 10:08:35 +00:00
? required = $ { true }
name = "jwtAlg" >
< select class = "pf-c-form-control" >
< option value = $ { OAuth2ProviderJwtAlgEnum.Rs256 } ? selected = $ { this.provider ? .jwtAlg = = = OAuth2ProviderJwtAlgEnum.Rs256 } >
2021-04-03 17:26:43 +00:00
$ { t ` RS256 (Asymmetric Encryption) ` }
2021-04-03 10:08:35 +00:00
< / option >
< option value = $ { OAuth2ProviderJwtAlgEnum.Hs256 } ? selected = $ { this.provider ? .jwtAlg = = = OAuth2ProviderJwtAlgEnum.Hs256 } >
2021-04-03 17:26:43 +00:00
$ { t ` HS256 (Symmetric Encryption) ` }
2021-04-03 10:08:35 +00:00
< / option >
< / select >
2021-04-03 17:26:43 +00:00
< p class = "pf-c-form__helper-text" > $ { t ` Algorithm used to sign the JWT Tokens. ` } < / p >
2021-04-03 10:08:35 +00:00
< / a k - f o r m - e l e m e n t - h o r i z o n t a l >
< ak - form - element - horizontal
2021-04-03 17:26:43 +00:00
label = $ { t ` Scopes ` }
2021-04-03 10:08:35 +00:00
? required = $ { true }
name = "propertyMappings" >
< select class = "pf-c-form-control" multiple >
$ { until ( new PropertymappingsApi ( DEFAULT_CONFIG ) . propertymappingsScopeList ( {
ordering : "scope_name"
} ) . then ( scopes = > {
return scopes . results . map ( scope = > {
const selected = Array . from ( this . provider ? . propertyMappings || [ ] ) . some ( su = > {
return su == scope . pk ;
} ) ;
return html ` <option value= ${ ifDefined ( scope . pk ) } ?selected= ${ selected } > ${ scope . name } </option> ` ;
} ) ;
2021-04-03 22:24:06 +00:00
} ) , html ` <option> ${ t ` Loading... ` } </option> ` ) }
2021-04-03 10:08:35 +00:00
< / select >
2021-04-03 17:26:43 +00:00
< p class = "pf-c-form__helper-text" > $ { t ` Select which scopes can be used by the client. The client stil has to specify the scope to access the data. ` } < / p >
< p class = "pf-c-form__helper-text" > $ { t ` Hold control/command to select multiple items. ` } < / p >
2021-04-03 10:08:35 +00:00
< / a k - f o r m - e l e m e n t - h o r i z o n t a l >
< ak - form - element - horizontal
2021-04-03 17:26:43 +00:00
label = $ { t ` RSA Key ` }
2021-04-03 10:08:35 +00:00
? required = $ { true }
name = "rsaKey" >
< select class = "pf-c-form-control" >
< option value = "" ? selected = $ { this.provider ? .rsaKey = = = undefined } > -- -- -- -- - < / option >
$ { until ( new CryptoApi ( DEFAULT_CONFIG ) . cryptoCertificatekeypairsList ( {
ordering : "pk" ,
hasKey : "true" ,
} ) . then ( keys = > {
return keys . results . map ( key = > {
return html ` <option value= ${ ifDefined ( key . pk ) } ?selected= ${ this . provider ? . rsaKey === key . pk } > ${ key . name } </option> ` ;
} ) ;
2021-04-03 22:24:06 +00:00
} ) , html ` <option> ${ t ` Loading... ` } </option> ` ) }
2021-04-03 10:08:35 +00:00
< / select >
2021-04-03 17:26:43 +00:00
< p class = "pf-c-form__helper-text" > $ { t ` Key used to sign the tokens. Only required when JWT Algorithm is set to RS256. ` } < / p >
2021-04-03 10:08:35 +00:00
< / a k - f o r m - e l e m e n t - h o r i z o n t a l >
< ak - form - element - horizontal
2021-04-03 17:26:43 +00:00
label = $ { t ` Subject mode ` }
2021-04-03 10:08:35 +00:00
? required = $ { true }
name = "subMode" >
< select class = "pf-c-form-control" >
< option value = "${OAuth2ProviderSubModeEnum.HashedUserId}" ? selected = $ { this.provider ? .subMode = = = OAuth2ProviderSubModeEnum.HashedUserId } >
2021-04-03 17:26:43 +00:00
$ { t ` Based on the Hashed User ID ` }
2021-04-03 10:08:35 +00:00
< / option >
< option value = "${OAuth2ProviderSubModeEnum.UserUsername}" ? selected = $ { this.provider ? .subMode = = = OAuth2ProviderSubModeEnum.UserUsername } >
2021-04-03 17:26:43 +00:00
$ { t ` Based on the username ` }
2021-04-03 10:08:35 +00:00
< / option >
< option value = "${OAuth2ProviderSubModeEnum.UserEmail}" ? selected = $ { this.provider ? .subMode = = = OAuth2ProviderSubModeEnum.UserEmail } >
2021-04-03 17:26:43 +00:00
$ { t ` Based on the User's Email. This is recommended over the UPN method. ` }
2021-04-03 10:08:35 +00:00
< / option >
< option value = "${OAuth2ProviderSubModeEnum.UserUpn}" ? selected = $ { this.provider ? .subMode = = = OAuth2ProviderSubModeEnum.UserUpn } >
2021-04-03 17:26:43 +00:00
$ { t ` Based on the User's UPN, only works if user has a 'upn' attribute set. Use this method only if you have different UPN and Mail domains. ` }
2021-04-03 10:08:35 +00:00
< / option >
< / select >
< p class = "pf-c-form__helper-text" >
2021-04-03 17:26:43 +00:00
$ { t ` Configure what data should be used as unique User Identifier. For most cases, the default should be fine. ` }
2021-04-03 10:08:35 +00:00
< / p >
< / a k - f o r m - e l e m e n t - h o r i z o n t a l >
< ak - form - element - horizontal name = "includeClaimsInIdToken" >
< div class = "pf-c-check" >
< input type = "checkbox" class = "pf-c-check__input" ? checked = $ { this.provider ? .includeClaimsInIdToken | | false } >
< label class = "pf-c-check__label" >
2021-04-03 17:26:43 +00:00
$ { t ` Include claims in id_token ` }
2021-04-03 10:08:35 +00:00
< / label >
< / div >
2021-04-03 17:26:43 +00:00
< p class = "pf-c-form__helper-text" > $ { t ` Include User claims from scopes in the id_token, for applications that don't access the userinfo endpoint. ` } < / p >
2021-04-03 10:08:35 +00:00
< / a k - f o r m - e l e m e n t - h o r i z o n t a l >
< ak - form - element - horizontal
2021-04-03 17:26:43 +00:00
label = $ { t ` Issuer mode ` }
2021-04-03 10:08:35 +00:00
? required = $ { true }
name = "issuerMode" >
< select class = "pf-c-form-control" >
< option value = "${OAuth2ProviderIssuerModeEnum.PerProvider}" ? selected = $ { this.provider ? .issuerMode = = = OAuth2ProviderIssuerModeEnum.PerProvider } >
2021-04-03 17:26:43 +00:00
$ { t ` Each provider has a different issuer, based on the application slug. ` }
2021-04-03 10:08:35 +00:00
< / option >
< option value = "${OAuth2ProviderIssuerModeEnum.Global}" ? selected = $ { this.provider ? .issuerMode = = = OAuth2ProviderIssuerModeEnum.Global } >
2021-04-03 17:26:43 +00:00
$ { t ` Same identifier is used for all providers ` }
2021-04-03 10:08:35 +00:00
< / option >
< / select >
< p class = "pf-c-form__helper-text" >
2021-04-03 17:26:43 +00:00
$ { t ` Configure how the issuer field of the ID Token should be filled. ` }
2021-04-03 10:08:35 +00:00
< / p >
< / a k - f o r m - e l e m e n t - h o r i z o n t a l >
< / div >
< / a k - f o r m - g r o u p >
2021-04-01 13:39:59 +00:00
< / form > ` ;
}
}