2021-08-03 15:52:21 +00:00
|
|
|
import {
|
|
|
|
OAuthSource,
|
|
|
|
SourcesApi,
|
|
|
|
FlowsApi,
|
|
|
|
UserMatchingModeEnum,
|
|
|
|
OAuthSourceRequest,
|
|
|
|
FlowsInstancesListDesignationEnum,
|
|
|
|
} from "authentik-api";
|
2021-04-03 17:26:43 +00:00
|
|
|
import { t } from "@lingui/macro";
|
2021-04-02 13:15:19 +00:00
|
|
|
import { customElement, property } from "lit-element";
|
|
|
|
import { html, TemplateResult } from "lit-html";
|
|
|
|
import { DEFAULT_CONFIG } from "../../../api/Config";
|
|
|
|
import "../../../elements/forms/FormGroup";
|
|
|
|
import "../../../elements/forms/HorizontalFormElement";
|
|
|
|
import { ifDefined } from "lit-html/directives/if-defined";
|
|
|
|
import { until } from "lit-html/directives/until";
|
2021-04-03 22:36:53 +00:00
|
|
|
import { first } from "../../../utils";
|
2021-05-11 09:48:34 +00:00
|
|
|
import { ModelForm } from "../../../elements/forms/ModelForm";
|
2021-04-02 13:15:19 +00:00
|
|
|
|
|
|
|
@customElement("ak-source-oauth-form")
|
2021-05-11 09:48:34 +00:00
|
|
|
export class OAuthSourceForm extends ModelForm<OAuthSource, string> {
|
|
|
|
loadInstance(pk: string): Promise<OAuthSource> {
|
2021-08-03 15:52:21 +00:00
|
|
|
return new SourcesApi(DEFAULT_CONFIG)
|
|
|
|
.sourcesOauthRetrieve({
|
|
|
|
slug: pk,
|
|
|
|
})
|
|
|
|
.then((source) => {
|
|
|
|
this.showUrlOptions = first(source.type?.urlsCustomizable, false);
|
|
|
|
return source;
|
|
|
|
});
|
2021-04-02 13:15:19 +00:00
|
|
|
}
|
|
|
|
|
2021-04-17 17:16:23 +00:00
|
|
|
@property()
|
|
|
|
modelName?: string;
|
|
|
|
|
2021-08-03 15:52:21 +00:00
|
|
|
@property({ type: Boolean })
|
2021-04-02 13:15:19 +00:00
|
|
|
showUrlOptions = false;
|
|
|
|
|
2021-08-03 15:52:21 +00:00
|
|
|
@property({ type: Boolean })
|
2021-04-17 19:13:33 +00:00
|
|
|
showRequestTokenURL = false;
|
|
|
|
|
2021-04-02 13:15:19 +00:00
|
|
|
getSuccessMessage(): string {
|
2021-05-11 09:48:34 +00:00
|
|
|
if (this.instance) {
|
2021-04-03 17:26:43 +00:00
|
|
|
return t`Successfully updated source.`;
|
2021-04-02 13:15:19 +00:00
|
|
|
} else {
|
2021-04-03 17:26:43 +00:00
|
|
|
return t`Successfully created source.`;
|
2021-04-02 13:15:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
send = (data: OAuthSource): Promise<OAuthSource> => {
|
2021-06-01 21:36:21 +00:00
|
|
|
if (this.instance?.slug) {
|
2021-05-11 11:31:33 +00:00
|
|
|
return new SourcesApi(DEFAULT_CONFIG).sourcesOauthPartialUpdate({
|
2021-05-11 09:48:34 +00:00
|
|
|
slug: this.instance.slug,
|
2021-08-03 15:52:21 +00:00
|
|
|
patchedOAuthSourceRequest: data,
|
2021-04-02 13:15:19 +00:00
|
|
|
});
|
|
|
|
} else {
|
|
|
|
return new SourcesApi(DEFAULT_CONFIG).sourcesOauthCreate({
|
2021-08-03 15:52:21 +00:00
|
|
|
oAuthSourceRequest: data as unknown as OAuthSourceRequest,
|
2021-04-02 13:15:19 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
renderUrlOptions(): TemplateResult {
|
|
|
|
if (!this.showUrlOptions) {
|
|
|
|
return html``;
|
|
|
|
}
|
2021-08-03 15:52:21 +00:00
|
|
|
return html` <ak-form-group>
|
|
|
|
<span slot="header"> ${t`URL settings`} </span>
|
|
|
|
<div slot="body" class="pf-c-form">
|
|
|
|
<ak-form-element-horizontal
|
|
|
|
label=${t`Authorization URL`}
|
|
|
|
?required=${true}
|
|
|
|
name="authorizationUrl"
|
|
|
|
>
|
|
|
|
<input
|
|
|
|
type="text"
|
|
|
|
value="${first(this.instance?.authorizationUrl, "")}"
|
|
|
|
class="pf-c-form-control"
|
|
|
|
required
|
|
|
|
/>
|
|
|
|
<p class="pf-c-form__helper-text">
|
|
|
|
${t`URL the user is redirect to to consent the authorization.`}
|
|
|
|
</p>
|
|
|
|
</ak-form-element-horizontal>
|
|
|
|
<ak-form-element-horizontal
|
|
|
|
label=${t`Access token URL`}
|
|
|
|
?required=${true}
|
|
|
|
name="accessTokenUrl"
|
|
|
|
>
|
|
|
|
<input
|
|
|
|
type="text"
|
|
|
|
value="${first(this.instance?.accessTokenUrl, "")}"
|
|
|
|
class="pf-c-form-control"
|
|
|
|
required
|
|
|
|
/>
|
|
|
|
<p class="pf-c-form__helper-text">
|
|
|
|
${t`URL used by authentik to retrieve tokens.`}
|
|
|
|
</p>
|
|
|
|
</ak-form-element-horizontal>
|
|
|
|
<ak-form-element-horizontal
|
|
|
|
label=${t`Profile URL`}
|
|
|
|
?required=${true}
|
|
|
|
name="profileUrl"
|
|
|
|
>
|
|
|
|
<input
|
|
|
|
type="text"
|
|
|
|
value="${first(this.instance?.profileUrl, "")}"
|
|
|
|
class="pf-c-form-control"
|
|
|
|
required
|
|
|
|
/>
|
|
|
|
<p class="pf-c-form__helper-text">
|
|
|
|
${t`URL used by authentik to get user information.`}
|
|
|
|
</p>
|
|
|
|
</ak-form-element-horizontal>
|
|
|
|
${this.showRequestTokenURL
|
|
|
|
? html`<ak-form-element-horizontal
|
|
|
|
label=${t`Request token URL`}
|
|
|
|
name="requestTokenUrl"
|
|
|
|
>
|
|
|
|
<input
|
|
|
|
type="text"
|
|
|
|
value="${first(this.instance?.requestTokenUrl, "")}"
|
|
|
|
class="pf-c-form-control"
|
|
|
|
/>
|
|
|
|
<p class="pf-c-form__helper-text">
|
|
|
|
${t`URL used to request the initial token. This URL is only required for OAuth 1.`}
|
|
|
|
</p>
|
|
|
|
</ak-form-element-horizontal> `
|
|
|
|
: html``}
|
|
|
|
</div>
|
|
|
|
</ak-form-group>`;
|
2021-04-02 13:15:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
renderForm(): TemplateResult {
|
|
|
|
return html`<form class="pf-c-form pf-m-horizontal">
|
2021-08-03 15:52:21 +00:00
|
|
|
<ak-form-element-horizontal label=${t`Name`} ?required=${true} name="name">
|
|
|
|
<input
|
|
|
|
type="text"
|
|
|
|
value="${ifDefined(this.instance?.name)}"
|
|
|
|
class="pf-c-form-control"
|
|
|
|
required
|
|
|
|
/>
|
2021-04-02 13:15:19 +00:00
|
|
|
</ak-form-element-horizontal>
|
2021-08-03 15:52:21 +00:00
|
|
|
<ak-form-element-horizontal label=${t`Slug`} ?required=${true} name="slug">
|
|
|
|
<input
|
|
|
|
type="text"
|
|
|
|
value="${ifDefined(this.instance?.slug)}"
|
|
|
|
class="pf-c-form-control"
|
|
|
|
required
|
|
|
|
/>
|
2021-04-02 13:15:19 +00:00
|
|
|
</ak-form-element-horizontal>
|
|
|
|
<ak-form-element-horizontal name="enabled">
|
|
|
|
<div class="pf-c-check">
|
2021-08-03 15:52:21 +00:00
|
|
|
<input
|
|
|
|
type="checkbox"
|
|
|
|
class="pf-c-check__input"
|
|
|
|
?checked=${first(this.instance?.enabled, true)}
|
|
|
|
/>
|
|
|
|
<label class="pf-c-check__label"> ${t`Enabled`} </label>
|
2021-04-02 13:15:19 +00:00
|
|
|
</div>
|
|
|
|
</ak-form-element-horizontal>
|
2021-05-04 10:02:16 +00:00
|
|
|
<ak-form-element-horizontal
|
|
|
|
label=${t`User matching mode`}
|
|
|
|
?required=${true}
|
2021-08-03 15:52:21 +00:00
|
|
|
name="userMatchingMode"
|
|
|
|
>
|
2021-05-04 10:02:16 +00:00
|
|
|
<select class="pf-c-form-control">
|
2021-08-03 15:52:21 +00:00
|
|
|
<option
|
|
|
|
value=${UserMatchingModeEnum.Identifier}
|
|
|
|
?selected=${this.instance?.userMatchingMode ===
|
|
|
|
UserMatchingModeEnum.Identifier}
|
|
|
|
>
|
2021-05-04 10:02:16 +00:00
|
|
|
${t`Link users on unique identifier`}
|
|
|
|
</option>
|
2021-08-03 15:52:21 +00:00
|
|
|
<option
|
|
|
|
value=${UserMatchingModeEnum.UsernameLink}
|
|
|
|
?selected=${this.instance?.userMatchingMode ===
|
|
|
|
UserMatchingModeEnum.UsernameLink}
|
|
|
|
>
|
2021-05-04 10:02:16 +00:00
|
|
|
${t`Link to a user with identical email address. Can have security implications when a source doesn't validate email addresses`}
|
|
|
|
</option>
|
2021-08-03 15:52:21 +00:00
|
|
|
<option
|
|
|
|
value=${UserMatchingModeEnum.UsernameDeny}
|
|
|
|
?selected=${this.instance?.userMatchingMode ===
|
|
|
|
UserMatchingModeEnum.UsernameDeny}
|
|
|
|
>
|
2021-05-04 10:02:16 +00:00
|
|
|
${t`Use the user's email address, but deny enrollment when the email address already exists.`}
|
|
|
|
</option>
|
2021-08-03 15:52:21 +00:00
|
|
|
<option
|
|
|
|
value=${UserMatchingModeEnum.EmailLink}
|
|
|
|
?selected=${this.instance?.userMatchingMode ===
|
|
|
|
UserMatchingModeEnum.EmailLink}
|
|
|
|
>
|
2021-05-04 10:02:16 +00:00
|
|
|
${t`Link to a user with identical username address. Can have security implications when a username is used with another source.`}
|
|
|
|
</option>
|
2021-08-03 15:52:21 +00:00
|
|
|
<option
|
|
|
|
value=${UserMatchingModeEnum.EmailDeny}
|
|
|
|
?selected=${this.instance?.userMatchingMode ===
|
|
|
|
UserMatchingModeEnum.EmailDeny}
|
|
|
|
>
|
2021-05-04 10:02:16 +00:00
|
|
|
${t`Use the user's username, but deny enrollment when the username already exists.`}
|
|
|
|
</option>
|
|
|
|
</select>
|
|
|
|
</ak-form-element-horizontal>
|
2021-04-02 13:15:19 +00:00
|
|
|
|
|
|
|
<ak-form-group .expanded=${true}>
|
2021-08-03 15:52:21 +00:00
|
|
|
<span slot="header"> ${t`Protocol settings`} </span>
|
2021-04-02 13:15:19 +00:00
|
|
|
<div slot="body" class="pf-c-form">
|
|
|
|
<ak-form-element-horizontal
|
2021-04-03 17:26:43 +00:00
|
|
|
label=${t`Consumer key`}
|
2021-04-02 13:15:19 +00:00
|
|
|
?required=${true}
|
2021-08-03 15:52:21 +00:00
|
|
|
name="consumerKey"
|
|
|
|
>
|
|
|
|
<input
|
|
|
|
type="text"
|
|
|
|
value="${ifDefined(this.instance?.consumerKey)}"
|
|
|
|
class="pf-c-form-control"
|
|
|
|
required
|
|
|
|
/>
|
2021-04-02 13:15:19 +00:00
|
|
|
</ak-form-element-horizontal>
|
|
|
|
<ak-form-element-horizontal
|
2021-04-03 17:26:43 +00:00
|
|
|
label=${t`Consumer secret`}
|
2021-04-02 13:15:19 +00:00
|
|
|
?required=${true}
|
2021-05-11 09:48:34 +00:00
|
|
|
?writeOnly=${this.instance !== undefined}
|
2021-08-03 15:52:21 +00:00
|
|
|
name="consumerSecret"
|
|
|
|
>
|
|
|
|
<input type="text" value="" class="pf-c-form-control" required />
|
2021-04-02 13:15:19 +00:00
|
|
|
</ak-form-element-horizontal>
|
2021-08-03 15:52:21 +00:00
|
|
|
<ak-form-element-horizontal label=${t`Provider type`} name="providerType">
|
|
|
|
<select
|
|
|
|
class="pf-c-form-control"
|
|
|
|
@change=${(ev: Event) => {
|
|
|
|
const el = ev.target as HTMLSelectElement;
|
|
|
|
const selected = el.selectedOptions[0];
|
|
|
|
this.showUrlOptions = "data-urls-custom" in selected.attributes;
|
|
|
|
this.showRequestTokenURL =
|
|
|
|
"data-request-token" in selected.attributes;
|
|
|
|
if (!this.instance) {
|
|
|
|
this.instance = {} as OAuthSource;
|
|
|
|
}
|
|
|
|
this.instance.providerType = selected.value;
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
${until(
|
|
|
|
new SourcesApi(DEFAULT_CONFIG)
|
|
|
|
.sourcesOauthSourceTypesList()
|
|
|
|
.then((types) => {
|
|
|
|
return types.map((type) => {
|
|
|
|
let selected =
|
|
|
|
this.instance?.providerType === type.slug;
|
|
|
|
const modelSlug = this.modelName
|
|
|
|
?.replace("oauthsource", "")
|
|
|
|
.replace("-", "");
|
|
|
|
const typeSlug = type.slug.replace("-", "");
|
|
|
|
if (!this.instance?.pk) {
|
|
|
|
if (modelSlug === typeSlug) {
|
|
|
|
selected = true;
|
|
|
|
this.showUrlOptions = type.urlsCustomizable;
|
|
|
|
this.showRequestTokenURL =
|
|
|
|
type.requestTokenUrl !== null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return html`<option
|
|
|
|
?data-urls-custom=${type.urlsCustomizable}
|
|
|
|
?data-request-token=${type.requestTokenUrl}
|
|
|
|
value=${type.slug}
|
|
|
|
?selected=${selected}
|
|
|
|
>
|
|
|
|
${type.name}
|
|
|
|
</option>`;
|
|
|
|
});
|
|
|
|
}),
|
|
|
|
html`<option>${t`Loading...`}</option>`,
|
|
|
|
)}
|
2021-04-02 13:15:19 +00:00
|
|
|
</select>
|
|
|
|
</ak-form-element-horizontal>
|
|
|
|
</div>
|
|
|
|
</ak-form-group>
|
|
|
|
${this.renderUrlOptions()}
|
|
|
|
<ak-form-group>
|
2021-08-03 15:52:21 +00:00
|
|
|
<span slot="header"> ${t`Flow settings`} </span>
|
2021-04-02 13:15:19 +00:00
|
|
|
<div slot="body" class="pf-c-form">
|
|
|
|
<ak-form-element-horizontal
|
2021-04-03 17:26:43 +00:00
|
|
|
label=${t`Authentication flow`}
|
2021-04-02 13:15:19 +00:00
|
|
|
?required=${true}
|
2021-08-03 15:52:21 +00:00
|
|
|
name="authenticationFlow"
|
|
|
|
>
|
2021-04-02 13:15:19 +00:00
|
|
|
<select class="pf-c-form-control">
|
2021-08-03 15:52:21 +00:00
|
|
|
${until(
|
|
|
|
new FlowsApi(DEFAULT_CONFIG)
|
|
|
|
.flowsInstancesList({
|
|
|
|
ordering: "pk",
|
|
|
|
designation:
|
|
|
|
FlowsInstancesListDesignationEnum.Authentication,
|
|
|
|
})
|
|
|
|
.then((flows) => {
|
|
|
|
return flows.results.map((flow) => {
|
|
|
|
let selected =
|
|
|
|
this.instance?.authenticationFlow === flow.pk;
|
|
|
|
if (
|
|
|
|
!this.instance?.pk &&
|
|
|
|
!this.instance?.authenticationFlow &&
|
|
|
|
flow.slug === "default-source-authentication"
|
|
|
|
) {
|
|
|
|
selected = true;
|
|
|
|
}
|
|
|
|
return html`<option
|
|
|
|
value=${ifDefined(flow.pk)}
|
|
|
|
?selected=${selected}
|
|
|
|
>
|
|
|
|
${flow.name} (${flow.slug})
|
|
|
|
</option>`;
|
|
|
|
});
|
|
|
|
}),
|
|
|
|
html`<option>${t`Loading...`}</option>`,
|
|
|
|
)}
|
2021-04-02 13:15:19 +00:00
|
|
|
</select>
|
2021-08-03 15:52:21 +00:00
|
|
|
<p class="pf-c-form__helper-text">
|
|
|
|
${t`Flow to use when authenticating existing users.`}
|
|
|
|
</p>
|
2021-04-02 13:15:19 +00:00
|
|
|
</ak-form-element-horizontal>
|
|
|
|
<ak-form-element-horizontal
|
2021-04-03 17:26:43 +00:00
|
|
|
label=${t`Enrollment flow`}
|
2021-04-02 13:15:19 +00:00
|
|
|
?required=${true}
|
2021-08-03 15:52:21 +00:00
|
|
|
name="enrollmentFlow"
|
|
|
|
>
|
2021-04-02 13:15:19 +00:00
|
|
|
<select class="pf-c-form-control">
|
2021-08-03 15:52:21 +00:00
|
|
|
${until(
|
|
|
|
new FlowsApi(DEFAULT_CONFIG)
|
|
|
|
.flowsInstancesList({
|
|
|
|
ordering: "pk",
|
|
|
|
designation: FlowsInstancesListDesignationEnum.Enrollment,
|
|
|
|
})
|
|
|
|
.then((flows) => {
|
|
|
|
return flows.results.map((flow) => {
|
|
|
|
let selected =
|
|
|
|
this.instance?.enrollmentFlow === flow.pk;
|
|
|
|
if (
|
|
|
|
!this.instance?.pk &&
|
|
|
|
!this.instance?.enrollmentFlow &&
|
|
|
|
flow.slug === "default-source-enrollment"
|
|
|
|
) {
|
|
|
|
selected = true;
|
|
|
|
}
|
|
|
|
return html`<option
|
|
|
|
value=${ifDefined(flow.pk)}
|
|
|
|
?selected=${selected}
|
|
|
|
>
|
|
|
|
${flow.name} (${flow.slug})
|
|
|
|
</option>`;
|
|
|
|
});
|
|
|
|
}),
|
|
|
|
html`<option>${t`Loading...`}</option>`,
|
|
|
|
)}
|
2021-04-02 13:15:19 +00:00
|
|
|
</select>
|
2021-08-03 15:52:21 +00:00
|
|
|
<p class="pf-c-form__helper-text">
|
|
|
|
${t`Flow to use when enrolling new users.`}
|
|
|
|
</p>
|
2021-04-02 13:15:19 +00:00
|
|
|
</ak-form-element-horizontal>
|
|
|
|
</div>
|
|
|
|
</ak-form-group>
|
|
|
|
</form>`;
|
|
|
|
}
|
|
|
|
}
|