flows: make use of oneOf OpenAPI to annotate all challenge types
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
@ -8,23 +8,3 @@ export interface Error {
|
||||
export interface ErrorDict {
|
||||
[key: string]: Error[];
|
||||
}
|
||||
|
||||
export interface Challenge {
|
||||
type: ChallengeChoices;
|
||||
component?: string;
|
||||
title?: string;
|
||||
response_errors?: ErrorDict;
|
||||
}
|
||||
|
||||
export interface WithUserInfoChallenge extends Challenge {
|
||||
pending_user: string;
|
||||
pending_user_avatar: string;
|
||||
}
|
||||
|
||||
export interface ShellChallenge extends Challenge {
|
||||
body: string;
|
||||
}
|
||||
|
||||
export interface RedirectChallenge extends Challenge {
|
||||
to: string;
|
||||
}
|
||||
|
||||
@ -25,29 +25,16 @@ import "./stages/identification/IdentificationStage";
|
||||
import "./stages/password/PasswordStage";
|
||||
import "./stages/prompt/PromptStage";
|
||||
import "./sources/plex/PlexLoginInit";
|
||||
import { ShellChallenge, RedirectChallenge } from "../api/Flows";
|
||||
import { IdentificationChallenge } from "./stages/identification/IdentificationStage";
|
||||
import { PasswordChallenge } from "./stages/password/PasswordStage";
|
||||
import { ConsentChallenge } from "./stages/consent/ConsentStage";
|
||||
import { EmailChallenge } from "./stages/email/EmailStage";
|
||||
import { AutosubmitChallenge } from "./stages/autosubmit/AutosubmitStage";
|
||||
import { PromptChallenge } from "./stages/prompt/PromptStage";
|
||||
import { AuthenticatorTOTPChallenge } from "./stages/authenticator_totp/AuthenticatorTOTPStage";
|
||||
import { AuthenticatorStaticChallenge } from "./stages/authenticator_static/AuthenticatorStaticStage";
|
||||
import { AuthenticatorValidateStageChallenge } from "./stages/authenticator_validate/AuthenticatorValidateStage";
|
||||
import { WebAuthnAuthenticatorRegisterChallenge } from "./stages/authenticator_webauthn/WebAuthnAuthenticatorRegisterStage";
|
||||
import { CaptchaChallenge } from "./stages/captcha/CaptchaStage";
|
||||
import { StageHost } from "./stages/base";
|
||||
import { Challenge, ChallengeChoices, Config, FlowsApi } from "authentik-api";
|
||||
import { Challenge, ChallengeChoices, Config, FlowsApi, RedirectChallenge, ShellChallenge } from "authentik-api";
|
||||
import { config, DEFAULT_CONFIG } from "../api/Config";
|
||||
import { ifDefined } from "lit-html/directives/if-defined";
|
||||
import { until } from "lit-html/directives/until";
|
||||
import { AccessDeniedChallenge } from "./access_denied/FlowAccessDenied";
|
||||
import { PFSize } from "../elements/Spinner";
|
||||
import { TITLE_DEFAULT } from "../constants";
|
||||
import { configureSentry } from "../api/Sentry";
|
||||
import { PlexAuthenticationChallenge } from "./sources/plex/PlexLoginInit";
|
||||
import { AuthenticatorDuoChallenge } from "./stages/authenticator_duo/AuthenticatorDuoStage";
|
||||
import { ChallengeResponseRequest } from "authentik-api/dist/models/ChallengeResponseRequest";
|
||||
|
||||
|
||||
@customElement("ak-flow-executor")
|
||||
export class FlowExecutor extends LitElement implements StageHost {
|
||||
@ -112,18 +99,18 @@ export class FlowExecutor extends LitElement implements StageHost {
|
||||
});
|
||||
}
|
||||
|
||||
submit<T>(formData?: T): Promise<void> {
|
||||
submit(payload: ChallengeResponseRequest): Promise<void> {
|
||||
payload.component = this.challenge.component;
|
||||
this.loading = true;
|
||||
return new FlowsApi(DEFAULT_CONFIG).flowsExecutorSolveRaw({
|
||||
return new FlowsApi(DEFAULT_CONFIG).flowsExecutorSolve({
|
||||
flowSlug: this.flowSlug,
|
||||
requestBody: formData || {},
|
||||
query: window.location.search.substring(1),
|
||||
}).then((challengeRaw) => {
|
||||
return challengeRaw.raw.json();
|
||||
challengeResponseRequest: payload,
|
||||
}).then((data) => {
|
||||
this.challenge = data;
|
||||
this.postUpdate();
|
||||
}).catch((e: Response) => {
|
||||
console.debug(e);
|
||||
this.errorMessage(e.statusText);
|
||||
}).finally(() => {
|
||||
this.loading = false;
|
||||
@ -135,19 +122,18 @@ export class FlowExecutor extends LitElement implements StageHost {
|
||||
this.config = config;
|
||||
});
|
||||
this.loading = true;
|
||||
new FlowsApi(DEFAULT_CONFIG).flowsExecutorGetRaw({
|
||||
new FlowsApi(DEFAULT_CONFIG).flowsExecutorGet({
|
||||
flowSlug: this.flowSlug,
|
||||
query: window.location.search.substring(1),
|
||||
}).then((challengeRaw) => {
|
||||
return challengeRaw.raw.json();
|
||||
}).then((challenge) => {
|
||||
this.challenge = challenge as Challenge;
|
||||
this.challenge = challenge;
|
||||
// Only set background on first update, flow won't change throughout execution
|
||||
if (this.challenge?.background) {
|
||||
this.setBackground(this.challenge.background);
|
||||
}
|
||||
this.postUpdate();
|
||||
}).catch((e: Response) => {
|
||||
console.debug(e);
|
||||
// Catch JSON or Update errors
|
||||
this.errorMessage(e.statusText);
|
||||
}).finally(() => {
|
||||
@ -202,35 +188,35 @@ export class FlowExecutor extends LitElement implements StageHost {
|
||||
case ChallengeChoices.Native:
|
||||
switch (this.challenge.component) {
|
||||
case "ak-stage-access-denied":
|
||||
return html`<ak-stage-access-denied .host=${this} .challenge=${this.challenge as AccessDeniedChallenge}></ak-stage-access-denied>`;
|
||||
return html`<ak-stage-access-denied .host=${this} .challenge=${this.challenge}></ak-stage-access-denied>`;
|
||||
case "ak-stage-identification":
|
||||
return html`<ak-stage-identification .host=${this} .challenge=${this.challenge as IdentificationChallenge}></ak-stage-identification>`;
|
||||
return html`<ak-stage-identification .host=${this} .challenge=${this.challenge}></ak-stage-identification>`;
|
||||
case "ak-stage-password":
|
||||
return html`<ak-stage-password .host=${this} .challenge=${this.challenge as PasswordChallenge}></ak-stage-password>`;
|
||||
return html`<ak-stage-password .host=${this} .challenge=${this.challenge}></ak-stage-password>`;
|
||||
case "ak-stage-captcha":
|
||||
return html`<ak-stage-captcha .host=${this} .challenge=${this.challenge as CaptchaChallenge}></ak-stage-captcha>`;
|
||||
return html`<ak-stage-captcha .host=${this} .challenge=${this.challenge}></ak-stage-captcha>`;
|
||||
case "ak-stage-consent":
|
||||
return html`<ak-stage-consent .host=${this} .challenge=${this.challenge as ConsentChallenge}></ak-stage-consent>`;
|
||||
return html`<ak-stage-consent .host=${this} .challenge=${this.challenge}></ak-stage-consent>`;
|
||||
case "ak-stage-dummy":
|
||||
return html`<ak-stage-dummy .host=${this} .challenge=${this.challenge as Challenge}></ak-stage-dummy>`;
|
||||
return html`<ak-stage-dummy .host=${this} .challenge=${this.challenge}></ak-stage-dummy>`;
|
||||
case "ak-stage-email":
|
||||
return html`<ak-stage-email .host=${this} .challenge=${this.challenge as EmailChallenge}></ak-stage-email>`;
|
||||
return html`<ak-stage-email .host=${this} .challenge=${this.challenge}></ak-stage-email>`;
|
||||
case "ak-stage-autosubmit":
|
||||
return html`<ak-stage-autosubmit .host=${this} .challenge=${this.challenge as AutosubmitChallenge}></ak-stage-autosubmit>`;
|
||||
return html`<ak-stage-autosubmit .host=${this} .challenge=${this.challenge}></ak-stage-autosubmit>`;
|
||||
case "ak-stage-prompt":
|
||||
return html`<ak-stage-prompt .host=${this} .challenge=${this.challenge as PromptChallenge}></ak-stage-prompt>`;
|
||||
return html`<ak-stage-prompt .host=${this} .challenge=${this.challenge}></ak-stage-prompt>`;
|
||||
case "ak-stage-authenticator-totp":
|
||||
return html`<ak-stage-authenticator-totp .host=${this} .challenge=${this.challenge as AuthenticatorTOTPChallenge}></ak-stage-authenticator-totp>`;
|
||||
return html`<ak-stage-authenticator-totp .host=${this} .challenge=${this.challenge}></ak-stage-authenticator-totp>`;
|
||||
case "ak-stage-authenticator-duo":
|
||||
return html`<ak-stage-authenticator-duo .host=${this} .challenge=${this.challenge as AuthenticatorDuoChallenge}></ak-stage-authenticator-duo>`;
|
||||
return html`<ak-stage-authenticator-duo .host=${this} .challenge=${this.challenge}></ak-stage-authenticator-duo>`;
|
||||
case "ak-stage-authenticator-static":
|
||||
return html`<ak-stage-authenticator-static .host=${this} .challenge=${this.challenge as AuthenticatorStaticChallenge}></ak-stage-authenticator-static>`;
|
||||
return html`<ak-stage-authenticator-static .host=${this} .challenge=${this.challenge}></ak-stage-authenticator-static>`;
|
||||
case "ak-stage-authenticator-webauthn":
|
||||
return html`<ak-stage-authenticator-webauthn .host=${this} .challenge=${this.challenge as WebAuthnAuthenticatorRegisterChallenge}></ak-stage-authenticator-webauthn>`;
|
||||
return html`<ak-stage-authenticator-webauthn .host=${this} .challenge=${this.challenge}></ak-stage-authenticator-webauthn>`;
|
||||
case "ak-stage-authenticator-validate":
|
||||
return html`<ak-stage-authenticator-validate .host=${this} .challenge=${this.challenge as AuthenticatorValidateStageChallenge}></ak-stage-authenticator-validate>`;
|
||||
return html`<ak-stage-authenticator-validate .host=${this} .challenge=${this.challenge}></ak-stage-authenticator-validate>`;
|
||||
case "ak-flow-sources-plex":
|
||||
return html`<ak-flow-sources-plex .host=${this} .challenge=${this.challenge as PlexAuthenticationChallenge}></ak-flow-sources-plex>`;
|
||||
return html`<ak-flow-sources-plex .host=${this} .challenge=${this.challenge}></ak-flow-sources-plex>`;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -288,8 +274,7 @@ export class FlowExecutor extends LitElement implements StageHost {
|
||||
</li>`;
|
||||
}))}
|
||||
${this.config?.brandingTitle != "authentik" ? html`
|
||||
<li><a href="https://goauthentik.io">${t`Powered by authentik`}</a></li>
|
||||
` : html``}
|
||||
<li><a href="https://goauthentik.io">${t`Powered by authentik`}</a></li>` : html``}
|
||||
</ul>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Challenge } from "authentik-api";
|
||||
import { AccessDeniedChallenge } from "authentik-api";
|
||||
import { CSSResult, customElement, html, property, TemplateResult } from "lit-element";
|
||||
import { BaseStage } from "../stages/base";
|
||||
import PFLogin from "@patternfly/patternfly/components/Login/login.css";
|
||||
@ -12,10 +12,6 @@ import { t } from "@lingui/macro";
|
||||
|
||||
import "../../elements/EmptyState";
|
||||
|
||||
export interface AccessDeniedChallenge extends Challenge {
|
||||
error_message?: string;
|
||||
}
|
||||
|
||||
@customElement("ak-stage-access-denied")
|
||||
export class FlowAccessDenied extends BaseStage {
|
||||
|
||||
@ -45,9 +41,9 @@ export class FlowAccessDenied extends BaseStage {
|
||||
<i class="pf-icon pf-icon-error-circle-o"></i>
|
||||
${t`Request has been denied.`}
|
||||
</p>
|
||||
${this.challenge?.error_message &&
|
||||
${this.challenge?.errorMessage &&
|
||||
html`<hr>
|
||||
<p>${this.challenge.error_message}</p>`}
|
||||
<p>${this.challenge.errorMessage}</p>`}
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { t } from "@lingui/macro";
|
||||
import { Challenge } from "authentik-api";
|
||||
import { PlexAuthenticationChallenge } from "authentik-api";
|
||||
import PFLogin from "@patternfly/patternfly/components/Login/login.css";
|
||||
import PFForm from "@patternfly/patternfly/components/Form/form.css";
|
||||
import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css";
|
||||
@ -16,12 +16,6 @@ import { SourcesApi } from "authentik-api";
|
||||
import { showMessage } from "../../../elements/messages/MessageContainer";
|
||||
import { MessageLevel } from "../../../elements/messages/Message";
|
||||
|
||||
export interface PlexAuthenticationChallenge extends Challenge {
|
||||
|
||||
client_id: string;
|
||||
slug: string;
|
||||
|
||||
}
|
||||
|
||||
@customElement("ak-flow-sources-plex")
|
||||
export class PlexLoginInit extends BaseStage {
|
||||
@ -34,9 +28,9 @@ export class PlexLoginInit extends BaseStage {
|
||||
}
|
||||
|
||||
async firstUpdated(): Promise<void> {
|
||||
const authInfo = await PlexAPIClient.getPin(this.challenge?.client_id || "");
|
||||
const authInfo = await PlexAPIClient.getPin(this.challenge?.clientId || "");
|
||||
const authWindow = popupCenterScreen(authInfo.authUrl, "plex auth", 550, 700);
|
||||
PlexAPIClient.pinPoll(this.challenge?.client_id || "", authInfo.pin.id).then(token => {
|
||||
PlexAPIClient.pinPoll(this.challenge?.clientId || "", authInfo.pin.id).then(token => {
|
||||
authWindow?.close();
|
||||
new SourcesApi(DEFAULT_CONFIG).sourcesPlexRedeemTokenCreate({
|
||||
plexTokenRedeemRequest: {
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { t } from "@lingui/macro";
|
||||
import { CSSResult, customElement, html, property, TemplateResult } from "lit-element";
|
||||
import { WithUserInfoChallenge } from "../../../api/Flows";
|
||||
import PFLogin from "@patternfly/patternfly/components/Login/login.css";
|
||||
import PFForm from "@patternfly/patternfly/components/Form/form.css";
|
||||
import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css";
|
||||
@ -13,15 +12,9 @@ import "../../../elements/forms/FormElement";
|
||||
import "../../../elements/EmptyState";
|
||||
import "../../FormStatic";
|
||||
import { FlowURLManager } from "../../../api/legacy";
|
||||
import { StagesApi } from "authentik-api";
|
||||
import { AuthenticatorDuoChallenge, StagesApi } from "authentik-api";
|
||||
import { DEFAULT_CONFIG } from "../../../api/Config";
|
||||
|
||||
export interface AuthenticatorDuoChallenge extends WithUserInfoChallenge {
|
||||
activation_barcode: string;
|
||||
activation_code: string;
|
||||
stage_uuid: string;
|
||||
}
|
||||
|
||||
@customElement("ak-stage-authenticator-duo")
|
||||
export class AuthenticatorDuoStage extends BaseStage {
|
||||
|
||||
@ -42,10 +35,11 @@ export class AuthenticatorDuoStage extends BaseStage {
|
||||
|
||||
checkEnrollStatus(): Promise<void> {
|
||||
return new StagesApi(DEFAULT_CONFIG).stagesAuthenticatorDuoEnrollmentStatusCreate({
|
||||
stageUuid: this.challenge?.stage_uuid || "",
|
||||
}).then(r => {
|
||||
stageUuid: this.challenge?.stageUuid || "",
|
||||
}).then(() => {
|
||||
this.host?.submit({});
|
||||
}).catch(e => {
|
||||
}).catch(() => {
|
||||
console.debug("authentik/flows/duo: Waiting for auth status");
|
||||
});
|
||||
}
|
||||
|
||||
@ -65,17 +59,17 @@ export class AuthenticatorDuoStage extends BaseStage {
|
||||
<form class="pf-c-form" @submit=${(e: Event) => { this.submitForm(e); }}>
|
||||
<ak-form-static
|
||||
class="pf-c-form__group"
|
||||
userAvatar="${this.challenge.pending_user_avatar}"
|
||||
user=${this.challenge.pending_user}>
|
||||
userAvatar="${this.challenge.pendingUserAvatar}"
|
||||
user=${this.challenge.pendingUser}>
|
||||
<div slot="link">
|
||||
<a href="${FlowURLManager.cancel()}">${t`Not you?`}</a>
|
||||
</div>
|
||||
</ak-form-static>
|
||||
<img src=${this.challenge.activation_barcode} />
|
||||
<img src=${this.challenge.activationBarcode} />
|
||||
<p>
|
||||
${t`Alternatively, if your current device has Duo installed, click on this link:`}
|
||||
</p>
|
||||
<a href=${this.challenge.activation_code}>${t`Duo activation`}</a>
|
||||
<a href=${this.challenge.activationCode}>${t`Duo activation`}</a>
|
||||
|
||||
<div class="pf-c-form__group pf-m-action">
|
||||
<button type="button" class="pf-c-button pf-m-primary pf-m-block" @click=${() => {
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { t } from "@lingui/macro";
|
||||
import { css, CSSResult, customElement, html, property, TemplateResult } from "lit-element";
|
||||
import { WithUserInfoChallenge } from "../../../api/Flows";
|
||||
import PFLogin from "@patternfly/patternfly/components/Login/login.css";
|
||||
import PFForm from "@patternfly/patternfly/components/Form/form.css";
|
||||
import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css";
|
||||
@ -13,6 +12,7 @@ import "../../../elements/forms/FormElement";
|
||||
import "../../../elements/EmptyState";
|
||||
import "../../FormStatic";
|
||||
import { FlowURLManager } from "../../../api/legacy";
|
||||
import { AuthenticatorStaticChallenge } from "authentik-api";
|
||||
|
||||
export const STATIC_TOKEN_STYLE = css`
|
||||
/* Static OTP Tokens */
|
||||
@ -29,9 +29,6 @@ export const STATIC_TOKEN_STYLE = css`
|
||||
}
|
||||
`;
|
||||
|
||||
export interface AuthenticatorStaticChallenge extends WithUserInfoChallenge {
|
||||
codes: number[];
|
||||
}
|
||||
|
||||
@customElement("ak-stage-authenticator-static")
|
||||
export class AuthenticatorStaticStage extends BaseStage {
|
||||
@ -59,8 +56,8 @@ export class AuthenticatorStaticStage extends BaseStage {
|
||||
<form class="pf-c-form" @submit=${(e: Event) => { this.submitForm(e); }}>
|
||||
<ak-form-static
|
||||
class="pf-c-form__group"
|
||||
userAvatar="${this.challenge.pending_user_avatar}"
|
||||
user=${this.challenge.pending_user}>
|
||||
userAvatar="${this.challenge.pendingUserAvatar}"
|
||||
user=${this.challenge.pendingUser}>
|
||||
<div slot="link">
|
||||
<a href="${FlowURLManager.cancel()}">${t`Not you?`}</a>
|
||||
</div>
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { t } from "@lingui/macro";
|
||||
import { CSSResult, customElement, html, property, TemplateResult } from "lit-element";
|
||||
import { WithUserInfoChallenge } from "../../../api/Flows";
|
||||
import PFLogin from "@patternfly/patternfly/components/Login/login.css";
|
||||
import PFForm from "@patternfly/patternfly/components/Form/form.css";
|
||||
import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css";
|
||||
@ -16,10 +15,8 @@ import "../../../elements/EmptyState";
|
||||
import "../../FormStatic";
|
||||
import { MessageLevel } from "../../../elements/messages/Message";
|
||||
import { FlowURLManager } from "../../../api/legacy";
|
||||
import { AuthenticatorTOTPChallenge } from "authentik-api";
|
||||
|
||||
export interface AuthenticatorTOTPChallenge extends WithUserInfoChallenge {
|
||||
config_url: string;
|
||||
}
|
||||
|
||||
@customElement("ak-stage-authenticator-totp")
|
||||
export class AuthenticatorTOTPStage extends BaseStage {
|
||||
@ -47,20 +44,20 @@ export class AuthenticatorTOTPStage extends BaseStage {
|
||||
<form class="pf-c-form" @submit=${(e: Event) => { this.submitForm(e); }}>
|
||||
<ak-form-static
|
||||
class="pf-c-form__group"
|
||||
userAvatar="${this.challenge.pending_user_avatar}"
|
||||
user=${this.challenge.pending_user}>
|
||||
userAvatar="${this.challenge.pendingUserAvatar}"
|
||||
user=${this.challenge.pendingUser}>
|
||||
<div slot="link">
|
||||
<a href="${FlowURLManager.cancel()}">${t`Not you?`}</a>
|
||||
</div>
|
||||
</ak-form-static>
|
||||
<input type="hidden" name="otp_uri" value=${this.challenge.config_url} />
|
||||
<input type="hidden" name="otp_uri" value=${this.challenge.configUrl} />
|
||||
<ak-form-element>
|
||||
<!-- @ts-ignore -->
|
||||
<qr-code data="${this.challenge.config_url}"></qr-code>
|
||||
<qr-code data="${this.challenge.configUrl}"></qr-code>
|
||||
<button type="button" class="pf-c-button pf-m-secondary pf-m-progress pf-m-in-progress" @click=${(e: Event) => {
|
||||
e.preventDefault();
|
||||
if (!this.challenge?.config_url) return;
|
||||
navigator.clipboard.writeText(this.challenge?.config_url).then(() => {
|
||||
if (!this.challenge?.configUrl) return;
|
||||
navigator.clipboard.writeText(this.challenge?.configUrl).then(() => {
|
||||
showMessage({
|
||||
level: MessageLevel.success,
|
||||
message: t`Successfully copied TOTP Config.`
|
||||
@ -75,7 +72,7 @@ export class AuthenticatorTOTPStage extends BaseStage {
|
||||
label="${t`Code`}"
|
||||
?required="${true}"
|
||||
class="pf-c-form__group"
|
||||
.errors=${(this.challenge?.response_errors || {})["code"]}>
|
||||
.errors=${(this.challenge?.responseErrors || {})["code"]}>
|
||||
<!-- @ts-ignore -->
|
||||
<input type="text"
|
||||
name="code"
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { t } from "@lingui/macro";
|
||||
import { css, CSSResult, customElement, html, property, TemplateResult } from "lit-element";
|
||||
import { WithUserInfoChallenge } from "../../../api/Flows";
|
||||
import PFLogin from "@patternfly/patternfly/components/Login/login.css";
|
||||
import PFForm from "@patternfly/patternfly/components/Form/form.css";
|
||||
import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css";
|
||||
@ -13,6 +12,9 @@ import "./AuthenticatorValidateStageWebAuthn";
|
||||
import "./AuthenticatorValidateStageCode";
|
||||
import "./AuthenticatorValidateStageDuo";
|
||||
import { PasswordManagerPrefill } from "../identification/IdentificationStage";
|
||||
import { DeviceChallenge } from "authentik-api";
|
||||
import { AuthenticatorValidationChallenge } from "authentik-api/dist/models/AuthenticatorValidationChallenge";
|
||||
import { ChallengeResponseRequest } from "authentik-api/dist/models/ChallengeResponseRequest";
|
||||
|
||||
export enum DeviceClasses {
|
||||
STATIC = "static",
|
||||
@ -21,33 +23,17 @@ export enum DeviceClasses {
|
||||
DUO = "duo",
|
||||
}
|
||||
|
||||
export interface DeviceChallenge {
|
||||
device_class: DeviceClasses;
|
||||
device_uid: string;
|
||||
challenge: unknown;
|
||||
}
|
||||
|
||||
export interface AuthenticatorValidateStageChallenge extends WithUserInfoChallenge {
|
||||
device_challenges: DeviceChallenge[];
|
||||
}
|
||||
|
||||
export interface AuthenticatorValidateStageChallengeResponse {
|
||||
code?: string;
|
||||
webauthn?: string;
|
||||
duo?: number;
|
||||
}
|
||||
|
||||
@customElement("ak-stage-authenticator-validate")
|
||||
export class AuthenticatorValidateStage extends BaseStage implements StageHost {
|
||||
|
||||
@property({ attribute: false })
|
||||
challenge?: AuthenticatorValidateStageChallenge;
|
||||
challenge?: AuthenticatorValidationChallenge;
|
||||
|
||||
@property({attribute: false})
|
||||
selectedDeviceChallenge?: DeviceChallenge;
|
||||
|
||||
submit<T>(formData?: T): Promise<void> {
|
||||
return this.host?.submit<T>(formData) || Promise.resolve();
|
||||
submit(payload: ChallengeResponseRequest): Promise<void> {
|
||||
return this.host?.submit(payload) || Promise.resolve();
|
||||
}
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
@ -79,7 +65,7 @@ export class AuthenticatorValidateStage extends BaseStage implements StageHost {
|
||||
}
|
||||
|
||||
renderDevicePickerSingle(deviceChallenge: DeviceChallenge): TemplateResult {
|
||||
switch (deviceChallenge.device_class) {
|
||||
switch (deviceChallenge.deviceClass) {
|
||||
case DeviceClasses.DUO:
|
||||
return html`<i class="fas fa-mobile-alt"></i>
|
||||
<div class="right">
|
||||
@ -124,7 +110,7 @@ export class AuthenticatorValidateStage extends BaseStage implements StageHost {
|
||||
renderDevicePicker(): TemplateResult {
|
||||
return html`
|
||||
<ul>
|
||||
${this.challenge?.device_challenges.map((challenges) => {
|
||||
${this.challenge?.deviceChallenges.map((challenges) => {
|
||||
return html`<li>
|
||||
<button class="pf-c-button authenticator-button" type="button" @click=${() => {
|
||||
this.selectedDeviceChallenge = challenges;
|
||||
@ -140,30 +126,31 @@ export class AuthenticatorValidateStage extends BaseStage implements StageHost {
|
||||
if (!this.selectedDeviceChallenge) {
|
||||
return html``;
|
||||
}
|
||||
switch (this.selectedDeviceChallenge?.device_class) {
|
||||
switch (this.selectedDeviceChallenge?.deviceClass) {
|
||||
case DeviceClasses.STATIC:
|
||||
case DeviceClasses.TOTP:
|
||||
return html`<ak-stage-authenticator-validate-code
|
||||
.host=${this}
|
||||
.host=${this as StageHost}
|
||||
.challenge=${this.challenge}
|
||||
.deviceChallenge=${this.selectedDeviceChallenge}
|
||||
.showBackButton=${(this.challenge?.device_challenges.length || []) > 1}>
|
||||
.showBackButton=${(this.challenge?.deviceChallenges.length || []) > 1}>
|
||||
</ak-stage-authenticator-validate-code>`;
|
||||
case DeviceClasses.WEBAUTHN:
|
||||
return html`<ak-stage-authenticator-validate-webauthn
|
||||
.host=${this}
|
||||
.host=${this as StageHost}
|
||||
.challenge=${this.challenge}
|
||||
.deviceChallenge=${this.selectedDeviceChallenge}
|
||||
.showBackButton=${(this.challenge?.device_challenges.length || []) > 1}>
|
||||
.showBackButton=${(this.challenge?.deviceChallenges.length || []) > 1}>
|
||||
</ak-stage-authenticator-validate-webauthn>`;
|
||||
case DeviceClasses.DUO:
|
||||
return html`<ak-stage-authenticator-validate-duo
|
||||
.host=${this}
|
||||
.host=${this as StageHost}
|
||||
.challenge=${this.challenge}
|
||||
.deviceChallenge=${this.selectedDeviceChallenge}
|
||||
.showBackButton=${(this.challenge?.device_challenges.length || []) > 1}>
|
||||
.showBackButton=${(this.challenge?.deviceChallenges.length || []) > 1}>
|
||||
</ak-stage-authenticator-validate-duo>`;
|
||||
}
|
||||
return html``;
|
||||
}
|
||||
|
||||
render(): TemplateResult {
|
||||
@ -174,8 +161,8 @@ export class AuthenticatorValidateStage extends BaseStage implements StageHost {
|
||||
</ak-empty-state>`;
|
||||
}
|
||||
// User only has a single device class, so we don't show a picker
|
||||
if (this.challenge?.device_challenges.length === 1) {
|
||||
this.selectedDeviceChallenge = this.challenge.device_challenges[0];
|
||||
if (this.challenge?.deviceChallenges.length === 1) {
|
||||
this.selectedDeviceChallenge = this.challenge.deviceChallenges[0];
|
||||
}
|
||||
return html`<header class="pf-c-login__main-header">
|
||||
<h1 class="pf-c-title pf-m-3xl">
|
||||
|
||||
@ -8,18 +8,20 @@ import PFButton from "@patternfly/patternfly/components/Button/button.css";
|
||||
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||
import AKGlobal from "../../../authentik.css";
|
||||
import { BaseStage } from "../base";
|
||||
import { AuthenticatorValidateStage, AuthenticatorValidateStageChallenge, DeviceChallenge } from "./AuthenticatorValidateStage";
|
||||
import { AuthenticatorValidateStage } from "./AuthenticatorValidateStage";
|
||||
import "../../../elements/forms/FormElement";
|
||||
import "../../../elements/EmptyState";
|
||||
import { PasswordManagerPrefill } from "../identification/IdentificationStage";
|
||||
import "../../FormStatic";
|
||||
import { FlowURLManager } from "../../../api/legacy";
|
||||
import { AuthenticatorValidationChallenge } from "authentik-api/dist/models/AuthenticatorValidationChallenge";
|
||||
import { DeviceChallenge } from "authentik-api";
|
||||
|
||||
@customElement("ak-stage-authenticator-validate-code")
|
||||
export class AuthenticatorValidateStageWebCode extends BaseStage {
|
||||
|
||||
@property({ attribute: false })
|
||||
challenge?: AuthenticatorValidateStageChallenge;
|
||||
challenge?: AuthenticatorValidationChallenge;
|
||||
|
||||
@property({ attribute: false })
|
||||
deviceChallenge?: DeviceChallenge;
|
||||
@ -42,8 +44,8 @@ export class AuthenticatorValidateStageWebCode extends BaseStage {
|
||||
<form class="pf-c-form" @submit=${(e: Event) => { this.submitForm(e); }}>
|
||||
<ak-form-static
|
||||
class="pf-c-form__group"
|
||||
userAvatar="${this.challenge.pending_user_avatar}"
|
||||
user=${this.challenge.pending_user}>
|
||||
userAvatar="${this.challenge.pendingUserAvatar}"
|
||||
user=${this.challenge.pendingUser}>
|
||||
<div slot="link">
|
||||
<a href="${FlowURLManager.cancel()}">${t`Not you?`}</a>
|
||||
</div>
|
||||
@ -52,7 +54,7 @@ export class AuthenticatorValidateStageWebCode extends BaseStage {
|
||||
label="${t`Code`}"
|
||||
?required="${true}"
|
||||
class="pf-c-form__group"
|
||||
.errors=${(this.challenge?.response_errors || {})["code"]}>
|
||||
.errors=${(this.challenge?.responseErrors || {})["code"]}>
|
||||
<!-- @ts-ignore -->
|
||||
<input type="text"
|
||||
name="code"
|
||||
|
||||
@ -8,18 +8,19 @@ import PFButton from "@patternfly/patternfly/components/Button/button.css";
|
||||
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||
import AKGlobal from "../../../authentik.css";
|
||||
import { BaseStage } from "../base";
|
||||
import { AuthenticatorValidateStage, AuthenticatorValidateStageChallenge, DeviceChallenge } from "./AuthenticatorValidateStage";
|
||||
import { AuthenticatorValidateStage } from "./AuthenticatorValidateStage";
|
||||
import "../../../elements/forms/FormElement";
|
||||
import "../../../elements/EmptyState";
|
||||
import { PasswordManagerPrefill } from "../identification/IdentificationStage";
|
||||
import "../../FormStatic";
|
||||
import { FlowURLManager } from "../../../api/legacy";
|
||||
import { AuthenticatorValidationChallenge } from "authentik-api/dist/models/AuthenticatorValidationChallenge";
|
||||
import { DeviceChallenge } from "authentik-api";
|
||||
|
||||
@customElement("ak-stage-authenticator-validate-duo")
|
||||
export class AuthenticatorValidateStageWebDuo extends BaseStage {
|
||||
|
||||
@property({ attribute: false })
|
||||
challenge?: AuthenticatorValidateStageChallenge;
|
||||
challenge?: AuthenticatorValidationChallenge;
|
||||
|
||||
@property({ attribute: false })
|
||||
deviceChallenge?: DeviceChallenge;
|
||||
@ -33,7 +34,7 @@ export class AuthenticatorValidateStageWebDuo extends BaseStage {
|
||||
|
||||
firstUpdated(): void {
|
||||
this.host?.submit({
|
||||
"duo": this.deviceChallenge?.device_uid
|
||||
"duo": this.deviceChallenge?.deviceUid
|
||||
});
|
||||
}
|
||||
|
||||
@ -48,8 +49,8 @@ export class AuthenticatorValidateStageWebDuo extends BaseStage {
|
||||
<form class="pf-c-form" @submit=${(e: Event) => { this.submitForm(e); }}>
|
||||
<ak-form-static
|
||||
class="pf-c-form__group"
|
||||
userAvatar="${this.challenge.pending_user_avatar}"
|
||||
user=${this.challenge.pending_user}>
|
||||
userAvatar="${this.challenge.pendingUserAvatar}"
|
||||
user=${this.challenge.pendingUser}>
|
||||
<div slot="link">
|
||||
<a href="${FlowURLManager.cancel()}">${t`Not you?`}</a>
|
||||
</div>
|
||||
|
||||
@ -10,13 +10,15 @@ import AKGlobal from "../../../authentik.css";
|
||||
import { PFSize } from "../../../elements/Spinner";
|
||||
import { transformAssertionForServer, transformCredentialRequestOptions } from "../authenticator_webauthn/utils";
|
||||
import { BaseStage } from "../base";
|
||||
import { AuthenticatorValidateStage, AuthenticatorValidateStageChallenge, DeviceChallenge } from "./AuthenticatorValidateStage";
|
||||
import { AuthenticatorValidateStage } from "./AuthenticatorValidateStage";
|
||||
import { AuthenticatorValidationChallenge } from "authentik-api/dist/models/AuthenticatorValidationChallenge";
|
||||
import { DeviceChallenge } from "authentik-api";
|
||||
|
||||
@customElement("ak-stage-authenticator-validate-webauthn")
|
||||
export class AuthenticatorValidateStageWebAuthn extends BaseStage {
|
||||
|
||||
@property({attribute: false})
|
||||
challenge?: AuthenticatorValidateStageChallenge;
|
||||
challenge?: AuthenticatorValidationChallenge;
|
||||
|
||||
@property({attribute: false})
|
||||
deviceChallenge?: DeviceChallenge;
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { t } from "@lingui/macro";
|
||||
import { CSSResult, customElement, html, property, TemplateResult } from "lit-element";
|
||||
import { WithUserInfoChallenge } from "../../../api/Flows";
|
||||
import PFLogin from "@patternfly/patternfly/components/Login/login.css";
|
||||
import PFForm from "@patternfly/patternfly/components/Form/form.css";
|
||||
import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css";
|
||||
@ -11,10 +10,7 @@ import AKGlobal from "../../../authentik.css";
|
||||
import { PFSize } from "../../../elements/Spinner";
|
||||
import { BaseStage } from "../base";
|
||||
import { Assertion, transformCredentialCreateOptions, transformNewAssertionForServer } from "./utils";
|
||||
|
||||
export interface WebAuthnAuthenticatorRegisterChallenge extends WithUserInfoChallenge {
|
||||
registration: PublicKeyCredentialCreationOptions;
|
||||
}
|
||||
import { AuthenticatorWebAuthnChallenge } from "authentik-api";
|
||||
|
||||
export interface WebAuthnAuthenticatorRegisterChallengeResponse {
|
||||
response: Assertion;
|
||||
@ -24,7 +20,7 @@ export interface WebAuthnAuthenticatorRegisterChallengeResponse {
|
||||
export class WebAuthnAuthenticatorRegisterStage extends BaseStage {
|
||||
|
||||
@property({ attribute: false })
|
||||
challenge?: WebAuthnAuthenticatorRegisterChallenge;
|
||||
challenge?: AuthenticatorWebAuthnChallenge;
|
||||
|
||||
@property({type: Boolean})
|
||||
registerRunning = false;
|
||||
@ -42,7 +38,7 @@ export class WebAuthnAuthenticatorRegisterStage extends BaseStage {
|
||||
}
|
||||
// convert certain members of the PublicKeyCredentialCreateOptions into
|
||||
// byte arrays as expected by the spec.
|
||||
const publicKeyCredentialCreateOptions = transformCredentialCreateOptions(this.challenge?.registration);
|
||||
const publicKeyCredentialCreateOptions = transformCredentialCreateOptions(this.challenge?.registration as PublicKeyCredentialCreationOptions);
|
||||
|
||||
// request the authenticator(s) to create a new credential keypair.
|
||||
let credential;
|
||||
@ -106,8 +102,8 @@ export class WebAuthnAuthenticatorRegisterStage extends BaseStage {
|
||||
</div>`:
|
||||
html`
|
||||
<div class="pf-c-form__group pf-m-action">
|
||||
${this.challenge?.response_errors ?
|
||||
html`<p class="pf-m-block">${this.challenge.response_errors["response"][0].string}</p>`:
|
||||
${this.challenge?.responseErrors ?
|
||||
html`<p class="pf-m-block">${this.challenge.responseErrors["response"][0].string}</p>`:
|
||||
html``}
|
||||
<p class="pf-m-block">${this.registerMessage}</p>
|
||||
<button class="pf-c-button pf-m-primary pf-m-block" @click=${() => {
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { t } from "@lingui/macro";
|
||||
import { CSSResult, customElement, html, property, TemplateResult } from "lit-element";
|
||||
import { WithUserInfoChallenge } from "../../../api/Flows";
|
||||
import PFLogin from "@patternfly/patternfly/components/Login/login.css";
|
||||
import PFForm from "@patternfly/patternfly/components/Form/form.css";
|
||||
import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css";
|
||||
@ -10,11 +9,7 @@ import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||
import AKGlobal from "../../../authentik.css";
|
||||
import { BaseStage } from "../base";
|
||||
import "../../../elements/EmptyState";
|
||||
|
||||
export interface AutosubmitChallenge extends WithUserInfoChallenge {
|
||||
url: string;
|
||||
attrs: { [key: string]: string };
|
||||
}
|
||||
import { AutosubmitChallenge } from "authentik-api";
|
||||
|
||||
@customElement("ak-stage-autosubmit")
|
||||
export class AutosubmitStage extends BaseStage {
|
||||
|
||||
@ -1,20 +1,25 @@
|
||||
import { Challenge } from "authentik-api";
|
||||
import { ChallengeResponseRequest } from "authentik-api/dist/models/ChallengeResponseRequest";
|
||||
import { LitElement } from "lit-element";
|
||||
|
||||
export interface StageHost {
|
||||
challenge?: Challenge;
|
||||
submit<T>(formData?: T): Promise<void>;
|
||||
submit(payload: ChallengeResponseRequest): Promise<void>;
|
||||
}
|
||||
|
||||
export class BaseStage extends LitElement {
|
||||
|
||||
host?: StageHost;
|
||||
challenge?: Challenge;
|
||||
|
||||
submitForm(e: Event): void {
|
||||
e.preventDefault();
|
||||
const object: {
|
||||
component: string;
|
||||
[key: string]: unknown;
|
||||
} = {};
|
||||
} = {
|
||||
component: this.challenge.component,
|
||||
};
|
||||
const form = new FormData(this.shadowRoot?.querySelector("form") || undefined);
|
||||
form.forEach((value, key) => object[key] = value);
|
||||
this.host?.submit(object);
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { t } from "@lingui/macro";
|
||||
import { CSSResult, customElement, html, property, TemplateResult } from "lit-element";
|
||||
import { WithUserInfoChallenge } from "../../../api/Flows";
|
||||
import PFLogin from "@patternfly/patternfly/components/Login/login.css";
|
||||
import PFForm from "@patternfly/patternfly/components/Form/form.css";
|
||||
import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css";
|
||||
@ -14,10 +13,7 @@ import "../../../elements/forms/FormElement";
|
||||
import "../../../elements/EmptyState";
|
||||
import "../../FormStatic";
|
||||
import { FlowURLManager } from "../../../api/legacy";
|
||||
|
||||
export interface CaptchaChallenge extends WithUserInfoChallenge {
|
||||
site_key: string;
|
||||
}
|
||||
import { CaptchaChallenge } from "authentik-api";
|
||||
|
||||
@customElement("ak-stage-captcha")
|
||||
export class CaptchaStage extends BaseStage {
|
||||
@ -39,10 +35,10 @@ export class CaptchaStage extends BaseStage {
|
||||
script.onload = () => {
|
||||
console.debug("authentik/stages/captcha: script loaded");
|
||||
grecaptcha.ready(() => {
|
||||
if (!this.challenge?.site_key) return;
|
||||
if (!this.challenge?.siteKey) return;
|
||||
console.debug("authentik/stages/captcha: ready");
|
||||
const captchaId = grecaptcha.render(captchaContainer, {
|
||||
sitekey: this.challenge.site_key,
|
||||
sitekey: this.challenge.siteKey,
|
||||
callback: (token) => {
|
||||
this.host?.submit({
|
||||
"token": token,
|
||||
@ -72,8 +68,8 @@ export class CaptchaStage extends BaseStage {
|
||||
<form class="pf-c-form">
|
||||
<ak-form-static
|
||||
class="pf-c-form__group"
|
||||
userAvatar="${this.challenge.pending_user_avatar}"
|
||||
user=${this.challenge.pending_user}>
|
||||
userAvatar="${this.challenge.pendingUserAvatar}"
|
||||
user=${this.challenge.pendingUser}>
|
||||
<div slot="link">
|
||||
<a href="${FlowURLManager.cancel()}">${t`Not you?`}</a>
|
||||
</div>
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { t } from "@lingui/macro";
|
||||
import { CSSResult, customElement, html, property, TemplateResult } from "lit-element";
|
||||
import { WithUserInfoChallenge } from "../../../api/Flows";
|
||||
import PFLogin from "@patternfly/patternfly/components/Login/login.css";
|
||||
import PFForm from "@patternfly/patternfly/components/Form/form.css";
|
||||
import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css";
|
||||
@ -12,18 +11,8 @@ import { BaseStage } from "../base";
|
||||
import "../../../elements/EmptyState";
|
||||
import "../../FormStatic";
|
||||
import { FlowURLManager } from "../../../api/legacy";
|
||||
import { ConsentChallenge } from "authentik-api";
|
||||
|
||||
export interface Permission {
|
||||
name: string;
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface ConsentChallenge extends WithUserInfoChallenge {
|
||||
|
||||
header_text: string;
|
||||
permissions?: Permission[];
|
||||
|
||||
}
|
||||
|
||||
@customElement("ak-stage-consent")
|
||||
export class ConsentStage extends BaseStage {
|
||||
@ -51,15 +40,15 @@ export class ConsentStage extends BaseStage {
|
||||
<form class="pf-c-form" @submit=${(e: Event) => { this.submitForm(e); }}>
|
||||
<ak-form-static
|
||||
class="pf-c-form__group"
|
||||
userAvatar="${this.challenge.pending_user_avatar}"
|
||||
user=${this.challenge.pending_user}>
|
||||
userAvatar="${this.challenge.pendingUserAvatar}"
|
||||
user=${this.challenge.pendingUser}>
|
||||
<div slot="link">
|
||||
<a href="${FlowURLManager.cancel()}">${t`Not you?`}</a>
|
||||
</div>
|
||||
</ak-form-static>
|
||||
<div class="pf-c-form__group">
|
||||
<p id="header-text">
|
||||
${this.challenge.header_text}
|
||||
${this.challenge.headerText}
|
||||
</p>
|
||||
<p>${t`Application requires following permissions`}</p>
|
||||
<ul class="pf-c-list" id="permmissions">
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { t } from "@lingui/macro";
|
||||
import { CSSResult, customElement, html, property, TemplateResult } from "lit-element";
|
||||
import { Challenge } from "../../../api/Flows";
|
||||
import PFLogin from "@patternfly/patternfly/components/Login/login.css";
|
||||
import PFForm from "@patternfly/patternfly/components/Form/form.css";
|
||||
import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css";
|
||||
@ -11,12 +10,13 @@ import AKGlobal from "../../../authentik.css";
|
||||
import { BaseStage } from "../base";
|
||||
import "../../../elements/EmptyState";
|
||||
import "../../FormStatic";
|
||||
import { DummyChallenge } from "authentik-api";
|
||||
|
||||
@customElement("ak-stage-dummy")
|
||||
export class DummyStage extends BaseStage {
|
||||
|
||||
@property({ attribute: false })
|
||||
challenge?: Challenge;
|
||||
challenge?: DummyChallenge;
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return [PFBase, PFLogin, PFForm, PFFormControl, PFTitle, PFButton, AKGlobal];
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { t } from "@lingui/macro";
|
||||
import { CSSResult, customElement, html, property, TemplateResult } from "lit-element";
|
||||
import { Challenge } from "authentik-api";
|
||||
import PFLogin from "@patternfly/patternfly/components/Login/login.css";
|
||||
import PFForm from "@patternfly/patternfly/components/Form/form.css";
|
||||
import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css";
|
||||
@ -10,8 +9,7 @@ import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||
import AKGlobal from "../../../authentik.css";
|
||||
import { BaseStage } from "../base";
|
||||
import "../../../elements/EmptyState";
|
||||
|
||||
export type EmailChallenge = Challenge;
|
||||
import { EmailChallenge } from "authentik-api";
|
||||
|
||||
@customElement("ak-stage-email")
|
||||
export class EmailStage extends BaseStage {
|
||||
|
||||
@ -10,7 +10,7 @@ import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||
import AKGlobal from "../../../authentik.css";
|
||||
import "../../../elements/forms/FormElement";
|
||||
import "../../../elements/EmptyState";
|
||||
import { Challenge } from "../../../api/Flows";
|
||||
import { IdentificationChallenge, UILoginButton } from "authentik-api";
|
||||
|
||||
export const PasswordManagerPrefill: {
|
||||
password: string | undefined;
|
||||
@ -20,24 +20,6 @@ export const PasswordManagerPrefill: {
|
||||
totp: undefined,
|
||||
};
|
||||
|
||||
export interface IdentificationChallenge extends Challenge {
|
||||
|
||||
user_fields?: string[];
|
||||
primary_action: string;
|
||||
sources?: UILoginButton[];
|
||||
|
||||
application_pre?: string;
|
||||
|
||||
enroll_url?: string;
|
||||
recovery_url?: string;
|
||||
|
||||
}
|
||||
|
||||
export interface UILoginButton {
|
||||
name: string;
|
||||
challenge: Challenge;
|
||||
icon_url?: string;
|
||||
}
|
||||
|
||||
@customElement("ak-stage-identification")
|
||||
export class IdentificationStage extends BaseStage {
|
||||
@ -131,8 +113,8 @@ export class IdentificationStage extends BaseStage {
|
||||
|
||||
renderSource(source: UILoginButton): TemplateResult {
|
||||
let icon = html`<i class="fas fas fa-share-square" title="${source.name}"></i>`;
|
||||
if (source.icon_url) {
|
||||
icon = html`<img src="${source.icon_url}" alt="${source.name}">`;
|
||||
if (source.iconUrl) {
|
||||
icon = html`<img src="${source.iconUrl}" alt="${source.name}">`;
|
||||
}
|
||||
return html`<li class="pf-c-login__main-footer-links-item">
|
||||
<button type="button" @click=${() => {
|
||||
@ -145,18 +127,18 @@ export class IdentificationStage extends BaseStage {
|
||||
}
|
||||
|
||||
renderFooter(): TemplateResult {
|
||||
if (!this.challenge?.enroll_url && !this.challenge?.recovery_url) {
|
||||
if (!this.challenge?.enrollUrl && !this.challenge?.recoveryUrl) {
|
||||
return html``;
|
||||
}
|
||||
return html`<div class="pf-c-login__main-footer-band">
|
||||
${this.challenge.enroll_url ? html`
|
||||
${this.challenge.enrollUrl ? html`
|
||||
<p class="pf-c-login__main-footer-band-item">
|
||||
${t`Need an account?`}
|
||||
<a id="enroll" href="${this.challenge.enroll_url}">${t`Sign up.`}</a>
|
||||
<a id="enroll" href="${this.challenge.enrollUrl}">${t`Sign up.`}</a>
|
||||
</p>` : html``}
|
||||
${this.challenge.recovery_url ? html`
|
||||
${this.challenge.recoveryUrl ? html`
|
||||
<p class="pf-c-login__main-footer-band-item">
|
||||
<a id="recovery" href="${this.challenge.recovery_url}">${t`Forgot username or password?`}</a>
|
||||
<a id="recovery" href="${this.challenge.recoveryUrl}">${t`Forgot username or password?`}</a>
|
||||
</p>` : html``}
|
||||
</div>`;
|
||||
}
|
||||
@ -164,15 +146,15 @@ export class IdentificationStage extends BaseStage {
|
||||
renderInput(): TemplateResult {
|
||||
let label = "";
|
||||
let type = "text";
|
||||
if (!this.challenge?.user_fields) {
|
||||
if (!this.challenge?.userFields) {
|
||||
return html`<p>
|
||||
${t`Select one of the sources below to login.`}
|
||||
</p>`;
|
||||
}
|
||||
if (this.challenge?.user_fields === ["email"]) {
|
||||
if (this.challenge?.userFields === ["email"]) {
|
||||
label = t`Email`;
|
||||
type = "email";
|
||||
} else if (this.challenge?.user_fields === ["username"]) {
|
||||
} else if (this.challenge?.userFields === ["username"]) {
|
||||
label = t`Username`;
|
||||
} else {
|
||||
label = t`Email or username`;
|
||||
@ -181,10 +163,10 @@ export class IdentificationStage extends BaseStage {
|
||||
label=${label}
|
||||
?required="${true}"
|
||||
class="pf-c-form__group"
|
||||
.errors=${(this.challenge?.response_errors || {})["uid_field"]}>
|
||||
.errors=${(this.challenge?.responseErrors || {})["uidField"]}>
|
||||
<!-- @ts-ignore -->
|
||||
<input type=${type}
|
||||
name="uid_field"
|
||||
name="uidField"
|
||||
placeholder="Email or Username"
|
||||
autofocus=""
|
||||
autocomplete="username"
|
||||
@ -193,7 +175,7 @@ export class IdentificationStage extends BaseStage {
|
||||
</ak-form-element>
|
||||
<div class="pf-c-form__group pf-m-action">
|
||||
<button type="submit" class="pf-c-button pf-m-primary pf-m-block">
|
||||
${this.challenge.primary_action}
|
||||
${this.challenge.primaryAction}
|
||||
</button>
|
||||
</div>`;
|
||||
}
|
||||
@ -212,9 +194,9 @@ export class IdentificationStage extends BaseStage {
|
||||
</header>
|
||||
<div class="pf-c-login__main-body">
|
||||
<form class="pf-c-form" @submit=${(e: Event) => {this.submitForm(e);}}>
|
||||
${this.challenge.application_pre ?
|
||||
${this.challenge.applicationPre ?
|
||||
html`<p>
|
||||
${t`Login to continue to ${this.challenge.application_pre}.`}
|
||||
${t`Login to continue to ${this.challenge.applicationPre}.`}
|
||||
</p>`:
|
||||
html``}
|
||||
${this.renderInput()}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { t } from "@lingui/macro";
|
||||
import { CSSResult, customElement, html, property, TemplateResult } from "lit-element";
|
||||
import { WithUserInfoChallenge } from "../../../api/Flows";
|
||||
import PFLogin from "@patternfly/patternfly/components/Login/login.css";
|
||||
import PFForm from "@patternfly/patternfly/components/Form/form.css";
|
||||
import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css";
|
||||
@ -14,10 +13,7 @@ import "../../../elements/EmptyState";
|
||||
import { PasswordManagerPrefill } from "../identification/IdentificationStage";
|
||||
import "../../FormStatic";
|
||||
import { FlowURLManager } from "../../../api/legacy";
|
||||
|
||||
export interface PasswordChallenge extends WithUserInfoChallenge {
|
||||
recovery_url?: string;
|
||||
}
|
||||
import { PasswordChallenge } from "authentik-api";
|
||||
|
||||
@customElement("ak-stage-password")
|
||||
export class PasswordStage extends BaseStage {
|
||||
@ -45,18 +41,18 @@ export class PasswordStage extends BaseStage {
|
||||
<form class="pf-c-form" @submit=${(e: Event) => {this.submitForm(e);}}>
|
||||
<ak-form-static
|
||||
class="pf-c-form__group"
|
||||
userAvatar="${this.challenge.pending_user_avatar}"
|
||||
user=${this.challenge.pending_user}>
|
||||
userAvatar="${this.challenge.pendingUserAvatar}"
|
||||
user=${this.challenge.pendingUser}>
|
||||
<div slot="link">
|
||||
<a href="${FlowURLManager.cancel()}">${t`Not you?`}</a>
|
||||
</div>
|
||||
</ak-form-static>
|
||||
<input name="username" autocomplete="username" type="hidden" value="${this.challenge.pending_user}">
|
||||
<input name="username" autocomplete="username" type="hidden" value="${this.challenge.pendingUser}">
|
||||
<ak-form-element
|
||||
label="${t`Password`}"
|
||||
?required="${true}"
|
||||
class="pf-c-form__group"
|
||||
.errors=${(this.challenge?.response_errors || {})["password"]}>
|
||||
.errors=${(this.challenge?.responseErrors || {})["password"]}>
|
||||
<input type="password"
|
||||
name="password"
|
||||
placeholder="${t`Please enter your password`}"
|
||||
@ -67,8 +63,8 @@ export class PasswordStage extends BaseStage {
|
||||
value=${PasswordManagerPrefill.password || ""}>
|
||||
</ak-form-element>
|
||||
|
||||
${this.challenge.recovery_url ?
|
||||
html`<a href="${this.challenge.recovery_url}">
|
||||
${this.challenge.recoveryUrl ?
|
||||
html`<a href="${this.challenge.recoveryUrl}">
|
||||
${t`Forgot password?`}</a>` : ""}
|
||||
|
||||
<div class="pf-c-form__group pf-m-action">
|
||||
|
||||
@ -13,20 +13,9 @@ import { BaseStage } from "../base";
|
||||
import "../../../elements/forms/FormElement";
|
||||
import "../../../elements/EmptyState";
|
||||
import "../../../elements/Divider";
|
||||
import { Challenge, Error } from "../../../api/Flows";
|
||||
import { Error } from "../../../api/Flows";
|
||||
import { Prompt, PromptChallenge } from "authentik-api";
|
||||
|
||||
export interface Prompt {
|
||||
field_key: string;
|
||||
label: string;
|
||||
type: string;
|
||||
required: boolean;
|
||||
placeholder: string;
|
||||
order: number;
|
||||
}
|
||||
|
||||
export interface PromptChallenge extends Challenge {
|
||||
fields: Prompt[];
|
||||
}
|
||||
|
||||
@customElement("ak-stage-prompt")
|
||||
export class PromptStage extends BaseStage {
|
||||
@ -43,7 +32,7 @@ export class PromptStage extends BaseStage {
|
||||
case "text":
|
||||
return `<input
|
||||
type="text"
|
||||
name="${prompt.field_key}"
|
||||
name="${prompt.fieldKey}"
|
||||
placeholder="${prompt.placeholder}"
|
||||
autocomplete="off"
|
||||
class="pf-c-form-control"
|
||||
@ -52,7 +41,7 @@ export class PromptStage extends BaseStage {
|
||||
case "username":
|
||||
return `<input
|
||||
type="text"
|
||||
name="${prompt.field_key}"
|
||||
name="${prompt.fieldKey}"
|
||||
placeholder="${prompt.placeholder}"
|
||||
autocomplete="username"
|
||||
class="pf-c-form-control"
|
||||
@ -61,7 +50,7 @@ export class PromptStage extends BaseStage {
|
||||
case "email":
|
||||
return `<input
|
||||
type="email"
|
||||
name="${prompt.field_key}"
|
||||
name="${prompt.fieldKey}"
|
||||
placeholder="${prompt.placeholder}"
|
||||
class="pf-c-form-control"
|
||||
?required=${prompt.required}
|
||||
@ -69,7 +58,7 @@ export class PromptStage extends BaseStage {
|
||||
case "password":
|
||||
return `<input
|
||||
type="password"
|
||||
name="${prompt.field_key}"
|
||||
name="${prompt.fieldKey}"
|
||||
placeholder="${prompt.placeholder}"
|
||||
autocomplete="new-password"
|
||||
class="pf-c-form-control"
|
||||
@ -77,28 +66,28 @@ export class PromptStage extends BaseStage {
|
||||
case "number":
|
||||
return `<input
|
||||
type="number"
|
||||
name="${prompt.field_key}"
|
||||
name="${prompt.fieldKey}"
|
||||
placeholder="${prompt.placeholder}"
|
||||
class="pf-c-form-control"
|
||||
?required=${prompt.required}>`;
|
||||
case "checkbox":
|
||||
return `<input
|
||||
type="checkbox"
|
||||
name="${prompt.field_key}"
|
||||
name="${prompt.fieldKey}"
|
||||
placeholder="${prompt.placeholder}"
|
||||
class="pf-c-form-control"
|
||||
?required=${prompt.required}>`;
|
||||
case "date":
|
||||
return `<input
|
||||
type="date"
|
||||
name="${prompt.field_key}"
|
||||
name="${prompt.fieldKey}"
|
||||
placeholder="${prompt.placeholder}"
|
||||
class="pf-c-form-control"
|
||||
?required=${prompt.required}>`;
|
||||
case "date-time":
|
||||
return `<input
|
||||
type="datetime"
|
||||
name="${prompt.field_key}"
|
||||
name="${prompt.fieldKey}"
|
||||
placeholder="${prompt.placeholder}"
|
||||
class="pf-c-form-control"
|
||||
?required=${prompt.required}>`;
|
||||
@ -107,7 +96,7 @@ export class PromptStage extends BaseStage {
|
||||
case "hidden":
|
||||
return `<input
|
||||
type="hidden"
|
||||
name="${prompt.field_key}"
|
||||
name="${prompt.fieldKey}"
|
||||
value="${prompt.placeholder}"
|
||||
class="pf-c-form-control"
|
||||
?required=${prompt.required}>`;
|
||||
@ -158,12 +147,12 @@ export class PromptStage extends BaseStage {
|
||||
label="${prompt.label}"
|
||||
?required="${prompt.required}"
|
||||
class="pf-c-form__group"
|
||||
.errors=${(this.challenge?.response_errors || {})[prompt.field_key]}>
|
||||
.errors=${(this.challenge?.responseErrors || {})[prompt.fieldKey]}>
|
||||
${unsafeHTML(this.renderPromptInner(prompt))}
|
||||
</ak-form-element>`;
|
||||
})}
|
||||
${"non_field_errors" in (this.challenge?.response_errors || {}) ?
|
||||
this.renderNonFieldErrors(this.challenge?.response_errors?.non_field_errors || []):
|
||||
${"non_field_errors" in (this.challenge?.responseErrors || {}) ?
|
||||
this.renderNonFieldErrors(this.challenge?.responseErrors?.non_field_errors || []):
|
||||
html``}
|
||||
<div class="pf-c-form__group pf-m-action">
|
||||
<button type="submit" class="pf-c-button pf-m-primary pf-m-block">
|
||||
|
||||
@ -63,6 +63,10 @@ msgstr "ANY, any policy must match to grant access."
|
||||
msgid "ANY, any policy must match to include this stage access."
|
||||
msgstr "ANY, any policy must match to include this stage access."
|
||||
|
||||
#: src/pages/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
|
||||
msgid "API Hostname"
|
||||
msgstr "API Hostname"
|
||||
|
||||
#: src/elements/notifications/APIDrawer.ts
|
||||
msgid "API Requests"
|
||||
msgstr "API Requests"
|
||||
@ -180,6 +184,10 @@ msgstr "Allows/denys requests based on the users and/or the IPs reputation."
|
||||
msgid "Also known as Entity ID. Defaults the Metadata URL."
|
||||
msgstr "Also known as Entity ID. Defaults the Metadata URL."
|
||||
|
||||
#: src/flows/stages/authenticator_duo/AuthenticatorDuoStage.ts
|
||||
msgid "Alternatively, if your current device has Duo installed, click on this link:"
|
||||
msgstr "Alternatively, if your current device has Duo installed, click on this link:"
|
||||
|
||||
#: src/pages/stages/consent/ConsentStageForm.ts
|
||||
msgid "Always require consent"
|
||||
msgstr "Always require consent"
|
||||
@ -522,6 +530,10 @@ msgstr "Check IP"
|
||||
msgid "Check Username"
|
||||
msgstr "Check Username"
|
||||
|
||||
#: src/flows/stages/authenticator_duo/AuthenticatorDuoStage.ts
|
||||
msgid "Check status"
|
||||
msgstr "Check status"
|
||||
|
||||
#: src/flows/stages/email/EmailStage.ts
|
||||
msgid "Check your Emails for a password reset link."
|
||||
msgstr "Check your Emails for a password reset link."
|
||||
@ -572,6 +584,7 @@ msgstr "Click to copy token"
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderViewPage.ts
|
||||
#: src/pages/sources/plex/PlexSourceForm.ts
|
||||
#: src/pages/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
|
||||
msgid "Client ID"
|
||||
msgstr "Client ID"
|
||||
|
||||
@ -583,6 +596,7 @@ msgid "Client IP"
|
||||
msgstr "Client IP"
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
|
||||
#: src/pages/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
|
||||
msgid "Client Secret"
|
||||
msgstr "Client Secret"
|
||||
|
||||
@ -616,6 +630,7 @@ msgstr "Confidential clients are capable of maintaining the confidentiality of t
|
||||
msgid "Configuration"
|
||||
msgstr "Configuration"
|
||||
|
||||
#: src/pages/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
|
||||
#: src/pages/stages/authenticator_static/AuthenticatorStaticStageForm.ts
|
||||
#: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
|
||||
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
||||
@ -715,6 +730,7 @@ msgstr "Context"
|
||||
#: src/flows/stages/authenticator_static/AuthenticatorStaticStage.ts
|
||||
#: src/flows/stages/authenticator_totp/AuthenticatorTOTPStage.ts
|
||||
#: src/flows/stages/authenticator_validate/AuthenticatorValidateStageCode.ts
|
||||
#: src/flows/stages/authenticator_validate/AuthenticatorValidateStageDuo.ts
|
||||
#: src/flows/stages/autosubmit/AutosubmitStage.ts
|
||||
#: src/flows/stages/consent/ConsentStage.ts
|
||||
#: src/flows/stages/dummy/DummyStage.ts
|
||||
@ -1010,6 +1026,10 @@ msgstr "Determines how authentik sends the response back to the Service Provider
|
||||
msgid "Determines how long a session lasts. Default of 0 seconds means that the sessions lasts until the browser is closed."
|
||||
msgstr "Determines how long a session lasts. Default of 0 seconds means that the sessions lasts until the browser is closed."
|
||||
|
||||
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
||||
msgid "Device classes"
|
||||
msgstr "Device classes"
|
||||
|
||||
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
||||
msgid "Device classes which can be used to authenticate."
|
||||
msgstr "Device classes which can be used to authenticate."
|
||||
@ -1032,6 +1052,7 @@ msgstr "Digits"
|
||||
msgid "Disable"
|
||||
msgstr "Disable"
|
||||
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorDuo.ts
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorStatic.ts
|
||||
msgid "Disable Static Tokens"
|
||||
msgstr "Disable Static Tokens"
|
||||
@ -1070,6 +1091,22 @@ msgstr "Download Private key"
|
||||
msgid "Dummy stage used for testing. Shows a simple continue button and always passes."
|
||||
msgstr "Dummy stage used for testing. Shows a simple continue button and always passes."
|
||||
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorDuo.ts
|
||||
msgid "Duo"
|
||||
msgstr "Duo"
|
||||
|
||||
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
||||
msgid "Duo Authenticators"
|
||||
msgstr "Duo Authenticators"
|
||||
|
||||
#: src/flows/stages/authenticator_duo/AuthenticatorDuoStage.ts
|
||||
msgid "Duo activation"
|
||||
msgstr "Duo activation"
|
||||
|
||||
#: src/flows/stages/authenticator_validate/AuthenticatorValidateStage.ts
|
||||
msgid "Duo push-notifications"
|
||||
msgstr "Duo push-notifications"
|
||||
|
||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
|
||||
msgid "Each provider has a different issuer, based on the application slug."
|
||||
msgstr "Each provider has a different issuer, based on the application slug."
|
||||
@ -1159,6 +1196,7 @@ msgstr "Enable"
|
||||
msgid "Enable StartTLS"
|
||||
msgstr "Enable StartTLS"
|
||||
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorDuo.ts
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorStatic.ts
|
||||
msgid "Enable Static Tokens"
|
||||
msgstr "Enable Static Tokens"
|
||||
@ -1431,6 +1469,7 @@ msgstr "Flow used before authentication."
|
||||
msgid "Flow used by an authenticated user to configure their password. If empty, user will not be able to configure change their password."
|
||||
msgstr "Flow used by an authenticated user to configure their password. If empty, user will not be able to configure change their password."
|
||||
|
||||
#: src/pages/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
|
||||
#: src/pages/stages/authenticator_static/AuthenticatorStaticStageForm.ts
|
||||
#: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
|
||||
msgid "Flow used by an authenticated user to configure this Stage. If empty, user will not be able to configure this stage."
|
||||
@ -1803,10 +1842,12 @@ msgstr "Load servers"
|
||||
#: src/flows/FlowExecutor.ts
|
||||
#: src/flows/FlowExecutor.ts
|
||||
#: src/flows/access_denied/FlowAccessDenied.ts
|
||||
#: src/flows/stages/authenticator_duo/AuthenticatorDuoStage.ts
|
||||
#: src/flows/stages/authenticator_static/AuthenticatorStaticStage.ts
|
||||
#: src/flows/stages/authenticator_totp/AuthenticatorTOTPStage.ts
|
||||
#: src/flows/stages/authenticator_validate/AuthenticatorValidateStage.ts
|
||||
#: src/flows/stages/authenticator_validate/AuthenticatorValidateStageCode.ts
|
||||
#: src/flows/stages/authenticator_validate/AuthenticatorValidateStageDuo.ts
|
||||
#: src/flows/stages/autosubmit/AutosubmitStage.ts
|
||||
#: src/flows/stages/captcha/CaptchaStage.ts
|
||||
#: src/flows/stages/consent/ConsentStage.ts
|
||||
@ -1866,6 +1907,7 @@ msgstr "Loading"
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts
|
||||
#: src/pages/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
|
||||
#: src/pages/stages/authenticator_static/AuthenticatorStaticStageForm.ts
|
||||
#: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
|
||||
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
||||
@ -2041,6 +2083,7 @@ msgstr "My Applications"
|
||||
#: src/pages/sources/saml/SAMLSourceForm.ts
|
||||
#: src/pages/sources/saml/SAMLSourceViewPage.ts
|
||||
#: src/pages/stages/StageListPage.ts
|
||||
#: src/pages/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
|
||||
#: src/pages/stages/authenticator_static/AuthenticatorStaticStageForm.ts
|
||||
#: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
|
||||
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
||||
@ -2173,9 +2216,11 @@ msgstr "Not found"
|
||||
msgid "Not synced yet."
|
||||
msgstr "Not synced yet."
|
||||
|
||||
#: src/flows/stages/authenticator_duo/AuthenticatorDuoStage.ts
|
||||
#: src/flows/stages/authenticator_static/AuthenticatorStaticStage.ts
|
||||
#: src/flows/stages/authenticator_totp/AuthenticatorTOTPStage.ts
|
||||
#: src/flows/stages/authenticator_validate/AuthenticatorValidateStageCode.ts
|
||||
#: src/flows/stages/authenticator_validate/AuthenticatorValidateStageDuo.ts
|
||||
#: src/flows/stages/captcha/CaptchaStage.ts
|
||||
#: src/flows/stages/consent/ConsentStage.ts
|
||||
#: src/flows/stages/password/PasswordStage.ts
|
||||
@ -2617,6 +2662,10 @@ msgstr "RSA-SHA512"
|
||||
msgid "Re-evaluate policies"
|
||||
msgstr "Re-evaluate policies"
|
||||
|
||||
#: src/flows/stages/authenticator_validate/AuthenticatorValidateStage.ts
|
||||
msgid "Receive a push notification on your phone to prove your identity."
|
||||
msgstr "Receive a push notification on your phone to prove your identity."
|
||||
|
||||
#: src/pages/flows/FlowForm.ts
|
||||
msgid "Recovery"
|
||||
msgstr "Recovery"
|
||||
@ -2728,6 +2777,7 @@ msgid "Return home"
|
||||
msgstr "Return home"
|
||||
|
||||
#: src/flows/stages/authenticator_validate/AuthenticatorValidateStageCode.ts
|
||||
#: src/flows/stages/authenticator_validate/AuthenticatorValidateStageDuo.ts
|
||||
#: src/flows/stages/authenticator_validate/AuthenticatorValidateStageWebAuthn.ts
|
||||
msgid "Return to device picker"
|
||||
msgstr "Return to device picker"
|
||||
@ -3033,6 +3083,10 @@ msgstr "Stage used to configure a TOTP authenticator (i.e. Authy/Google Authenti
|
||||
msgid "Stage used to configure a WebAutnn authenticator (i.e. Yubikey, FaceID/Windows Hello)."
|
||||
msgstr "Stage used to configure a WebAutnn authenticator (i.e. Yubikey, FaceID/Windows Hello)."
|
||||
|
||||
#: src/pages/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
|
||||
msgid "Stage used to configure a duo-based authenticator. This stage should be used for configuration flows."
|
||||
msgstr "Stage used to configure a duo-based authenticator. This stage should be used for configuration flows."
|
||||
|
||||
#: src/pages/stages/authenticator_static/AuthenticatorStaticStageForm.ts
|
||||
msgid "Stage used to configure a static authenticator (i.e. static tokens). This stage should be used for configuration flows."
|
||||
msgstr "Stage used to configure a static authenticator (i.e. static tokens). This stage should be used for configuration flows."
|
||||
@ -3041,6 +3095,7 @@ msgstr "Stage used to configure a static authenticator (i.e. static tokens). Thi
|
||||
msgid "Stage used to validate any authenticator. This stage should be used during authentication or authorization flows."
|
||||
msgstr "Stage used to validate any authenticator. This stage should be used during authentication or authorization flows."
|
||||
|
||||
#: src/pages/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
|
||||
#: src/pages/stages/authenticator_static/AuthenticatorStaticStageForm.ts
|
||||
#: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
|
||||
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
||||
@ -3074,7 +3129,7 @@ msgstr "State"
|
||||
msgid "Static Tokens"
|
||||
msgstr "Static Tokens"
|
||||
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorTOTP.ts
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorStatic.ts
|
||||
msgid "Static tokens"
|
||||
msgstr "Static tokens"
|
||||
|
||||
@ -3090,11 +3145,13 @@ msgstr "Statically deny the flow. To use this stage effectively, disable *Evalua
|
||||
msgid "Status"
|
||||
msgstr "Status"
|
||||
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorDuo.ts
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorStatic.ts
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorTOTP.ts
|
||||
msgid "Status: Disabled"
|
||||
msgstr "Status: Disabled"
|
||||
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorDuo.ts
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorStatic.ts
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorTOTP.ts
|
||||
msgid "Status: Enabled"
|
||||
@ -3204,6 +3261,7 @@ msgstr "Successfully created service-connection."
|
||||
msgid "Successfully created source."
|
||||
msgstr "Successfully created source."
|
||||
|
||||
#: src/pages/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
|
||||
#: src/pages/stages/authenticator_static/AuthenticatorStaticStageForm.ts
|
||||
#: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
|
||||
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
||||
@ -3342,6 +3400,7 @@ msgstr "Successfully updated service-connection."
|
||||
msgid "Successfully updated source."
|
||||
msgstr "Successfully updated source."
|
||||
|
||||
#: src/pages/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
|
||||
#: src/pages/stages/authenticator_static/AuthenticatorStaticStageForm.ts
|
||||
#: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
|
||||
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
||||
@ -3533,7 +3592,7 @@ msgstr "Time in minutes the token sent is valid."
|
||||
msgid "Time offset when temporary users should be deleted. This only applies if your IDP uses the NameID Format 'transient', and the user doesn't log out manually. (Format: hours=1;minutes=2;seconds=3)."
|
||||
msgstr "Time offset when temporary users should be deleted. This only applies if your IDP uses the NameID Format 'transient', and the user doesn't log out manually. (Format: hours=1;minutes=2;seconds=3)."
|
||||
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorStatic.ts
|
||||
#: src/pages/user-settings/settings/UserSettingsAuthenticatorTOTP.ts
|
||||
msgid "Time-based One-Time Passwords"
|
||||
msgstr "Time-based One-Time Passwords"
|
||||
|
||||
@ -3893,7 +3952,6 @@ msgstr "User details"
|
||||
msgid "User events"
|
||||
msgstr "User events"
|
||||
|
||||
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
||||
#: src/pages/stages/identification/IdentificationStageForm.ts
|
||||
msgid "User fields"
|
||||
msgstr "User fields"
|
||||
|
||||
@ -63,6 +63,10 @@ msgstr ""
|
||||
msgid "ANY, any policy must match to include this stage access."
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
msgid "API Hostname"
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
msgid "API Requests"
|
||||
msgstr ""
|
||||
@ -180,6 +184,10 @@ msgstr ""
|
||||
msgid "Also known as Entity ID. Defaults the Metadata URL."
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
msgid "Alternatively, if your current device has Duo installed, click on this link:"
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
msgid "Always require consent"
|
||||
msgstr ""
|
||||
@ -518,6 +526,10 @@ msgstr ""
|
||||
msgid "Check Username"
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
msgid "Check status"
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
msgid "Check your Emails for a password reset link."
|
||||
msgstr ""
|
||||
@ -566,6 +578,7 @@ msgstr ""
|
||||
#:
|
||||
#:
|
||||
#:
|
||||
#:
|
||||
msgid "Client ID"
|
||||
msgstr ""
|
||||
|
||||
@ -576,6 +589,7 @@ msgstr ""
|
||||
msgid "Client IP"
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
#:
|
||||
msgid "Client Secret"
|
||||
msgstr ""
|
||||
@ -614,6 +628,7 @@ msgstr ""
|
||||
#:
|
||||
#:
|
||||
#:
|
||||
#:
|
||||
msgid "Configuration flow"
|
||||
msgstr ""
|
||||
|
||||
@ -715,6 +730,7 @@ msgstr ""
|
||||
#:
|
||||
#:
|
||||
#:
|
||||
#:
|
||||
msgid "Continue"
|
||||
msgstr ""
|
||||
|
||||
@ -1002,6 +1018,10 @@ msgstr ""
|
||||
msgid "Determines how long a session lasts. Default of 0 seconds means that the sessions lasts until the browser is closed."
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
msgid "Device classes"
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
msgid "Device classes which can be used to authenticate."
|
||||
msgstr ""
|
||||
@ -1024,6 +1044,7 @@ msgstr ""
|
||||
msgid "Disable"
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
#:
|
||||
msgid "Disable Static Tokens"
|
||||
msgstr ""
|
||||
@ -1062,6 +1083,22 @@ msgstr ""
|
||||
msgid "Dummy stage used for testing. Shows a simple continue button and always passes."
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
msgid "Duo"
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
msgid "Duo Authenticators"
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
msgid "Duo activation"
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
msgid "Duo push-notifications"
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
msgid "Each provider has a different issuer, based on the application slug."
|
||||
msgstr ""
|
||||
@ -1151,6 +1188,7 @@ msgstr ""
|
||||
msgid "Enable StartTLS"
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
#:
|
||||
msgid "Enable Static Tokens"
|
||||
msgstr ""
|
||||
@ -1423,6 +1461,7 @@ msgstr ""
|
||||
msgid "Flow used by an authenticated user to configure their password. If empty, user will not be able to configure change their password."
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
#:
|
||||
#:
|
||||
msgid "Flow used by an authenticated user to configure this Stage. If empty, user will not be able to configure this stage."
|
||||
@ -1811,6 +1850,8 @@ msgstr ""
|
||||
#:
|
||||
#:
|
||||
#:
|
||||
#:
|
||||
#:
|
||||
msgid "Loading"
|
||||
msgstr ""
|
||||
|
||||
@ -1867,6 +1908,7 @@ msgstr ""
|
||||
#:
|
||||
#:
|
||||
#:
|
||||
#:
|
||||
msgid "Loading..."
|
||||
msgstr ""
|
||||
|
||||
@ -2054,6 +2096,7 @@ msgstr ""
|
||||
#:
|
||||
#:
|
||||
#:
|
||||
#:
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
|
||||
@ -2171,6 +2214,8 @@ msgstr ""
|
||||
#:
|
||||
#:
|
||||
#:
|
||||
#:
|
||||
#:
|
||||
msgid "Not you?"
|
||||
msgstr ""
|
||||
|
||||
@ -2609,6 +2654,10 @@ msgstr ""
|
||||
msgid "Re-evaluate policies"
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
msgid "Receive a push notification on your phone to prove your identity."
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
msgid "Recovery"
|
||||
msgstr ""
|
||||
@ -2719,6 +2768,7 @@ msgstr ""
|
||||
msgid "Return home"
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
#:
|
||||
#:
|
||||
msgid "Return to device picker"
|
||||
@ -3025,6 +3075,10 @@ msgstr ""
|
||||
msgid "Stage used to configure a WebAutnn authenticator (i.e. Yubikey, FaceID/Windows Hello)."
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
msgid "Stage used to configure a duo-based authenticator. This stage should be used for configuration flows."
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
msgid "Stage used to configure a static authenticator (i.e. static tokens). This stage should be used for configuration flows."
|
||||
msgstr ""
|
||||
@ -3044,6 +3098,7 @@ msgstr ""
|
||||
#:
|
||||
#:
|
||||
#:
|
||||
#:
|
||||
msgid "Stage-specific settings"
|
||||
msgstr ""
|
||||
|
||||
@ -3082,11 +3137,13 @@ msgstr ""
|
||||
msgid "Status"
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
#:
|
||||
#:
|
||||
msgid "Status: Disabled"
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
#:
|
||||
#:
|
||||
msgid "Status: Enabled"
|
||||
@ -3213,6 +3270,7 @@ msgstr ""
|
||||
#:
|
||||
#:
|
||||
#:
|
||||
#:
|
||||
msgid "Successfully created stage."
|
||||
msgstr ""
|
||||
|
||||
@ -3351,6 +3409,7 @@ msgstr ""
|
||||
#:
|
||||
#:
|
||||
#:
|
||||
#:
|
||||
msgid "Successfully updated stage."
|
||||
msgstr ""
|
||||
|
||||
@ -3881,7 +3940,6 @@ msgstr ""
|
||||
msgid "User events"
|
||||
msgstr ""
|
||||
|
||||
#:
|
||||
#:
|
||||
msgid "User fields"
|
||||
msgstr ""
|
||||
|
||||
Reference in New Issue
Block a user