web/flows: fix error when using consecutive webauthn validator stages (#9629)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
@ -5,7 +5,7 @@ import "@goauthentik/flow/FormStatic";
|
||||
import { BaseStage } from "@goauthentik/flow/stages/base";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
import { CSSResult, TemplateResult, html } from "lit";
|
||||
import { CSSResult, PropertyValues, TemplateResult, html } from "lit";
|
||||
import { customElement } from "lit/decorators.js";
|
||||
import { ifDefined } from "lit/directives/if-defined.js";
|
||||
|
||||
@ -32,14 +32,16 @@ export class AuthenticatorDuoStage extends BaseStage<
|
||||
return [PFBase, PFLogin, PFForm, PFFormControl, PFTitle, PFButton];
|
||||
}
|
||||
|
||||
firstUpdated(): void {
|
||||
const i = setInterval(() => {
|
||||
this.checkEnrollStatus().then((shouldStop) => {
|
||||
if (shouldStop) {
|
||||
clearInterval(i);
|
||||
}
|
||||
});
|
||||
}, 3000);
|
||||
updated(changedProperties: PropertyValues<this>) {
|
||||
if (changedProperties.has("challenge") && this.challenge !== undefined) {
|
||||
const i = setInterval(() => {
|
||||
this.checkEnrollStatus().then((shouldStop) => {
|
||||
if (shouldStop) {
|
||||
clearInterval(i);
|
||||
}
|
||||
});
|
||||
}, 3000);
|
||||
}
|
||||
}
|
||||
|
||||
async checkEnrollStatus(): Promise<boolean> {
|
||||
|
@ -3,7 +3,7 @@ import "@goauthentik/elements/forms/FormElement";
|
||||
import { BaseDeviceStage } from "@goauthentik/flow/stages/authenticator_validate/base";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
import { TemplateResult, html } from "lit";
|
||||
import { PropertyValues, TemplateResult, html } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators.js";
|
||||
|
||||
import {
|
||||
@ -26,21 +26,23 @@ export class AuthenticatorValidateStageWebDuo extends BaseDeviceStage<
|
||||
@state()
|
||||
authenticating = false;
|
||||
|
||||
firstUpdated(): void {
|
||||
this.authenticating = true;
|
||||
this.host
|
||||
?.submit(
|
||||
{
|
||||
duo: this.deviceChallenge?.deviceUid,
|
||||
},
|
||||
{ invisible: true },
|
||||
)
|
||||
.then(() => {
|
||||
this.authenticating = false;
|
||||
})
|
||||
.catch(() => {
|
||||
this.authenticating = false;
|
||||
});
|
||||
updated(changedProperties: PropertyValues<this>) {
|
||||
if (changedProperties.has("challenge") && this.challenge !== undefined) {
|
||||
this.authenticating = true;
|
||||
this.host
|
||||
?.submit(
|
||||
{
|
||||
duo: this.deviceChallenge?.deviceUid,
|
||||
},
|
||||
{ invisible: true },
|
||||
)
|
||||
.then(() => {
|
||||
this.authenticating = false;
|
||||
})
|
||||
.catch(() => {
|
||||
this.authenticating = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
render(): TemplateResult {
|
||||
|
@ -7,7 +7,7 @@ import "@goauthentik/elements/EmptyState";
|
||||
import { BaseDeviceStage } from "@goauthentik/flow/stages/authenticator_validate/base";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
import { TemplateResult, html, nothing } from "lit";
|
||||
import { PropertyValues, TemplateResult, html, nothing } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators.js";
|
||||
|
||||
import {
|
||||
@ -72,14 +72,16 @@ export class AuthenticatorValidateStageWebAuthn extends BaseDeviceStage<
|
||||
}
|
||||
}
|
||||
|
||||
firstUpdated(): void {
|
||||
// convert certain members of the PublicKeyCredentialRequestOptions into
|
||||
// byte arrays as expected by the spec.
|
||||
const credentialRequestOptions = this.deviceChallenge
|
||||
?.challenge as PublicKeyCredentialRequestOptions;
|
||||
this.transformedCredentialRequestOptions =
|
||||
transformCredentialRequestOptions(credentialRequestOptions);
|
||||
this.authenticateWrapper();
|
||||
updated(changedProperties: PropertyValues<this>) {
|
||||
if (changedProperties.has("challenge") && this.challenge !== undefined) {
|
||||
// convert certain members of the PublicKeyCredentialRequestOptions into
|
||||
// byte arrays as expected by the spec.
|
||||
const credentialRequestOptions = this.deviceChallenge
|
||||
?.challenge as PublicKeyCredentialRequestOptions;
|
||||
this.transformedCredentialRequestOptions =
|
||||
transformCredentialRequestOptions(credentialRequestOptions);
|
||||
this.authenticateWrapper();
|
||||
}
|
||||
}
|
||||
|
||||
async authenticateWrapper(): Promise<void> {
|
||||
|
@ -6,7 +6,7 @@ import { BaseStage } from "@goauthentik/flow/stages/base";
|
||||
import type { TurnstileObject } from "turnstile-types";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
import { CSSResult, TemplateResult, html } from "lit";
|
||||
import { CSSResult, PropertyValues, TemplateResult, html } from "lit";
|
||||
import { customElement, state } from "lit/decorators.js";
|
||||
import { ifDefined } from "lit/directives/if-defined.js";
|
||||
|
||||
@ -42,46 +42,55 @@ export class CaptchaStage extends BaseStage<CaptchaChallenge, CaptchaChallengeRe
|
||||
@state()
|
||||
captchaContainer: HTMLDivElement;
|
||||
|
||||
@state()
|
||||
scriptElement?: HTMLScriptElement;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.captchaContainer = document.createElement("div");
|
||||
this.captchaContainer.id = captchaContainerID;
|
||||
}
|
||||
|
||||
firstUpdated(): void {
|
||||
const script = document.createElement("script");
|
||||
script.src = this.challenge.jsUrl;
|
||||
script.async = true;
|
||||
script.defer = true;
|
||||
script.onload = () => {
|
||||
console.debug("authentik/stages/captcha: script loaded");
|
||||
let found = false;
|
||||
let lastError = undefined;
|
||||
this.handlers.forEach((handler) => {
|
||||
let handlerFound = false;
|
||||
try {
|
||||
console.debug(`authentik/stages/captcha[${handler.name}]: trying handler`);
|
||||
handlerFound = handler.apply(this);
|
||||
if (handlerFound) {
|
||||
updated(changedProperties: PropertyValues<this>) {
|
||||
if (changedProperties.has("challenge") && this.challenge !== undefined) {
|
||||
this.scriptElement = document.createElement("script");
|
||||
this.scriptElement.src = this.challenge.jsUrl;
|
||||
this.scriptElement.async = true;
|
||||
this.scriptElement.defer = true;
|
||||
this.scriptElement.dataset.akCaptchaScript = "true";
|
||||
this.scriptElement.onload = () => {
|
||||
console.debug("authentik/stages/captcha: script loaded");
|
||||
let found = false;
|
||||
let lastError = undefined;
|
||||
this.handlers.forEach((handler) => {
|
||||
let handlerFound = false;
|
||||
try {
|
||||
console.debug(`authentik/stages/captcha[${handler.name}]: trying handler`);
|
||||
handlerFound = handler.apply(this);
|
||||
if (handlerFound) {
|
||||
console.debug(
|
||||
`authentik/stages/captcha[${handler.name}]: handler succeeded`,
|
||||
);
|
||||
found = true;
|
||||
}
|
||||
} catch (exc) {
|
||||
console.debug(
|
||||
`authentik/stages/captcha[${handler.name}]: handler succeeded`,
|
||||
`authentik/stages/captcha[${handler.name}]: handler failed: ${exc}`,
|
||||
);
|
||||
found = true;
|
||||
}
|
||||
} catch (exc) {
|
||||
console.debug(
|
||||
`authentik/stages/captcha[${handler.name}]: handler failed: ${exc}`,
|
||||
);
|
||||
if (handlerFound) {
|
||||
lastError = exc;
|
||||
if (handlerFound) {
|
||||
lastError = exc;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (!found && lastError) {
|
||||
this.error = (lastError as Error).toString();
|
||||
}
|
||||
});
|
||||
if (!found && lastError) {
|
||||
this.error = (lastError as Error).toString();
|
||||
}
|
||||
};
|
||||
document.head.appendChild(script);
|
||||
};
|
||||
document.head
|
||||
.querySelectorAll("[data-ak-captcha-script=true]")
|
||||
.forEach((el) => el.remove());
|
||||
document.head.appendChild(this.scriptElement);
|
||||
}
|
||||
}
|
||||
|
||||
handleGReCaptcha(): boolean {
|
||||
|
@ -5,7 +5,7 @@ import "@goauthentik/elements/forms/FormElement";
|
||||
import { BaseStage } from "@goauthentik/flow/stages/base";
|
||||
|
||||
import { msg, str } from "@lit/localize";
|
||||
import { CSSResult, TemplateResult, css, html, nothing } from "lit";
|
||||
import { CSSResult, PropertyValues, TemplateResult, css, html, nothing } from "lit";
|
||||
import { customElement } from "lit/decorators.js";
|
||||
|
||||
import PFAlert from "@patternfly/patternfly/components/Alert/alert.css";
|
||||
@ -63,9 +63,11 @@ export class IdentificationStage extends BaseStage<
|
||||
`);
|
||||
}
|
||||
|
||||
firstUpdated(): void {
|
||||
this.autoRedirect();
|
||||
this.createHelperForm();
|
||||
updated(changedProperties: PropertyValues<this>) {
|
||||
if (changedProperties.has("challenge") && this.challenge !== undefined) {
|
||||
this.autoRedirect();
|
||||
this.createHelperForm();
|
||||
}
|
||||
}
|
||||
|
||||
autoRedirect(): void {
|
||||
|
Reference in New Issue
Block a user