2021-04-03 17:26:43 +00:00
|
|
|
import { t } from "@lingui/macro";
|
2021-08-03 15:52:21 +00:00
|
|
|
import {
|
|
|
|
LitElement,
|
|
|
|
html,
|
|
|
|
customElement,
|
|
|
|
property,
|
|
|
|
TemplateResult,
|
|
|
|
CSSResult,
|
|
|
|
css,
|
|
|
|
} from "lit-element";
|
2021-03-16 21:02:58 +00:00
|
|
|
|
2021-03-17 12:23:33 +00:00
|
|
|
import PFLogin from "@patternfly/patternfly/components/Login/login.css";
|
2021-03-17 16:11:39 +00:00
|
|
|
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
|
|
|
import PFTitle from "@patternfly/patternfly/components/Title/title.css";
|
2021-03-21 16:36:51 +00:00
|
|
|
import PFBackgroundImage from "@patternfly/patternfly/components/BackgroundImage/background-image.css";
|
|
|
|
import PFList from "@patternfly/patternfly/components/List/list.css";
|
2021-04-06 18:25:22 +00:00
|
|
|
import PFButton from "@patternfly/patternfly/components/Button/button.css";
|
2021-03-21 16:36:51 +00:00
|
|
|
import AKGlobal from "../authentik.css";
|
2021-03-16 21:02:58 +00:00
|
|
|
|
2021-02-17 22:52:49 +00:00
|
|
|
import { unsafeHTML } from "lit-html/directives/unsafe-html";
|
2021-03-27 21:32:29 +00:00
|
|
|
import "./access_denied/FlowAccessDenied";
|
2021-03-08 10:14:00 +00:00
|
|
|
import "./stages/authenticator_static/AuthenticatorStaticStage";
|
|
|
|
import "./stages/authenticator_totp/AuthenticatorTOTPStage";
|
2021-05-23 19:04:37 +00:00
|
|
|
import "./stages/authenticator_duo/AuthenticatorDuoStage";
|
2021-03-08 10:14:00 +00:00
|
|
|
import "./stages/authenticator_validate/AuthenticatorValidateStage";
|
|
|
|
import "./stages/authenticator_webauthn/WebAuthnAuthenticatorRegisterStage";
|
|
|
|
import "./stages/autosubmit/AutosubmitStage";
|
|
|
|
import "./stages/captcha/CaptchaStage";
|
|
|
|
import "./stages/consent/ConsentStage";
|
2021-03-27 21:32:29 +00:00
|
|
|
import "./stages/dummy/DummyStage";
|
2021-03-08 10:14:00 +00:00
|
|
|
import "./stages/email/EmailStage";
|
|
|
|
import "./stages/identification/IdentificationStage";
|
|
|
|
import "./stages/password/PasswordStage";
|
|
|
|
import "./stages/prompt/PromptStage";
|
2021-05-02 14:47:20 +00:00
|
|
|
import "./sources/plex/PlexLoginInit";
|
2021-03-08 10:14:00 +00:00
|
|
|
import { StageHost } from "./stages/base";
|
2021-08-03 15:52:21 +00:00
|
|
|
import {
|
|
|
|
ChallengeChoices,
|
|
|
|
CurrentTenant,
|
|
|
|
ChallengeTypes,
|
|
|
|
FlowChallengeResponseRequest,
|
|
|
|
FlowsApi,
|
|
|
|
RedirectChallenge,
|
|
|
|
ShellChallenge,
|
|
|
|
} from "authentik-api";
|
2021-05-29 15:35:56 +00:00
|
|
|
import { DEFAULT_CONFIG, tenant } from "../api/Config";
|
2021-03-21 16:36:51 +00:00
|
|
|
import { ifDefined } from "lit-html/directives/if-defined";
|
|
|
|
import { until } from "lit-html/directives/until";
|
2021-04-04 20:04:46 +00:00
|
|
|
import { PFSize } from "../elements/Spinner";
|
2021-04-22 21:49:30 +00:00
|
|
|
import { TITLE_DEFAULT } from "../constants";
|
2021-04-22 18:47:48 +00:00
|
|
|
import { configureSentry } from "../api/Sentry";
|
2021-07-22 11:47:27 +00:00
|
|
|
import { WebsocketClient } from "../common/ws";
|
2021-03-23 16:55:32 +00:00
|
|
|
|
2021-02-17 22:52:49 +00:00
|
|
|
@customElement("ak-flow-executor")
|
2021-02-23 12:50:47 +00:00
|
|
|
export class FlowExecutor extends LitElement implements StageHost {
|
2021-03-21 16:36:51 +00:00
|
|
|
flowSlug: string;
|
2020-11-20 21:08:00 +00:00
|
|
|
|
2021-08-03 15:52:21 +00:00
|
|
|
@property({ attribute: false })
|
2021-06-14 20:24:34 +00:00
|
|
|
challenge?: ChallengeTypes;
|
2020-10-16 14:36:18 +00:00
|
|
|
|
2021-08-03 15:52:21 +00:00
|
|
|
@property({ type: Boolean })
|
2021-02-21 21:01:58 +00:00
|
|
|
loading = false;
|
2021-02-21 21:01:35 +00:00
|
|
|
|
2021-03-21 16:36:51 +00:00
|
|
|
@property({ attribute: false })
|
2021-05-29 15:35:56 +00:00
|
|
|
tenant?: CurrentTenant;
|
2021-03-21 16:36:51 +00:00
|
|
|
|
2021-07-22 11:47:27 +00:00
|
|
|
ws: WebsocketClient;
|
|
|
|
|
2021-02-21 21:01:35 +00:00
|
|
|
static get styles(): CSSResult[] {
|
2021-04-06 18:25:22 +00:00
|
|
|
return [PFBase, PFLogin, PFButton, PFTitle, PFList, PFBackgroundImage, AKGlobal].concat(css`
|
2021-02-21 21:01:35 +00:00
|
|
|
.ak-loading {
|
|
|
|
display: flex;
|
|
|
|
height: 100%;
|
|
|
|
width: 100%;
|
|
|
|
justify-content: center;
|
|
|
|
align-items: center;
|
|
|
|
position: absolute;
|
2021-03-21 14:01:48 +00:00
|
|
|
background-color: var(--pf-global--BackgroundColor--dark-transparent-100);
|
|
|
|
z-index: 1;
|
2021-02-21 21:01:35 +00:00
|
|
|
}
|
|
|
|
.ak-hidden {
|
|
|
|
display: none;
|
|
|
|
}
|
|
|
|
:host {
|
|
|
|
position: relative;
|
|
|
|
}
|
2021-03-17 16:11:39 +00:00
|
|
|
.ak-exception {
|
|
|
|
font-family: monospace;
|
|
|
|
overflow-x: scroll;
|
|
|
|
}
|
2021-02-21 21:01:35 +00:00
|
|
|
`);
|
2020-10-16 14:36:18 +00:00
|
|
|
}
|
|
|
|
|
2021-02-17 19:49:58 +00:00
|
|
|
constructor() {
|
|
|
|
super();
|
2021-07-22 11:47:27 +00:00
|
|
|
this.ws = new WebsocketClient();
|
|
|
|
this.ws.connect();
|
2021-03-22 12:44:17 +00:00
|
|
|
this.flowSlug = window.location.pathname.split("/")[3];
|
|
|
|
}
|
|
|
|
|
|
|
|
setBackground(url: string): void {
|
2021-08-03 15:52:21 +00:00
|
|
|
this.shadowRoot
|
|
|
|
?.querySelectorAll<HTMLDivElement>(".pf-c-background-image")
|
|
|
|
.forEach((bg) => {
|
|
|
|
bg.style.setProperty("--ak-flow-background", `url('${url}')`);
|
|
|
|
});
|
2021-02-17 19:49:58 +00:00
|
|
|
}
|
|
|
|
|
2021-03-22 13:39:51 +00:00
|
|
|
private postUpdate(): void {
|
2021-08-03 15:52:21 +00:00
|
|
|
tenant().then((tenant) => {
|
2021-06-08 15:56:35 +00:00
|
|
|
if (this.challenge?.flowInfo?.title) {
|
|
|
|
document.title = `${this.challenge.flowInfo?.title} - ${tenant.brandingTitle}`;
|
2021-04-22 21:49:30 +00:00
|
|
|
} else {
|
2021-05-29 15:35:56 +00:00
|
|
|
document.title = tenant.brandingTitle || TITLE_DEFAULT;
|
2021-04-22 21:49:30 +00:00
|
|
|
}
|
|
|
|
});
|
2021-03-22 13:39:51 +00:00
|
|
|
}
|
|
|
|
|
2021-05-24 21:43:48 +00:00
|
|
|
submit(payload?: FlowChallengeResponseRequest): Promise<void> {
|
|
|
|
if (!payload) return Promise.reject();
|
2021-05-24 20:21:18 +00:00
|
|
|
if (!this.challenge) return Promise.reject();
|
2021-05-24 18:52:12 +00:00
|
|
|
// @ts-ignore
|
2021-05-24 20:21:18 +00:00
|
|
|
payload.component = this.challenge.component;
|
2021-02-21 21:01:35 +00:00
|
|
|
this.loading = true;
|
2021-08-03 15:52:21 +00:00
|
|
|
return new FlowsApi(DEFAULT_CONFIG)
|
|
|
|
.flowsExecutorSolve({
|
|
|
|
flowSlug: this.flowSlug,
|
|
|
|
query: window.location.search.substring(1),
|
|
|
|
flowChallengeResponseRequest: payload,
|
|
|
|
})
|
|
|
|
.then((data) => {
|
|
|
|
this.challenge = data;
|
|
|
|
this.postUpdate();
|
|
|
|
})
|
|
|
|
.catch((e: Error | Response) => {
|
|
|
|
this.errorMessage(e);
|
|
|
|
})
|
|
|
|
.finally(() => {
|
|
|
|
this.loading = false;
|
|
|
|
});
|
2021-02-17 22:52:49 +00:00
|
|
|
}
|
|
|
|
|
2020-12-01 08:15:41 +00:00
|
|
|
firstUpdated(): void {
|
2021-05-29 15:35:56 +00:00
|
|
|
configureSentry();
|
2021-08-03 15:52:21 +00:00
|
|
|
tenant().then((tenant) => (this.tenant = tenant));
|
2021-02-21 21:01:35 +00:00
|
|
|
this.loading = true;
|
2021-08-03 15:52:21 +00:00
|
|
|
new FlowsApi(DEFAULT_CONFIG)
|
|
|
|
.flowsExecutorGet({
|
|
|
|
flowSlug: this.flowSlug,
|
|
|
|
query: window.location.search.substring(1),
|
|
|
|
})
|
|
|
|
.then((challenge) => {
|
|
|
|
this.challenge = challenge;
|
|
|
|
// Only set background on first update, flow won't change throughout execution
|
|
|
|
if (this.challenge?.flowInfo?.background) {
|
|
|
|
this.setBackground(this.challenge.flowInfo.background);
|
|
|
|
}
|
|
|
|
this.postUpdate();
|
|
|
|
})
|
|
|
|
.catch((e: Error | Response) => {
|
|
|
|
// Catch JSON or Update errors
|
|
|
|
this.errorMessage(e);
|
|
|
|
})
|
|
|
|
.finally(() => {
|
|
|
|
this.loading = false;
|
|
|
|
});
|
2020-10-16 14:36:18 +00:00
|
|
|
}
|
|
|
|
|
2021-06-12 16:18:36 +00:00
|
|
|
async errorMessage(error: Error | Response): Promise<void> {
|
|
|
|
let body = "";
|
|
|
|
if (error instanceof Error) {
|
|
|
|
body = error.message;
|
|
|
|
} else if (error instanceof Response) {
|
|
|
|
body = await error.text();
|
|
|
|
}
|
2021-05-24 18:52:12 +00:00
|
|
|
this.challenge = {
|
2021-05-16 13:31:13 +00:00
|
|
|
type: ChallengeChoices.Shell,
|
2021-03-17 16:11:39 +00:00
|
|
|
body: `<header class="pf-c-login__main-header">
|
|
|
|
<h1 class="pf-c-title pf-m-3xl">
|
2021-04-03 17:26:43 +00:00
|
|
|
${t`Whoops!`}
|
2021-03-17 16:11:39 +00:00
|
|
|
</h1>
|
|
|
|
</header>
|
|
|
|
<div class="pf-c-login__main-body">
|
2021-04-03 17:26:43 +00:00
|
|
|
<h3>${t`Something went wrong! Please try again later.`}</h3>
|
2021-06-12 16:18:36 +00:00
|
|
|
<pre class="ak-exception">${body}</pre>
|
2021-04-06 18:25:22 +00:00
|
|
|
</div>
|
|
|
|
<footer class="pf-c-login__main-footer">
|
|
|
|
<ul class="pf-c-login__main-footer-links">
|
2021-04-16 20:56:44 +00:00
|
|
|
<li class="pf-c-login__main-footer-links-item">
|
|
|
|
<a class="pf-c-button pf-m-primary pf-m-block" href="/">
|
|
|
|
${t`Return`}
|
|
|
|
</a>
|
|
|
|
</li>
|
2021-04-06 18:25:22 +00:00
|
|
|
</ul>
|
2021-08-03 15:52:21 +00:00
|
|
|
</footer>`,
|
2021-06-14 20:24:34 +00:00
|
|
|
} as ChallengeTypes;
|
2020-10-26 09:52:13 +00:00
|
|
|
}
|
|
|
|
|
2021-02-21 21:01:35 +00:00
|
|
|
renderLoading(): TemplateResult {
|
2021-03-23 18:52:00 +00:00
|
|
|
return html`<div class="ak-loading">
|
2021-04-04 20:04:46 +00:00
|
|
|
<ak-spinner size=${PFSize.XLarge}></ak-spinner>
|
2021-03-23 18:52:00 +00:00
|
|
|
</div>`;
|
2020-10-16 14:36:18 +00:00
|
|
|
}
|
|
|
|
|
2021-02-21 21:01:35 +00:00
|
|
|
renderChallenge(): TemplateResult {
|
2021-02-20 22:19:27 +00:00
|
|
|
if (!this.challenge) {
|
2021-03-22 19:49:11 +00:00
|
|
|
return html``;
|
2021-02-20 22:19:27 +00:00
|
|
|
}
|
2021-04-04 14:15:50 +00:00
|
|
|
switch (this.challenge.type) {
|
2021-05-16 13:31:13 +00:00
|
|
|
case ChallengeChoices.Redirect:
|
2021-08-03 15:52:21 +00:00
|
|
|
console.debug(
|
|
|
|
"authentik/flows: redirecting to url from server",
|
|
|
|
(this.challenge as RedirectChallenge).to,
|
|
|
|
);
|
2021-03-23 21:18:24 +00:00
|
|
|
window.location.assign((this.challenge as RedirectChallenge).to);
|
2021-08-03 15:52:21 +00:00
|
|
|
return html`<ak-empty-state ?loading=${true} header=${t`Loading`}>
|
|
|
|
</ak-empty-state>`;
|
2021-05-16 13:31:13 +00:00
|
|
|
case ChallengeChoices.Shell:
|
2021-02-21 21:01:35 +00:00
|
|
|
return html`${unsafeHTML((this.challenge as ShellChallenge).body)}`;
|
2021-05-16 13:31:13 +00:00
|
|
|
case ChallengeChoices.Native:
|
2021-02-21 21:01:35 +00:00
|
|
|
switch (this.challenge.component) {
|
2021-03-23 16:23:44 +00:00
|
|
|
case "ak-stage-access-denied":
|
2021-08-03 15:52:21 +00:00
|
|
|
return html`<ak-stage-access-denied
|
|
|
|
.host=${this as StageHost}
|
|
|
|
.challenge=${this.challenge}
|
|
|
|
></ak-stage-access-denied>`;
|
2021-02-21 21:01:35 +00:00
|
|
|
case "ak-stage-identification":
|
2021-08-03 15:52:21 +00:00
|
|
|
return html`<ak-stage-identification
|
|
|
|
.host=${this as StageHost}
|
|
|
|
.challenge=${this.challenge}
|
|
|
|
></ak-stage-identification>`;
|
2021-02-21 21:01:35 +00:00
|
|
|
case "ak-stage-password":
|
2021-08-03 15:52:21 +00:00
|
|
|
return html`<ak-stage-password
|
|
|
|
.host=${this as StageHost}
|
|
|
|
.challenge=${this.challenge}
|
|
|
|
></ak-stage-password>`;
|
2021-02-25 18:58:38 +00:00
|
|
|
case "ak-stage-captcha":
|
2021-08-03 15:52:21 +00:00
|
|
|
return html`<ak-stage-captcha
|
|
|
|
.host=${this as StageHost}
|
|
|
|
.challenge=${this.challenge}
|
|
|
|
></ak-stage-captcha>`;
|
2021-02-21 21:01:35 +00:00
|
|
|
case "ak-stage-consent":
|
2021-08-03 15:52:21 +00:00
|
|
|
return html`<ak-stage-consent
|
|
|
|
.host=${this as StageHost}
|
|
|
|
.challenge=${this.challenge}
|
|
|
|
></ak-stage-consent>`;
|
2021-03-27 21:32:29 +00:00
|
|
|
case "ak-stage-dummy":
|
2021-08-03 15:52:21 +00:00
|
|
|
return html`<ak-stage-dummy
|
|
|
|
.host=${this as StageHost}
|
|
|
|
.challenge=${this.challenge}
|
|
|
|
></ak-stage-dummy>`;
|
2021-02-21 21:01:35 +00:00
|
|
|
case "ak-stage-email":
|
2021-08-03 15:52:21 +00:00
|
|
|
return html`<ak-stage-email
|
|
|
|
.host=${this as StageHost}
|
|
|
|
.challenge=${this.challenge}
|
|
|
|
></ak-stage-email>`;
|
2021-02-21 21:01:35 +00:00
|
|
|
case "ak-stage-autosubmit":
|
2021-08-03 15:52:21 +00:00
|
|
|
return html`<ak-stage-autosubmit
|
|
|
|
.host=${this as StageHost}
|
|
|
|
.challenge=${this.challenge}
|
|
|
|
></ak-stage-autosubmit>`;
|
2021-02-21 21:01:35 +00:00
|
|
|
case "ak-stage-prompt":
|
2021-08-03 15:52:21 +00:00
|
|
|
return html`<ak-stage-prompt
|
|
|
|
.host=${this as StageHost}
|
|
|
|
.challenge=${this.challenge}
|
|
|
|
></ak-stage-prompt>`;
|
2021-02-21 21:01:35 +00:00
|
|
|
case "ak-stage-authenticator-totp":
|
2021-08-03 15:52:21 +00:00
|
|
|
return html`<ak-stage-authenticator-totp
|
|
|
|
.host=${this as StageHost}
|
|
|
|
.challenge=${this.challenge}
|
|
|
|
></ak-stage-authenticator-totp>`;
|
2021-05-23 19:04:37 +00:00
|
|
|
case "ak-stage-authenticator-duo":
|
2021-08-03 15:52:21 +00:00
|
|
|
return html`<ak-stage-authenticator-duo
|
|
|
|
.host=${this as StageHost}
|
|
|
|
.challenge=${this.challenge}
|
|
|
|
></ak-stage-authenticator-duo>`;
|
2021-02-21 21:01:35 +00:00
|
|
|
case "ak-stage-authenticator-static":
|
2021-08-03 15:52:21 +00:00
|
|
|
return html`<ak-stage-authenticator-static
|
|
|
|
.host=${this as StageHost}
|
|
|
|
.challenge=${this.challenge}
|
|
|
|
></ak-stage-authenticator-static>`;
|
2021-02-23 12:50:47 +00:00
|
|
|
case "ak-stage-authenticator-webauthn":
|
2021-08-03 15:52:21 +00:00
|
|
|
return html`<ak-stage-authenticator-webauthn
|
|
|
|
.host=${this as StageHost}
|
|
|
|
.challenge=${this.challenge}
|
|
|
|
></ak-stage-authenticator-webauthn>`;
|
2021-02-23 22:43:13 +00:00
|
|
|
case "ak-stage-authenticator-validate":
|
2021-08-03 15:52:21 +00:00
|
|
|
return html`<ak-stage-authenticator-validate
|
|
|
|
.host=${this as StageHost}
|
|
|
|
.challenge=${this.challenge}
|
|
|
|
></ak-stage-authenticator-validate>`;
|
2021-05-02 14:47:20 +00:00
|
|
|
case "ak-flow-sources-plex":
|
2021-08-03 15:52:21 +00:00
|
|
|
return html`<ak-flow-sources-plex
|
|
|
|
.host=${this as StageHost}
|
|
|
|
.challenge=${this.challenge}
|
|
|
|
></ak-flow-sources-plex>`;
|
2021-02-21 21:01:35 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
console.debug(`authentik/flows: unexpected data type ${this.challenge.type}`);
|
|
|
|
break;
|
2020-10-16 14:36:18 +00:00
|
|
|
}
|
2021-02-20 22:19:27 +00:00
|
|
|
return html``;
|
2020-10-16 14:36:18 +00:00
|
|
|
}
|
2021-02-21 21:01:35 +00:00
|
|
|
|
2021-03-21 16:36:51 +00:00
|
|
|
renderChallengeWrapper(): TemplateResult {
|
2021-02-21 21:01:35 +00:00
|
|
|
if (!this.challenge) {
|
2021-08-03 15:52:21 +00:00
|
|
|
return html`<ak-empty-state ?loading=${true} header=${t`Loading`}> </ak-empty-state>`;
|
2021-02-21 21:01:35 +00:00
|
|
|
}
|
2021-08-03 15:52:21 +00:00
|
|
|
return html` ${this.loading ? this.renderLoading() : html``} ${this.renderChallenge()} `;
|
2021-02-21 21:01:35 +00:00
|
|
|
}
|
2021-03-21 16:36:51 +00:00
|
|
|
|
|
|
|
render(): TemplateResult {
|
|
|
|
return html`<div class="pf-c-background-image">
|
2021-08-03 15:52:21 +00:00
|
|
|
<svg
|
|
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
|
|
class="pf-c-background-image__filter"
|
|
|
|
width="0"
|
|
|
|
height="0"
|
|
|
|
>
|
|
|
|
<filter id="image_overlay">
|
|
|
|
<feColorMatrix
|
|
|
|
in="SourceGraphic"
|
|
|
|
type="matrix"
|
|
|
|
values="1.3 0 0 0 0 0 1.3 0 0 0 0 0 1.3 0 0 0 0 0 1 0"
|
|
|
|
/>
|
|
|
|
<feComponentTransfer color-interpolation-filters="sRGB" result="duotone">
|
|
|
|
<feFuncR
|
|
|
|
type="table"
|
|
|
|
tableValues="0.086274509803922 0.43921568627451"
|
|
|
|
></feFuncR>
|
|
|
|
<feFuncG
|
|
|
|
type="table"
|
|
|
|
tableValues="0.086274509803922 0.43921568627451"
|
|
|
|
></feFuncG>
|
|
|
|
<feFuncB
|
|
|
|
type="table"
|
|
|
|
tableValues="0.086274509803922 0.43921568627451"
|
|
|
|
></feFuncB>
|
|
|
|
<feFuncA type="table" tableValues="0 1"></feFuncA>
|
|
|
|
</feComponentTransfer>
|
|
|
|
</filter>
|
|
|
|
</svg>
|
2021-03-21 16:36:51 +00:00
|
|
|
</div>
|
2021-08-03 15:52:21 +00:00
|
|
|
<div class="pf-c-login">
|
|
|
|
<div class="ak-login-container">
|
|
|
|
<header class="pf-c-login__header">
|
|
|
|
<div class="pf-c-brand ak-brand">
|
|
|
|
<img
|
|
|
|
src="${ifDefined(this.tenant?.brandingLogo)}"
|
|
|
|
alt="authentik icon"
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</header>
|
|
|
|
<div class="pf-c-login__main">${this.renderChallengeWrapper()}</div>
|
|
|
|
<footer class="pf-c-login__footer">
|
|
|
|
<p></p>
|
|
|
|
<ul class="pf-c-list pf-m-inline">
|
|
|
|
${until(
|
|
|
|
this.tenant?.uiFooterLinks?.map((link) => {
|
|
|
|
return html`<li>
|
|
|
|
<a href="${link.href || ""}">${link.name}</a>
|
|
|
|
</li>`;
|
|
|
|
}),
|
|
|
|
)}
|
|
|
|
${this.tenant?.brandingTitle != "authentik"
|
|
|
|
? html`
|
|
|
|
<li>
|
|
|
|
<a href="https://goauthentik.io"
|
|
|
|
>${t`Powered by authentik`}</a
|
|
|
|
>
|
|
|
|
</li>
|
|
|
|
`
|
|
|
|
: html``}
|
|
|
|
${this.challenge?.flowInfo?.background?.startsWith("/static")
|
|
|
|
? html`
|
|
|
|
<li>
|
2021-08-07 19:32:40 +00:00
|
|
|
<a href="https://unsplash.com/@wckd_official"
|
2021-08-03 15:52:21 +00:00
|
|
|
>${t`Background image`}</a
|
|
|
|
>
|
|
|
|
</li>
|
|
|
|
`
|
|
|
|
: html``}
|
|
|
|
</ul>
|
|
|
|
</footer>
|
|
|
|
</div>
|
|
|
|
</div>`;
|
2021-03-21 16:36:51 +00:00
|
|
|
}
|
2020-10-16 14:36:18 +00:00
|
|
|
}
|