Papa Labs

FortiGate SSL-VPN with DUO 2FA: two critical gotchas nobody puts on page one

Adding DUO two-factor to a FortiGate (100F) SSL-VPN, the standard architecture:

FortiClient → FortiGate ──RADIUS──> DUO Authentication Proxy (on the AD server)
                                        ├─ factor 1: forwards to AD (LDAP) for the password
                                        └─ factor 2: DUO push to the user's phone

The SSL-VPN + DUO authentication chain with both gotchas marked

The full chain and where both traps live — both on the FortiGate side

The official docs cover installation well. Two traps, however, you only learn by stepping on them.

Gotcha 1: the 5-second default timeout kills every push

FortiGate’s remote auth timeout defaults to 5 seconds. The DUO push flow is: user starts the VPN connection → phone buzzes → user picks it up and taps Approve — five seconds doesn’t cover it. Result: the password validates fine, but before the user can tap, FortiGate has already declared failure.

The symptom is maximally confusing: wrong password fails instantly (normal), while the correct password “hangs a moment, then fails.”

The fix is CLI-only (no GUI option):

config system global
    set remoteauthtimeout 60
end

DUO recommends at least 60 seconds; we settled on 120 for users whose phone isn’t at hand.

Gotcha 2: LDAP left in the user group = 2FA theater

After configuring the RADIUS server, you point the SSL-VPN user group at it. The fatal detail:

Replace the group’s LDAP server member with the RADIUS server — do not simply add alongside.

With both LDAP and RADIUS in the group, an auth request that matches LDAP sails straight through — right password, you’re in, the DUO hop never happens. The console says 2FA is “configured”; in reality it doesn’t exist. After installing, test it properly: log in with the right password and the phone must buzz. If you get in without a push, you have this problem.

Verification checklist

  • Correct password + approve push → logged in;
  • Correct password + deny push → login fails (proves 2FA is actually in the chain);
  • Wrong password → instant failure (should trigger no push);
  • Time a real login end-to-end — connection to push-approval — and confirm it fits inside the timeout.

Lessons

  1. Any auth chain that involves “a human touching a phone” makes every timeout a suspect. Five seconds is an eternity for machines and barely a beginning for someone fishing out their phone;
  2. Hardening changes (2FA, ACLs) demand negative testing — “does denying the push block the login” matters far more than “does approving let me in”;
  3. Plenty of critical FortiGate parameters are CLI-only (remoteauthtimeout included) — before concluding a setting doesn’t exist, search the CLI reference.
← All posts