web/flows: fix error when using consecutive webauthn validator stages (#9629)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
Jens L
2024-05-07 19:50:57 +02:00
committed by GitHub
parent a140bad8fb
commit 18b4b2d7b2
5 changed files with 86 additions and 69 deletions

View File

@ -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,7 +32,8 @@ export class AuthenticatorDuoStage extends BaseStage<
return [PFBase, PFLogin, PFForm, PFFormControl, PFTitle, PFButton];
}
firstUpdated(): void {
updated(changedProperties: PropertyValues<this>) {
if (changedProperties.has("challenge") && this.challenge !== undefined) {
const i = setInterval(() => {
this.checkEnrollStatus().then((shouldStop) => {
if (shouldStop) {
@ -41,6 +42,7 @@ export class AuthenticatorDuoStage extends BaseStage<
});
}, 3000);
}
}
async checkEnrollStatus(): Promise<boolean> {
const status = await new StagesApi(

View File

@ -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,7 +26,8 @@ export class AuthenticatorValidateStageWebDuo extends BaseDeviceStage<
@state()
authenticating = false;
firstUpdated(): void {
updated(changedProperties: PropertyValues<this>) {
if (changedProperties.has("challenge") && this.challenge !== undefined) {
this.authenticating = true;
this.host
?.submit(
@ -42,6 +43,7 @@ export class AuthenticatorValidateStageWebDuo extends BaseDeviceStage<
this.authenticating = false;
});
}
}
render(): TemplateResult {
if (!this.challenge) {

View File

@ -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,7 +72,8 @@ export class AuthenticatorValidateStageWebAuthn extends BaseDeviceStage<
}
}
firstUpdated(): void {
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
@ -81,6 +82,7 @@ export class AuthenticatorValidateStageWebAuthn extends BaseDeviceStage<
transformCredentialRequestOptions(credentialRequestOptions);
this.authenticateWrapper();
}
}
async authenticateWrapper(): Promise<void> {
if (this.authenticating) {

View File

@ -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,18 +42,23 @@ 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 = () => {
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;
@ -81,7 +86,11 @@ export class CaptchaStage extends BaseStage<CaptchaChallenge, CaptchaChallengeRe
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 {

View File

@ -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,10 +63,12 @@ export class IdentificationStage extends BaseStage<
`);
}
firstUpdated(): void {
updated(changedProperties: PropertyValues<this>) {
if (changedProperties.has("challenge") && this.challenge !== undefined) {
this.autoRedirect();
this.createHelperForm();
}
}
autoRedirect(): void {
if (!this.challenge) return;