web/flows/sfe: add Duo push support to simplified flow executor - #26272
rubyfoster5841 wants to merge 5 commits into
Conversation
✅ Deploy Preview for authentik-docs ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Codecov Report✅ All modified and coverable lines are covered by tests. 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
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. |
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
| </form> | ||
| `); | ||
|
|
||
| this.executor.submit({ |
There was a problem hiding this comment.
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.
What does this PR change?
Adds Duo push support to the simplified flow executor (SFE).
web/packages/sfe/src/index.tsAuthenticatorValidateStagealready renders theauthenticator-validatestage for thestatic,totpandwebauthndevice classes. However it had no
caseforduo, so therender()switchfell through to
default: break;and rendered nothing.case "duo"to that switch, calling a newrenderDuo()."Duo push"label to the device-class picker, shown when auser has more than one compatible device.
renderDuo()shows a "Sending Duo push notification..." message witha spinner and submits
{ duo: deviceChallenge.deviceUid }— the samepayload the default flow executor's
AuthenticatorValidateStageDuosubmits.
Why is this change needed?
Because the SFE had no
duocase, any user whose only configured (oronly 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 asfamily=Edge, major=18) causes authentik toserve the SFE per
compat_needs_sfe(). Any Duo-only user hitting thatpath had no way to complete MFA.
How was this tested?
Manually, against a
default-authentication-flowwith anauthenticator-validatestage configured for theduodevice 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-validatewith aduodevice class, butrender()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-validatechallenge, and since Duo can bethe only selected device,
renderDuo()will auto-resubmit itThis 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
make all)make docs)(Not required as far as i can see(