root: support running authentik in subpath (#8675)

* initial subpath support

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

* make outpost compatible

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

* fix static files somewhat

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

* fix web interface

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

* fix most static stuff

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

* fix most web links

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

* fix websocket

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

* fix URL for static files

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

* format web

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

* add root redirect for subpath

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

* update docs

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

* set cookie path

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

* Update internal/config/struct.go

Co-authored-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
Signed-off-by: Jens L. <jens@beryju.org>

* fix sfe

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

* bump required version

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

* fix flow background

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

* fix lint and some more links

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

* format

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

* fix impersonate

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

* fix

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Signed-off-by: Jens L. <jens@beryju.org>
Signed-off-by: Jens L. <jens@goauthentik.io>
Co-authored-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
This commit is contained in:
Jens L.
2024-11-26 15:38:23 +01:00
committed by GitHub
parent ee15dbf671
commit 5e72ec9c0c
43 changed files with 236 additions and 96 deletions

View File

@ -1,5 +1,6 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { EVENT_SIDEBAR_TOGGLE, VERSION } from "@goauthentik/common/constants";
import { globalAK } from "@goauthentik/common/global";
import { me } from "@goauthentik/common/users";
import { AKElement } from "@goauthentik/elements/Base";
import {
@ -112,7 +113,7 @@ export class AkAdminSidebar extends WithCapabilitiesConfig(AKElement) {
// prettier-ignore
const sidebarContent: SidebarEntry[] = [
["/if/user/", msg("User interface"), { "?isAbsoluteLink": true, "?highlight": true }],
[`${globalAK().api.base}if/user/`, msg("User interface"), { "?isAbsoluteLink": true, "?highlight": true }],
[null, msg("Dashboards"), { "?expanded": true }, [
["/administration/overview", msg("Overview")],
["/administration/dashboard/users", msg("User Statistics")],

View File

@ -1,4 +1,5 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { globalAK } from "@goauthentik/common/global";
import "@goauthentik/components/ak-text-input";
import { Form } from "@goauthentik/elements/forms/Form";
@ -20,7 +21,7 @@ export class UserImpersonateForm extends Form<ImpersonationRequest> {
impersonationRequest: data,
})
.then(() => {
window.location.href = "/";
window.location.href = globalAK().api.base;
});
}

View File

@ -68,7 +68,7 @@ export function getMetaContent(key: string): string {
}
export const DEFAULT_CONFIG = new Configuration({
basePath: (process.env.AK_API_BASE_PATH || window.location.origin) + "/api/v3",
basePath: `${globalAK().api.base}api/v3`,
headers: {
"sentry-trace": getMetaContent("sentry-trace"),
},

View File

@ -11,6 +11,9 @@ export interface GlobalAuthentik {
versionFamily: string;
versionSubdomain: string;
build: string;
api: {
base: string;
};
}
export interface AuthentikWindow {
@ -35,6 +38,9 @@ export function globalAK(): GlobalAuthentik {
versionFamily: "",
versionSubdomain: "",
build: "",
api: {
base: process.env.AK_API_BASE_PATH || window.location.origin,
},
};
}
return ak;

View File

@ -1,4 +1,5 @@
import { EVENT_MESSAGE, EVENT_WS_MESSAGE } from "@goauthentik/common/constants";
import { globalAK } from "@goauthentik/common/global";
import { MessageLevel } from "@goauthentik/common/messages";
import { msg } from "@lit/localize";
@ -21,9 +22,8 @@ export class WebsocketClient {
connect(): void {
if (navigator.webdriver) return;
const wsUrl = `${window.location.protocol.replace("http", "ws")}//${
window.location.host
}/ws/client/`;
const apiURL = new URL(globalAK().api.base);
const wsUrl = `${window.location.protocol.replace("http", "ws")}//${apiURL.host}${apiURL.pathname}ws/client/`;
this.messageSocket = new WebSocket(wsUrl);
this.messageSocket.addEventListener("open", () => {
console.debug(`authentik/ws: connected to ${wsUrl}`);

View File

@ -1,3 +1,4 @@
import { globalAK } from "@goauthentik/common/global";
import { AKElement } from "@goauthentik/elements/Base";
import { WithLicenseSummary } from "@goauthentik/elements/Interface/licenseSummaryProvider";
@ -75,7 +76,9 @@ export class EnterpriseStatusBanner extends WithLicenseSummary(AKElement) {
: "pf-m-gold"}"
>
${message}
<a href="/if/admin/#/enterprise/licenses"> ${msg("Click here for more info.")} </a>
<a href="${globalAK().api.base}if/admin/#/enterprise/licenses"
>${msg("Click here for more info.")}</a
>
</div>`;
}

View File

@ -1,5 +1,6 @@
import { RequestInfo } from "@goauthentik/common/api/middleware";
import { EVENT_API_DRAWER_TOGGLE, EVENT_REQUEST_POST } from "@goauthentik/common/constants";
import { globalAK } from "@goauthentik/common/global";
import { AKElement } from "@goauthentik/elements/Base";
import { msg } from "@lit/localize";
@ -86,7 +87,9 @@ export class APIDrawer extends AKElement {
<h1 class="pf-c-notification-drawer__header-title">
${msg("API Requests")}
</h1>
<a href="/api/v3/" target="_blank">${msg("Open API Browser")}</a>
<a href="${globalAK().api.base}api/v3/" target="_blank"
>${msg("Open API Browser")}</a
>
</div>
<div class="pf-c-notification-drawer__header-action">
<div class="pf-c-notification-drawer__header-action-close">

View File

@ -1,5 +1,6 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { EVENT_NOTIFICATION_DRAWER_TOGGLE, EVENT_REFRESH } from "@goauthentik/common/constants";
import { globalAK } from "@goauthentik/common/global";
import { actionToLabel } from "@goauthentik/common/labels";
import { MessageLevel } from "@goauthentik/common/messages";
import { me } from "@goauthentik/common/users";
@ -100,7 +101,7 @@ export class NotificationDrawer extends AKElement {
html`
<a
class="pf-c-dropdown__toggle pf-m-plain"
href="/if/admin/#/events/log/${item.event?.pk}"
href="${globalAK().api.base}if/admin/#/events/log/${item.event?.pk}"
>
<pf-tooltip position="top" content=${msg("Show details")}>
<i class="fas fa-share-square"></i>

View File

@ -1,3 +1,4 @@
import { globalAK } from "@goauthentik/common/global";
import { me } from "@goauthentik/common/users";
import { AKElement } from "@goauthentik/elements/Base";
@ -35,7 +36,11 @@ export class SidebarUser extends AKElement {
render(): TemplateResult {
return html`
<a href="/if/user/#/settings" class="pf-c-nav__link user-avatar" id="user-settings">
<a
href="${globalAK().api.base}if/user/#/settings"
class="pf-c-nav__link user-avatar"
id="user-settings"
>
${until(
me().then((u) => {
return html`<img
@ -47,7 +52,11 @@ export class SidebarUser extends AKElement {
html``,
)}
</a>
<a href="/flows/-/default/invalidation/" class="pf-c-nav__link user-logout" id="logout">
<a
href="${globalAK().api.base}flows/-/default/invalidation/"
class="pf-c-nav__link user-logout"
id="logout"
>
<i class="fas fa-sign-out-alt" aria-hidden="true"></i>
</a>
`;

View File

@ -461,6 +461,7 @@ export class FlowExecutor extends Interface implements StageHost {
await import("@goauthentik/flow/FlowInspector");
return html`<ak-flow-inspector
class="pf-c-drawer__panel pf-m-width-33"
.flowSlug=${this.flowSlug}
></ak-flow-inspector>`;
}

View File

@ -19,7 +19,8 @@ import { FlowInspection, FlowsApi, ResponseError, Stage } from "@goauthentik/api
@customElement("ak-flow-inspector")
export class FlowInspector extends AKElement {
flowSlug: string;
@property()
flowSlug?: string;
@property({ attribute: false })
state?: FlowInspection;
@ -55,7 +56,6 @@ export class FlowInspector extends AKElement {
constructor() {
super();
this.flowSlug = window.location.pathname.split("/")[3];
window.addEventListener(EVENT_FLOW_ADVANCE, this.advanceHandler as EventListener);
}
@ -67,7 +67,7 @@ export class FlowInspector extends AKElement {
advanceHandler = (): void => {
new FlowsApi(DEFAULT_CONFIG)
.flowsInspectorGet({
flowSlug: this.flowSlug,
flowSlug: this.flowSlug || "",
})
.then((state) => {
this.error = undefined;

View File

@ -1,3 +1,4 @@
import { globalAK } from "@goauthentik/common/global";
import "@goauthentik/flow/FormStatic";
import { BaseStage } from "@goauthentik/flow/stages/base";
@ -47,7 +48,9 @@ export class SessionEnd extends BaseStage<SessionEndChallenge, unknown> {
str`You've logged out of ${this.challenge.applicationName}. You can go back to the overview to launch another application, or log out of your authentik account.`,
)}
</p>
<a href="/" class="pf-c-button pf-m-primary"> ${msg("Go back to overview")} </a>
<a href="${globalAK().api.base}" class="pf-c-button pf-m-primary">
${msg("Go back to overview")}
</a>
${this.challenge.invalidationFlowUrl
? html`
<a

View File

@ -1,4 +1,5 @@
import { PFSize } from "@goauthentik/common/enums.js";
import { globalAK } from "@goauthentik/common/global";
import { truncateWords } from "@goauthentik/common/utils";
import "@goauthentik/elements/AppIcon";
import { AKElement, rootInterface } from "@goauthentik/elements/Base";
@ -77,7 +78,8 @@ export class LibraryApplication extends AKElement {
? html`
<a
class="pf-c-button pf-m-control pf-m-small pf-m-block"
href="/if/admin/#/core/applications/${application?.slug}"
href="${globalAK().api
.base}if/admin/#/core/applications/${application?.slug}"
>
<i class="fas fa-edit"></i>&nbsp;${msg("Edit")}
</a>

View File

@ -1,4 +1,4 @@
import { docLink } from "@goauthentik/common/global";
import { docLink, globalAK } from "@goauthentik/common/global";
import { AKElement } from "@goauthentik/elements/Base";
import { paramURL } from "@goauthentik/elements/router/RouterOutlet";
@ -49,7 +49,7 @@ export class LibraryPageApplicationEmptyList extends AKElement {
<a
aria-disabled="false"
class="cta pf-c-button pf-m-secondary"
href="/if/admin/${href}"
href="${globalAK().api.base}if/admin/${href}"
>${msg("Create a new application")}</a
>
</div>

View File

@ -4,6 +4,7 @@ import {
EVENT_NOTIFICATION_DRAWER_TOGGLE,
EVENT_WS_MESSAGE,
} from "@goauthentik/common/constants";
import { globalAK } from "@goauthentik/common/global";
import { configureSentry } from "@goauthentik/common/sentry";
import { UIConfig, UserDisplay } from "@goauthentik/common/ui/config";
import { me } from "@goauthentik/common/users";
@ -207,7 +208,7 @@ class UserInterfacePresentation extends AKElement {
${this.renderSettings()}
<div class="pf-c-page__header-tools-item">
<a
href="/flows/-/default/invalidation/"
href="${globalAK().api.base}flows/-/default/invalidation/"
class="pf-c-button pf-m-plain"
>
<pf-tooltip position="top" content=${msg("Sign out")}>
@ -349,7 +350,7 @@ class UserInterfacePresentation extends AKElement {
return html`<a
class="pf-c-button pf-m-secondary pf-m-small pf-u-display-none pf-u-display-block-on-md"
href="/if/admin/"
href="${globalAK().api.base}if/admin/"
>
${msg("Admin interface")}
</a>`;

View File

@ -1,5 +1,6 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { EVENT_REFRESH } from "@goauthentik/common/constants";
import { globalAK } from "@goauthentik/common/global";
import { MessageLevel } from "@goauthentik/common/messages";
import { refreshMe } from "@goauthentik/common/users";
import { AKElement } from "@goauthentik/elements/Base";
@ -173,7 +174,10 @@ export class UserSettingsFlowExecutor
`authentik/user/flows: unsupported stage type ${this.challenge.component}`,
);
return html`
<a href="/if/flow/${this.flowSlug}/" class="pf-c-button pf-m-primary">
<a
href="${globalAK().api.base}if/flow/${this.flowSlug}/"
class="pf-c-button pf-m-primary"
>
${msg("Open settings")}
</a>
`;

View File

@ -1,3 +1,4 @@
import { globalAK } from "@goauthentik/common/global";
import "@goauthentik/elements/forms/HorizontalFormElement";
import { PromptStage } from "@goauthentik/flow/stages/prompt/PromptStage";
@ -50,7 +51,8 @@ export class UserSettingsPromptStage extends PromptStage {
${this.host.brand?.flowUnenrollment
? html` <a
class="pf-c-button pf-m-danger"
href="/if/flow/${this.host.brand.flowUnenrollment}/"
href="${globalAK().api.base}if/flow/${this.host.brand
.flowUnenrollment}/"
>
${msg("Delete account")}
</a>`