SSO & Duo 2FA
Browser-based SSO and Duo 2FA with OpenConnect
Modern corporate gateways increasingly force a browser-based SAML/SSO login — an Okta, Azure AD, or Ping Identity page, often wrapping an embedded Duo iframe — instead of accepting a username and password on the command line. VPN Up handles both classic Duo 2FA and the browser-based “SSO trap.”
Duo 2FA (push, phone, SMS, passcode)
Set the Duo method on a profile and VPN Up handles the prompt order so Duo and AuthGroup selection don’t collide:
push— approve on your phone (Duo Mobile)phone— callback to your registered phonesms— texted passcodespasscode— one-time code, prompted at connect time (never read from config)- empty — let the gateway auto-push
vpn-up start "Work VPN" # connect; approve the Duo push when prompted
TOTP authenticator-app codes (Google Authenticator, Authy, hardware tokens)
If your gateway prompts for a time-based one-time code, store the base32 seed once and VPN Up generates the current code at connect time:
vpn-up set-secret "Work VPN" token_secret # paste the base32 seed
Set <tokenMode>totp</tokenMode> on the profile (the add-profile wizard offers
it as a 2FA choice). Requires oathtool (brew install oath-toolkit /
apt install oathtool; reported by vpn-up doctor).
- The seed stays in your keychain — it’s never passed to OpenConnect’s command line or written to disk. Only the short-lived 6-digit code is sent, on stdin.
- TOTP needs no interaction, so it’s the one 2FA method that can run as a login service with auto-reconnect — ideal for headless servers. (Duo passcode and SSO can’t, since they need a human.)
- Security note: keeping the seed beside the password in one keychain is effectively “1.5-factor” — it’s opt-in.
Browser-based SSO (Okta, Azure AD, Ping Identity)
For gateways that require an external browser login, mark the profile with
authMode=sso — either answer yes to the SSO prompt in vpn-up add-profile,
or set it in the profile XML:
<VPN>
<name>Work SSO</name>
<protocol>anyconnect</protocol> <!-- anyconnect or gp; not nc -->
<host>vpn.example.com</host>
<authMode>sso</authMode>
</VPN>
Then connect normally:
vpn-up start "Work SSO"
VPN Up runs OpenConnect with --external-browser: it opens your browser to the
identity provider, you complete the login (including Duo) there, and the tunnel
comes up afterward. No password is stored or piped for SSO profiles.
Passkeys & FIDO2 / YubiKey (WebAuthn) work automatically. Because the SSO login happens in your real browser, any authenticator the identity provider accepts — a passkey, a FIDO2 security key, or a YubiKey as a WebAuthn device — just works, with no extra configuration in VPN Up. (Delegating to the real browser, rather than an embedded one, is what makes hardware WebAuthn reliable.) For a YubiKey holding a client certificate (PIV) instead, see client-certificate authentication.
Requirements and behavior
- OpenConnect ≥ 9.0 (when
--external-browserlanded).vpn-up doctorreports your version and whether SSO is available. - Supported for the
anyconnectandgpprotocols (notnc). - Runs in the foreground; an SSO profile cannot run as a login service because it needs an interactive desktop session.
Linux + sudo: getting the browser to open
OpenConnect runs as root via sudo, so a root-spawned browser may not reach your
desktop session on Linux. If the browser doesn’t appear, point VPN Up at a
session-aware opener:
# ~/bin/vpn-up-browser (chmod +x)
#!/bin/sh
exec sudo -u "$SUDO_USER" xdg-open "$@"
export VPN_UP_EXTERNAL_BROWSER="$HOME/bin/vpn-up-browser"
VPN_UP_EXTERNAL_BROWSER overrides the opener (default: open on macOS,
xdg-open on Linux, or the bundled openconnect-external-browser helper).
See also: usage and supported protocols.