providers/proxy: add initial header token auth (#4421)

* initial implementation

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* check for openid/profile claims

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* include jwks sources in proxy provider

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add web ui for jwks

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* only show sources with JWKS data configured

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix introspection tests

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* start basic

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add basic auth

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add docs, update admonitions

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add client_id to api, add tab for auth

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* update locale

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
Jens L
2023-01-13 16:22:03 +01:00
committed by GitHub
parent 31c6ea9fda
commit cd12e177ea
54 changed files with 830 additions and 162 deletions

View File

@ -400,6 +400,7 @@ ${this.instance?.redirectUris}</textarea
new SourcesApi(DEFAULT_CONFIG)
.sourcesOauthList({
ordering: "name",
hasJwks: true,
})
.then((sources) => {
return sources.results.map((source) => {

View File

@ -31,6 +31,7 @@ import {
ProvidersApi,
ProxyMode,
ProxyProvider,
SourcesApi,
} from "@goauthentik/api";
@customElement("ak-provider-proxy-form")
@ -385,7 +386,10 @@ export class ProxyProviderFormPage extends ModelForm<ProxyProvider, number> {
>
</ak-search-select>
</ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Scopes`} name="propertyMappings">
<ak-form-element-horizontal
label=${t`Additional scopes`}
name="propertyMappings"
>
<select class="pf-c-form-control" multiple>
${until(
new PropertymappingsApi(DEFAULT_CONFIG)
@ -440,7 +444,11 @@ ${this.instance?.skipPathRegex}</textarea
${t`When using proxy or forward auth (single application) mode, the requested URL Path is checked against the regular expressions. When using forward auth (domain mode), the full requested URL including scheme and host is matched against the regular expressions.`}
</p>
</ak-form-element-horizontal>
</div>
</ak-form-group>
<ak-form-group>
<span slot="header">${t`Authentication settings`}</span>
<div slot="body" class="pf-c-form">
<ak-form-element-horizontal name="basicAuthEnabled">
<label class="pf-c-switch">
<input
@ -458,14 +466,47 @@ ${this.instance?.skipPathRegex}</textarea
</span>
</span>
<span class="pf-c-switch__label"
>${t`Set HTTP-Basic Authentication`}</span
>${t`Send HTTP-Basic Authentication`}</span
>
</label>
<p class="pf-c-form__helper-text">
${t`Set a custom HTTP-Basic Authentication header based on values from authentik.`}
${t`Send a custom HTTP-Basic Authentication header based on values from authentik.`}
</p>
</ak-form-element-horizontal>
${this.showHttpBasic ? this.renderHttpBasic() : html``}
<ak-form-element-horizontal label=${t`Trusted OIDC Sources`} name="jwksSources">
<select class="pf-c-form-control" multiple>
${until(
new SourcesApi(DEFAULT_CONFIG)
.sourcesOauthList({
ordering: "name",
hasJwks: true,
})
.then((sources) => {
return sources.results.map((source) => {
const selected = (
this.instance?.jwksSources || []
).some((su) => {
return su == source.pk;
});
return html`<option
value=${source.pk}
?selected=${selected}
>
${source.name} (${source.slug})
</option>`;
});
}),
html`<option>${t`Loading...`}</option>`,
)}
</select>
<p class="pf-c-form__helper-text">
${t`JWTs signed by certificates configured in the selected sources can be used to authenticate to this provider.`}
</p>
<p class="pf-c-form__helper-text">
${t`Hold control/command to select multiple items.`}
</p>
</ak-form-element-horizontal>
</div>
</ak-form-group>
</form>`;

View File

@ -10,10 +10,12 @@ import MDNginxStandalone from "@goauthentik/docs/providers/proxy/_nginx_standalo
import MDTraefikCompose from "@goauthentik/docs/providers/proxy/_traefik_compose.md";
import MDTraefikIngress from "@goauthentik/docs/providers/proxy/_traefik_ingress.md";
import MDTraefikStandalone from "@goauthentik/docs/providers/proxy/_traefik_standalone.md";
import MDHeaderAuthentication from "@goauthentik/docs/providers/proxy/header_authentication.md";
import { AKElement } from "@goauthentik/elements/Base";
import "@goauthentik/elements/CodeMirror";
import { PFColor } from "@goauthentik/elements/Label";
import "@goauthentik/elements/Markdown";
import "@goauthentik/elements/Markdown";
import "@goauthentik/elements/Tabs";
import "@goauthentik/elements/buttons/ModalButton";
import "@goauthentik/elements/buttons/SpinnerButton";
@ -32,6 +34,7 @@ import PFContent from "@patternfly/patternfly/components/Content/content.css";
import PFDescriptionList from "@patternfly/patternfly/components/DescriptionList/description-list.css";
import PFForm from "@patternfly/patternfly/components/Form/form.css";
import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css";
import PFList from "@patternfly/patternfly/components/List/list.css";
import PFPage from "@patternfly/patternfly/components/Page/page.css";
import PFGrid from "@patternfly/patternfly/layouts/Grid/grid.css";
import PFBase from "@patternfly/patternfly/patternfly-base.css";
@ -90,6 +93,7 @@ export class ProxyProviderViewPage extends AKElement {
PFPage,
PFGrid,
PFContent,
PFList,
PFForm,
PFFormControl,
PFCard,
@ -182,6 +186,9 @@ export class ProxyProviderViewPage extends AKElement {
<section slot="page-overview" data-tab-title="${t`Overview`}">
${this.renderTabOverview()}
</section>
<section slot="page-authentication" data-tab-title="${t`Authentication`}">
${this.renderTabAuthentication()}
</section>
<section
slot="page-changelog"
data-tab-title="${t`Changelog`}"
@ -200,6 +207,37 @@ export class ProxyProviderViewPage extends AKElement {
</ak-tabs>`;
}
renderTabAuthentication(): TemplateResult {
if (!this.provider) {
return html``;
}
return html`<div
class="pf-c-page__main-section pf-m-no-padding-mobile pf-l-grid pf-m-gutter"
>
<div class="pf-c-card pf-l-grid__item pf-m-12-col">
<div class="pf-c-card__body">
<dl class="pf-c-description-list pf-m-3-col-on-lg">
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`Client ID`}</span>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
<pre>${this.provider.clientId}</pre>
</div>
</dd>
</div>
</dl>
</div>
</div>
<div class="pf-c-card pf-l-grid__item pf-m-12-col">
<div class="pf-c-card__body">
<ak-markdown .md=${MDHeaderAuthentication}></ak-markdown>
</div>
</div>
</div>`;
}
renderTabOverview(): TemplateResult {
if (!this.provider) {
return html``;
@ -316,21 +354,24 @@ export class ProxyProviderViewPage extends AKElement {
<div class="pf-c-card pf-l-grid__item pf-m-12-col">
<div class="pf-c-card__title">${t`Protocol Settings`}</div>
<div class="pf-c-card__body">
<form class="pf-c-form">
<div class="pf-c-form__group">
<label class="pf-c-form__label">
<span class="pf-c-form__label-text"
<dl class="pf-c-description-list pf-m-3-col-on-lg">
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text"
>${t`Allowed Redirect URIs`}</span
>
</label>
<input
class="pf-c-form-control"
readonly
type="text"
value=${this.provider.redirectUris}
/>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
<ul class="pf-c-list">
${this.provider.redirectUris.split("\n").map((url) => {
return html`<li><pre>${url}</pre></li>`;
})}
</ul>
</div>
</dd>
</div>
</form>
</dl>
</div>
</div>
<div class="pf-c-card pf-l-grid__item pf-m-12-col">