From fe17f116ed294f7b3ab0b24bf9270f32126ecb8e Mon Sep 17 00:00:00 2001
From: Ken Sternberg
Date: Mon, 7 Aug 2023 15:56:12 -0700
Subject: [PATCH] web: Tactical change. Put all the variants on the second
page; it's a longer list, but it's also easier to manage than all those
required sub-options.
---
...rd-authentication-method-choice.choices.ts | 35 +++++
...ion-wizard-authentication-method-choice.ts | 41 +----
...-proxy.ts => AuthenticationByProxyPage.ts} | 143 +++---------------
...wizard-authentication-for-reverse-proxy.ts | 49 ++++++
...authentication-for-single-forward-proxy.ts | 36 +++++
.../stories/ak-application-wizard.stories.ts | 25 ++-
6 files changed, 163 insertions(+), 166 deletions(-)
create mode 100644 web/src/admin/applications/wizard/ak-application-wizard-authentication-method-choice.choices.ts
rename web/src/admin/applications/wizard/proxy/{ak-application-wizard-authentication-by-proxy.ts => AuthenticationByProxyPage.ts} (66%)
create mode 100644 web/src/admin/applications/wizard/proxy/ak-application-wizard-authentication-for-reverse-proxy.ts
create mode 100644 web/src/admin/applications/wizard/proxy/ak-application-wizard-authentication-for-single-forward-proxy.ts
diff --git a/web/src/admin/applications/wizard/ak-application-wizard-authentication-method-choice.choices.ts b/web/src/admin/applications/wizard/ak-application-wizard-authentication-method-choice.choices.ts
new file mode 100644
index 000000000..46e33aab8
--- /dev/null
+++ b/web/src/admin/applications/wizard/ak-application-wizard-authentication-method-choice.choices.ts
@@ -0,0 +1,35 @@
+import { msg } from "@lit/localize";
+
+import type { TypeCreate } from "@goauthentik/api";
+
+type ProviderType = [string, string, string] | [string, string, string, ProviderType[]];
+
+type ProviderOption = TypeCreate & {
+ children?: TypeCreate[];
+};
+
+// prettier-ignore
+const _providerTypesTable: ProviderType[] = [
+ ["oauth2provider", msg("OAuth2/OpenID"), msg("Modern applications, APIs and Single-page applications.")],
+ ["ldapprovider", msg("LDAP"), msg("Provide an LDAP interface for applications and users to authenticate against.")],
+ ["proxyprovider-proxy", msg("Transparent Reverse Proxy"), msg("For transparent reverse proxies with required authentication")],
+ ["proxyprovider-forwardsingle", msg("Forward Single Proxy"), msg("For nginx's auth_request or traefix's forwardAuth")],
+ ["radiusprovider", msg("Radius"), msg("Allow applications to authenticate against authentik's users using Radius.")],
+ ["samlprovider-manual", msg("SAML Manual configuration"), msg("Configure SAML provider manually")],
+ ["samlprovider-import", msg("SAML Import Configuration"), msg("Create a SAML provider by importing its metadata")],
+ ["scimprovider", msg("SCIM Provider"), msg("SCIM 2.0 provider to create users and groups in external applications")]
+];
+
+function mapProviders([modelName, name, description, children]: ProviderType): ProviderOption {
+ return {
+ modelName,
+ name,
+ description,
+ component: "",
+ ...(children ? { children: children.map(mapProviders) } : {}),
+ };
+}
+
+export const providerTypesList = _providerTypesTable.map(mapProviders);
+
+export default providerTypesList;
diff --git a/web/src/admin/applications/wizard/ak-application-wizard-authentication-method-choice.ts b/web/src/admin/applications/wizard/ak-application-wizard-authentication-method-choice.ts
index 481fdb5cd..82ec4ecfb 100644
--- a/web/src/admin/applications/wizard/ak-application-wizard-authentication-method-choice.ts
+++ b/web/src/admin/applications/wizard/ak-application-wizard-authentication-method-choice.ts
@@ -1,4 +1,3 @@
-import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import "@goauthentik/components/ak-radio-input";
import "@goauthentik/components/ak-switch-input";
import "@goauthentik/components/ak-text-input";
@@ -9,73 +8,45 @@ import "@goauthentik/elements/forms/HorizontalFormElement";
import { msg } from "@lit/localize";
import { customElement } from "@lit/reactive-element/decorators/custom-element.js";
import { html } from "lit";
-import { state } from "lit/decorators.js";
import { map } from "lit/directives/map.js";
-import { ProvidersApi } from "@goauthentik/api";
import type { TypeCreate } from "@goauthentik/api";
import ApplicationWizardPageBase from "./ApplicationWizardPageBase";
-
-// The provider description that comes from the server is fairly specific and not internationalized.
-// We provide alternative descriptions that use the phrase 'authentication method' instead, and make
-// it available to i18n.
-//
-// prettier-ignore
-const alternativeDescription = new Map([
- ["oauth2provider", msg("Modern applications, APIs and Single-page applications.")],
- ["samlprovider", msg("XML-based SSO standard. Use this if your application only supports SAML.")],
- ["proxyprovider", msg("Legacy applications which don't natively support SSO.")],
- ["ldapprovider", msg("Provide an LDAP interface for applications and users to authenticate against.")]
-]);
+import providerTypesList from "./ak-application-wizard-authentication-method-choice.choices";
@customElement("ak-application-wizard-authentication-method-choice")
export class ApplicationWizardAuthenticationMethodChoice extends ApplicationWizardPageBase {
- @state()
- providerTypes: TypeCreate[] = [];
-
constructor() {
super();
this.handleChoice = this.handleChoice.bind(this);
this.renderProvider = this.renderProvider.bind(this);
- // If the provider doesn't supply a model to which to send our initialization, the user will
- // have to use the older provider path.
- new ProvidersApi(DEFAULT_CONFIG).providersAllTypesList().then((types) => {
- this.providerTypes = types.filter(({ modelName }) => modelName.trim() !== "");
- });
}
handleChoice(ev: InputEvent) {
const target = ev.target as HTMLInputElement;
-
this.dispatchWizardUpdate({ providerType: target.value });
}
renderProvider(type: TypeCreate) {
- const description = alternativeDescription.has(type.modelName)
- ? alternativeDescription.get(type.modelName)
- : type.description;
-
- const label = type.name.replace(/\s+Provider/, "");
-
return html`
- ${label}
- ${description}
+ ${type.name}
+ ${type.description}
`;
}
render() {
- return this.providerTypes.length > 0
+ return providerTypesList.length > 0
? html``
: html` `;
}
diff --git a/web/src/admin/applications/wizard/proxy/ak-application-wizard-authentication-by-proxy.ts b/web/src/admin/applications/wizard/proxy/AuthenticationByProxyPage.ts
similarity index 66%
rename from web/src/admin/applications/wizard/proxy/ak-application-wizard-authentication-by-proxy.ts
rename to web/src/admin/applications/wizard/proxy/AuthenticationByProxyPage.ts
index ea7df221e..00d82b25a 100644
--- a/web/src/admin/applications/wizard/proxy/ak-application-wizard-authentication-by-proxy.ts
+++ b/web/src/admin/applications/wizard/proxy/AuthenticationByProxyPage.ts
@@ -1,16 +1,15 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
-import "@goauthentik/elements/forms/HorizontalFormElement";
-
-import { msg } from "@lit/localize";
-import { customElement, state } from "@lit/reactive-element/decorators.js";
-import { TemplateResult, html } from "lit";
-import { ifDefined } from "lit/directives/if-defined.js";
-
import "@goauthentik/components/ak-switch-input";
import "@goauthentik/components/ak-text-input";
import "@goauthentik/components/ak-textarea-input";
import "@goauthentik/components/ak-toggle-group";
+import "@goauthentik/elements/forms/HorizontalFormElement";
+
+import { msg } from "@lit/localize";
+import { state } from "@lit/reactive-element/decorators.js";
+import { TemplateResult, html, nothing } from "lit";
+import { ifDefined } from "lit/directives/if-defined.js";
import {
FlowsInstancesListDesignationEnum,
@@ -24,7 +23,8 @@ import {
import ApplicationWizardPageBase from "../ApplicationWizardPageBase";
-@customElement("ak-application-wizard-authentication-by-proxy")
+type MaybeTemplateResult = TemplateResult | typeof nothing;
+
export class AkTypeProxyApplicationWizardPage extends ApplicationWizardPageBase {
constructor() {
super();
@@ -72,6 +72,14 @@ export class AkTypeProxyApplicationWizardPage extends ApplicationWizardPageBase
return this.wizard.provider as ProxyProvider;
}
+ renderModeDescription(): MaybeTemplateResult {
+ return nothing;
+ }
+
+ renderProxyMode() {
+ return html`This space intentionally left blank `;
+ }
+
renderHttpBasic(): TemplateResult {
return html``;
}
- renderModeSelector(): TemplateResult {
- const setMode = (ev: CustomEvent<{ value: ProxyMode }>) => {
- this.mode = ev.detail.value;
- };
-
- // prettier-ignore
- return html`
-
- ${msg("Proxy")}
- ${msg("Forward auth (single application)")}
- ${msg("Forward auth (domain level)")}
-
- `;
- }
-
- renderProxyModeProxy() {
- return html`
- ${msg(
- "This provider will behave like a transparent reverse-proxy, except requests must be authenticated. If your upstream application uses HTTPS, make sure to connect to the outpost using HTTPS as well.",
- )}
-
-
-
-
- `;
- }
-
- renderProxyModeForwardSingle() {
- return html`
- ${msg(
- "Use this provider with nginx's auth_request or traefik's forwardAuth. Each application/domain needs its own provider. Additionally, on each domain, /outpost.goauthentik.io must be routed to the outpost (when using a manged outpost, this is done for you).",
- )}
-
- `;
- }
-
- renderProxyModeForwardDomain() {
- return html`
- ${msg(
- "Use this provider with nginx's auth_request or traefik's forwardAuth. Only a single provider is required per root domain. You can't do per-application authorization, but you don't have to create a provider for each application.",
- )}
-
-
- ${msg("An example setup can look like this:")}
-
- ${msg("authentik running on auth.example.com")}
- ${msg("app1 running on app1.example.com")}
-
- ${msg(
- "In this case, you'd set the Authentication URL to auth.example.com and Cookie domain to example.com.",
- )}
-
-
- `;
- }
-
- renderSettings() {
- switch (this.mode) {
- case ProxyMode.Proxy:
- return this.renderProxyModeProxy();
- case ProxyMode.ForwardSingle:
- return this.renderProxyModeForwardSingle();
- case ProxyMode.ForwardDomain:
- return this.renderProxyModeForwardDomain();
- case ProxyMode.UnknownDefaultOpenApi:
- return html`${msg("Unknown proxy mode")}
`;
- }
- }
-
render() {
return html`
`;
+ }
+
+ renderProxyMode() {
+ return html`
+
+
+ `;
+ }
+}
+
+export default AkReverseProxyApplicationWizardPage;
diff --git a/web/src/admin/applications/wizard/proxy/ak-application-wizard-authentication-for-single-forward-proxy.ts b/web/src/admin/applications/wizard/proxy/ak-application-wizard-authentication-for-single-forward-proxy.ts
new file mode 100644
index 000000000..0840c698f
--- /dev/null
+++ b/web/src/admin/applications/wizard/proxy/ak-application-wizard-authentication-for-single-forward-proxy.ts
@@ -0,0 +1,36 @@
+import "@goauthentik/components/ak-text-input";
+
+import { msg } from "@lit/localize";
+import { customElement } from "@lit/reactive-element/decorators.js";
+import { html } from "lit";
+import { ifDefined } from "lit/directives/if-defined.js";
+
+import AkTypeProxyApplicationWizardPage from "./AuthenticationByProxyPage";
+
+@customElement("ak-application-wizard-authentication-for-single-forward-proxy")
+export class AkForwardSingleProxyApplicationWizardPage extends AkTypeProxyApplicationWizardPage {
+ renderModeDescription() {
+ return html`
+ ${msg(
+ html`Use this provider with nginx's auth_request
or traefik's
+ forwardAuth
. Each application/domain needs its own provider.
+ Additionally, on each domain, /outpost.goauthentik.io
must be
+ routed to the outpost (when using a managed outpost, this is done for you).`,
+ )}
+
`;
+ }
+
+ renderProxyMode() {
+ return html` `;
+ }
+}
+
+export default AkForwardSingleProxyApplicationWizardPage;
diff --git a/web/src/admin/applications/wizard/stories/ak-application-wizard.stories.ts b/web/src/admin/applications/wizard/stories/ak-application-wizard.stories.ts
index 203aded62..5aa678935 100644
--- a/web/src/admin/applications/wizard/stories/ak-application-wizard.stories.ts
+++ b/web/src/admin/applications/wizard/stories/ak-application-wizard.stories.ts
@@ -7,8 +7,9 @@ import AkApplicationWizardApplicationDetails from "../ak-application-wizard-appl
import "../ak-application-wizard-authentication-method-choice";
import "../ak-application-wizard-context";
import "../ldap/ak-application-wizard-authentication-by-ldap";
-import "../proxy/ak-application-wizard-authentication-by-proxy";
import "../oauth/ak-application-wizard-authentication-by-oauth";
+import "../proxy/ak-application-wizard-authentication-for-reverse-proxy";
+import "../proxy/ak-application-wizard-authentication-for-single-forward-proxy";
import "./ak-application-context-display-for-test";
import {
dummyAuthenticationFlowsSearch,
@@ -103,7 +104,7 @@ const container = (testItem: TemplateResult) => {
`;
};
-export const PageOne = () => {
+export const DescribeApplication = () => {
return container(
html`
@@ -113,7 +114,7 @@ export const PageOne = () => {
);
};
-export const PageTwo = () => {
+export const ChooseAuthMethod = () => {
return container(
html`
@@ -123,7 +124,7 @@ export const PageTwo = () => {
);
};
-export const PageThreeLdap = () => {
+export const ConfigureLdap = () => {
return container(
html`
@@ -133,7 +134,7 @@ export const PageThreeLdap = () => {
);
};
-export const PageThreeOauth2 = () => {
+export const ConfigureOauth2 = () => {
return container(
html`
@@ -143,10 +144,20 @@ export const PageThreeOauth2 = () => {
);
};
-export const PageThreeProxy = () => {
+export const ConfigureReverseProxy = () => {
return container(
html`
-
+
+
+
+ `,
+ );
+};
+
+export const ConfigureSingleForwardProxy = () => {
+ return container(
+ html`
+
`,