Skip to content

web/flows/sfe: add Duo push support to simplified flow executor - #26272

Open
rubyfoster5841 wants to merge 5 commits into
goauthentik:mainfrom
rubyfoster5841:SFECiscoDuoAuth
Open

rubyfoster5841 wants to merge 5 commits into
goauthentik:mainfrom
rubyfoster5841:SFECiscoDuoAuth

Conversation

@rubyfoster5841

Copy link
Copy Markdown

What does this PR change?

Adds Duo push support to the simplified flow executor (SFE).

web/packages/sfe/src/index.ts

  • The SFE's AuthenticatorValidateStage already renders the
    authenticator-validate stage for the static, totp and webauthn
    device classes. However it had no case for duo, so the render() switch
    fell through to default: break; and rendered nothing.
  • Adds a case "duo" to that switch, calling a new renderDuo().
  • Adds a "Duo push" label to the device-class picker, shown when a
    user has more than one compatible device.
  • renderDuo() shows a "Sending Duo push notification..." message with
    a spinner and submits { duo: deviceChallenge.deviceUid } — the same
    payload the default flow executor's AuthenticatorValidateStageDuo
    submits.

Why is this change needed?

Because the SFE had no duo case, any user whose only configured (or
only remaining) authenticator-validate device is Duo got stuck
indefinitely on a blank SFE stage after the password stage, SFE would render
nothing and never progressed, with no error shown.

This was found via a Windows WAM/WebView2-embedded sign-in (SAML
passive auth through Microsoft.AAD.BrokerPlugin.exe), whose user agent
(Edge/18.26200, parsed as family=Edge, major=18) causes authentik to
serve the SFE per compat_needs_sfe(). Any Duo-only user hitting that
path had no way to complete MFA.

How was this tested?

Manually, against a default-authentication-flow with an
authenticator-validate stage configured for the duo device class,
for a user with an enrolled Duo device.

This was tested on both Docker Compose, as well as Kubernetes on
both 2026.8.2 and 2026.8.3 via a manual patch

  • Before: after the password stage, the SFE rendered nothing and
    never progressed. The executor's next challenge was
    ak-stage-authenticator-validate with a duo device class, but
    render() had no matching case.

  • After: the SFE shows "Sending Duo push notification...", the push
    is sent to the enrolled device, and on approval the flow completes
    normally.

Known bugs: on a denied push, the backend
re-returns the same authenticator-validate challenge, and since Duo can be
the only selected device, renderDuo() will auto-resubmit it

This will effectively resend the push instead of surfacing the denial. This
seems to be an existing quirk in the default flow executor (#11368)

AI Use

This patch was created with the help of Claude, specifically models Opus 4.8 and
Sonnet 5 using Claude Code.

Checklist

  • The project has been linted, built, and tested (make all)
  • The documentation has been updated and formatted (make docs)
    (Not required as far as i can see(
  • I have read the AI usage policy.

@rubyfoster5841
rubyfoster5841 requested a review from a team as a code owner September 18, 2026 22:09
@netlify

netlify Bot commented Sep 18, 2026

Copy link
Copy Markdown

✅ Deploy Preview for authentik-docs ready!

Name Link
🔨 Latest commit 60776e9
🔍 Latest deploy log https://app.netlify.com/projects/authentik-docs/deploys/6aadb6a0beafe00008b2318d
😎 Deploy Preview https://deploy-preview-26272--authentik-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@BeryJu BeryJu changed the title web/sfe: add Duo push support to simplified flow executor web/flows/sfe: add Duo push support to simplified flow executor Sep 19, 2026
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
@codecov

codecov Bot commented Sep 19, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.97%. Comparing base (bafc5e1) to head (846665b).

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #26272      +/-   ##
==========================================
- Coverage   92.00%   91.97%   -0.04%     
==========================================
  Files        1175     1175              
  Lines       76288    76288              
  Branches     4056     4056              
==========================================
- Hits        70192    70166      -26     
- Misses       6054     6080      +26     
  Partials       42       42              
Flag Coverage Δ
conformance 33.49% <ø> (ø)
e2e 38.26% <ø> (+<0.01%) ⬆️
integration 29.78% <ø> (-0.45%) ⬇️
rust 42.89% <ø> (ø)
unit 93.56% <ø> (+<0.01%) ⬆️
unit-migrate 93.57% <ø> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
</form>
`);

this.executor.submit({

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we add a small SFE regression test around the Duo path?

renderDuo() submits immediately from render(), so it would be good to lock down that a single Duo challenge sends exactly one { duo: deviceUid } request, and that selecting Duo from the picker uses the selected device UID. That would also catch accidental duplicate push submissions if this stage is re-rendered later.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants