Skip to main content

OpenConnect wrapper with Azure AD (SAML) SSO support for Cisco SSL-VPNs

Project description

openconnect-saml

OpenConnect wrapper supporting Azure AD / SAML authentication for Cisco AnyConnect SSL-VPNs.

Modernized fork based on vlaci/openconnect-sso with improvements from kowyo/openconnect-lite.

Features

  • SAML / Azure AD authentication via embedded Qt WebEngine browser or headless CLI mode
  • Headless mode: No display/GUI required — works on servers, containers, and SSH sessions
  • Automatic form-filling for username, password, and TOTP
  • Password stored in system keyring (with in-memory fallback)
  • TOTP secret configurable directly in config file
  • Profile auto-detection from AnyConnect XML profiles
  • Proxy support (SOCKS/HTTP)
  • Client certificate handling (auto-fallback on cert-request)
  • --no-sudo mode for use with --script-tun
  • --csd-wrapper passthrough for CSD/hostscan support
  • --reset-credentials to clear saved keyring entries
  • Microsoft Authenticator number matching support
  • Office365 "Stay signed in?" auto-dismiss
  • Robust XML parsing (recovers from malformed responses)

Requirements

  • Python ≥ 3.10
  • OpenConnect installed and in PATH
  • Qt6 WebEngine (provided by PyQt6) — only for GUI mode

Installation

# Headless mode (no GUI dependencies):
pip install openconnect-saml

# With GUI browser support:
pip install openconnect-saml[gui]

# Or via uv:
uv tool install openconnect-saml       # headless
uv tool install openconnect-saml[gui]   # with browser

Usage

GUI Mode (default)

# Connect to a VPN server
openconnect-saml --server vpn.example.com

# With a specific user group
openconnect-saml --server vpn.example.com/usergroup

# Use AnyConnect profile
openconnect-saml --profile /opt/cisco/anyconnect/profile

Headless Mode (no display required)

Perfect for servers, containers, CI/CD, and SSH sessions:

# Automatic authentication (username/password/TOTP from keyring)
openconnect-saml --server vpn.example.com --headless --user user@example.com

# Authentication only — output cookie for scripting
openconnect-saml --server vpn.example.com --headless --user user@example.com --authenticate json

How headless mode works:

  1. Automatic: Uses HTTP requests + form parsing to submit credentials (username, password, TOTP) without a browser. Works with standard Azure AD / Microsoft Online flows.
  2. Callback fallback: If automatic auth fails (e.g., CAPTCHA, unsupported MFA), starts a local HTTP server and prints a URL. Open the URL in any browser (even on another machine), authenticate, and the callback captures the token.

Docker Example

FROM python:3.12-slim

RUN pip install openconnect-saml
RUN apt-get update && apt-get install -y openconnect && rm -rf /var/lib/apt/lists/*

# Run headless — no GUI needed
ENTRYPOINT ["openconnect-saml", "--headless"]
docker run -it --cap-add=NET_ADMIN --device=/dev/net/tun \
  vpn-client --server vpn.example.com --user user@example.com

Server Deployment

On a headless server (no X11/Wayland):

# Install without GUI deps
pip install openconnect-saml

# First run — will prompt for password & TOTP secret, saves to keyring
openconnect-saml --server vpn.example.com --headless --user user@example.com

# Subsequent runs use saved credentials
openconnect-saml --server vpn.example.com --headless --user user@example.com

More Options

# Without sudo (for --script-tun)
openconnect-saml --server vpn.example.com --no-sudo -- --script-tun

# With CSD hostscan wrapper
openconnect-saml --server vpn.example.com --csd-wrapper /path/to/csd-wrapper.sh

# Reset saved credentials
openconnect-saml --user user@example.com --reset-credentials

# SSL legacy mode (for older VPN appliances)
openconnect-saml --server vpn.example.com --ssl-legacy

# Custom timeout
openconnect-saml --server vpn.example.com --timeout 60

Configuration

Config file: $HOME/.config/openconnect-saml/config.toml

[default_profile]
address = "vpn.example.com"
user_group = ""
name = "My VPN"

[credentials]
username = "user@example.com"

# Optional: run a command on disconnect
on_disconnect = ""

Auto-fill rules

Custom auto-fill rules can be defined per URL pattern:

[auto_fill_rules]
"https://*" = [
    { selector = "input[type=email]", fill = "username" },
    { selector = "input[name=passwd]", fill = "password" },
    { selector = "input[id=idTxtBx_SAOTCC_OTC]", fill = "totp" },
]

Office365 "Stay signed in?" page

The default rules now auto-dismiss the "Stay signed in?" prompt. If you use custom auto_fill_rules, add these entries:

[[auto_fill_rules."https://*"]]
selector = "input[id=KmsiCheckboxField]"
action = "click"

[[auto_fill_rules."https://*"]]
selector = "input[id=idSIButton9]"
action = "click"

TOTP / Password

Credentials are stored in the system keyring. On first use, you'll be prompted for your password and optional TOTP secret.

If keyring is unavailable (e.g., headless server), passwords are kept in memory for the session.

To clear stored credentials:

openconnect-saml --user user@example.com --reset-credentials

Credits

Based on vlaci/openconnect-sso by László Vaskó, with improvements from kowyo/openconnect-lite.

License

GPL-3.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

openconnect_saml-0.2.0.tar.gz (49.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

openconnect_saml-0.2.0-py3-none-any.whl (40.0 kB view details)

Uploaded Python 3

File details

Details for the file openconnect_saml-0.2.0.tar.gz.

File metadata

  • Download URL: openconnect_saml-0.2.0.tar.gz
  • Upload date:
  • Size: 49.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for openconnect_saml-0.2.0.tar.gz
Algorithm Hash digest
SHA256 977aef8ef3f00bad1f18c8ff60ed23d641112f824ea1226e1783ae3e1e57c932
MD5 5b5e7f9ef01e9e2b5b6465f3b96b05e7
BLAKE2b-256 7b6fcb6dca3ee5cd5d8e659370eaecd31c8311478ab8f98cbaa04bb17dfa4595

See more details on using hashes here.

Provenance

The following attestation bundles were made for openconnect_saml-0.2.0.tar.gz:

Publisher: publish.yml on mschabhuettl/openconnect-saml

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file openconnect_saml-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for openconnect_saml-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 818b5e99283ea58e092facf29cb10aaa963b11a63530ed5eadd5ec67d3407425
MD5 3a94c9e8f413c0aafca6db832eae3c46
BLAKE2b-256 e94af037343aee0801c85f608dc348aa88b2bae7eb208d4d3a283dd3c7917e7d

See more details on using hashes here.

Provenance

The following attestation bundles were made for openconnect_saml-0.2.0-py3-none-any.whl:

Publisher: publish.yml on mschabhuettl/openconnect-saml

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page