stages/authenticator_validate: add Duo support
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
@ -11,12 +11,14 @@ import AKGlobal from "../../../authentik.css";
|
||||
import { BaseStage, StageHost } from "../base";
|
||||
import "./AuthenticatorValidateStageWebAuthn";
|
||||
import "./AuthenticatorValidateStageCode";
|
||||
import "./AuthenticatorValidateStageDuo";
|
||||
import { PasswordManagerPrefill } from "../identification/IdentificationStage";
|
||||
|
||||
export enum DeviceClasses {
|
||||
STATIC = "static",
|
||||
TOTP = "totp",
|
||||
WEBAUTHN = "webauthn",
|
||||
DUO = "duo",
|
||||
}
|
||||
|
||||
export interface DeviceChallenge {
|
||||
@ -30,8 +32,9 @@ export interface AuthenticatorValidateStageChallenge extends WithUserInfoChallen
|
||||
}
|
||||
|
||||
export interface AuthenticatorValidateStageChallengeResponse {
|
||||
code: string;
|
||||
webauthn: string;
|
||||
code?: string;
|
||||
webauthn?: string;
|
||||
duo?: number;
|
||||
}
|
||||
|
||||
@customElement("ak-stage-authenticator-validate")
|
||||
@ -77,6 +80,12 @@ export class AuthenticatorValidateStage extends BaseStage implements StageHost {
|
||||
|
||||
renderDevicePickerSingle(deviceChallenge: DeviceChallenge): TemplateResult {
|
||||
switch (deviceChallenge.device_class) {
|
||||
case DeviceClasses.DUO:
|
||||
return html`<i class="fas fa-mobile-alt"></i>
|
||||
<div class="right">
|
||||
<p>${t`Duo push-notifications`}</p>
|
||||
<small>${t`Receive a push notification on your phone to prove your identity.`}</small>
|
||||
</div>`;
|
||||
case DeviceClasses.WEBAUTHN:
|
||||
return html`<i class="fas fa-mobile-alt"></i>
|
||||
<div class="right">
|
||||
@ -147,6 +156,13 @@ export class AuthenticatorValidateStage extends BaseStage implements StageHost {
|
||||
.deviceChallenge=${this.selectedDeviceChallenge}
|
||||
.showBackButton=${(this.challenge?.device_challenges.length || []) > 1}>
|
||||
</ak-stage-authenticator-validate-webauthn>`;
|
||||
case DeviceClasses.DUO:
|
||||
return html`<ak-stage-authenticator-validate-duo
|
||||
.host=${this}
|
||||
.challenge=${this.challenge}
|
||||
.deviceChallenge=${this.selectedDeviceChallenge}
|
||||
.showBackButton=${(this.challenge?.device_challenges.length || []) > 1}>
|
||||
</ak-stage-authenticator-validate-duo>`;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,81 @@
|
||||
import { t } from "@lingui/macro";
|
||||
import { CSSResult, customElement, html, property, TemplateResult } from "lit-element";
|
||||
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";
|
||||
import PFTitle from "@patternfly/patternfly/components/Title/title.css";
|
||||
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 "../../../elements/forms/FormElement";
|
||||
import "../../../elements/EmptyState";
|
||||
import { PasswordManagerPrefill } from "../identification/IdentificationStage";
|
||||
import "../../FormStatic";
|
||||
import { FlowURLManager } from "../../../api/legacy";
|
||||
|
||||
@customElement("ak-stage-authenticator-validate-duo")
|
||||
export class AuthenticatorValidateStageWebDuo extends BaseStage {
|
||||
|
||||
@property({ attribute: false })
|
||||
challenge?: AuthenticatorValidateStageChallenge;
|
||||
|
||||
@property({ attribute: false })
|
||||
deviceChallenge?: DeviceChallenge;
|
||||
|
||||
@property({ type: Boolean })
|
||||
showBackButton = false;
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return [PFBase, PFLogin, PFForm, PFFormControl, PFTitle, PFButton, AKGlobal];
|
||||
}
|
||||
|
||||
firstUpdated(): void {
|
||||
this.host?.submit({
|
||||
"duo": this.deviceChallenge?.device_uid
|
||||
});
|
||||
}
|
||||
|
||||
render(): TemplateResult {
|
||||
if (!this.challenge) {
|
||||
return html`<ak-empty-state
|
||||
?loading="${true}"
|
||||
header=${t`Loading`}>
|
||||
</ak-empty-state>`;
|
||||
}
|
||||
return html`<div class="pf-c-login__main-body">
|
||||
<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}>
|
||||
<div slot="link">
|
||||
<a href="${FlowURLManager.cancel()}">${t`Not you?`}</a>
|
||||
</div>
|
||||
</ak-form-static>
|
||||
|
||||
<div class="pf-c-form__group pf-m-action">
|
||||
<button type="submit" class="pf-c-button pf-m-primary pf-m-block">
|
||||
${t`Continue`}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<footer class="pf-c-login__main-footer">
|
||||
<ul class="pf-c-login__main-footer-links">
|
||||
${this.showBackButton ?
|
||||
html`<li class="pf-c-login__main-footer-links-item">
|
||||
<button class="pf-c-button pf-m-secondary pf-m-block" @click=${() => {
|
||||
if (!this.host) return;
|
||||
(this.host as AuthenticatorValidateStage).selectedDeviceChallenge = undefined;
|
||||
}}>
|
||||
${t`Return to device picker`}
|
||||
</button>
|
||||
</li>`:
|
||||
html``}
|
||||
</ul>
|
||||
</footer>`;
|
||||
}
|
||||
|
||||
}
|
||||
@ -74,7 +74,7 @@ export class FlowViewPage extends LitElement {
|
||||
new FlowsApi(DEFAULT_CONFIG).flowsInstancesExecuteRetrieve({
|
||||
slug: this.flow.slug
|
||||
}).then(link => {
|
||||
const finalURL = `${link.link}?next=/%23${window.location.href}`;
|
||||
const finalURL = `${link.link}?next=/%23${window.location.hash}`;
|
||||
window.open(finalURL, "_blank");
|
||||
});
|
||||
}}>
|
||||
|
||||
@ -91,9 +91,9 @@ export class AuthenticatorValidateStageForm extends ModelForm<AuthenticatorValid
|
||||
</select>
|
||||
</ak-form-element-horizontal>
|
||||
<ak-form-element-horizontal
|
||||
label=${t`User fields`}
|
||||
label=${t`Device classes`}
|
||||
?required=${true}
|
||||
name="transports">
|
||||
name="deviceClasses">
|
||||
<select name="users" class="pf-c-form-control" multiple>
|
||||
<option value=${DeviceClassesEnum.Static} ?selected=${this.isDeviceClassSelected(DeviceClassesEnum.Static)}>
|
||||
${t`Static Tokens`}
|
||||
@ -104,6 +104,9 @@ export class AuthenticatorValidateStageForm extends ModelForm<AuthenticatorValid
|
||||
<option value=${DeviceClassesEnum.Webauthn} ?selected=${this.isDeviceClassSelected(DeviceClassesEnum.Webauthn)}>
|
||||
${t`WebAuthn Authenticators`}
|
||||
</option>
|
||||
<option value=${DeviceClassesEnum.Duo} ?selected=${this.isDeviceClassSelected(DeviceClassesEnum.Duo)}>
|
||||
${t`Duo Authenticators`}
|
||||
</option>
|
||||
</select>
|
||||
<p class="pf-c-form__helper-text">${t`Device classes which can be used to authenticate.`}</p>
|
||||
<p class="pf-c-form__helper-text">${t`Hold control/command to select multiple items.`}</p>
|
||||
|
||||
Reference in New Issue
Block a user