A tool to connect to VPNs protected by Microsoft SSO authentication using OpenConnect. Available as a command-line tool, a cross-platform GUI application (Linux/macOS), and a GNOME NetworkManager plugin.
A system tray application with a simple interface for managing VPN connections.
cd ui
./scripts/build-linux.sh 2.0.0 appimage
./dist/MS-SSO-OpenConnect-UI-2.0.0-x86_64.AppImagecd ui
./scripts/build-linux.sh 2.0.0 deb
sudo dpkg -i dist/ms-sso-openconnect-ui_*.debcd ui
./scripts/build-macos.sh 2.0.0
# Install the generated .pkg fileFeatures:
- System tray icon with connection status
- Quick connect/disconnect from tray menu
- Multiple connection profiles
- Desktop notifications
- Automatic session cookie caching for fast reconnection
- Passwordless operation via PolicyKit (Linux) or LaunchDaemon (macOS)
Integrates with GNOME Settings, allowing you to manage MS SSO VPN connections like any other VPN.
cd gnome-nm-plugin
./build-deb.sh
sudo dpkg -i dist/network-manager-ms-sso_*.debAfter installation:
- Open Settings → Network → VPN
- Click + to add a new VPN
- Select MS SSO OpenConnect
- Enter your VPN server and credentials
Note: This option is for GNOME desktop users who prefer native NetworkManager integration.
Add this to /etc/nixos/configuration.nix:
let
msSso = builtins.fetchTarball {
url = "https://github.com/FHNW-Security-Lab/ms-sso-openconnect/archive/a10badc.tar.gz";
};
in
{
imports = [ (import "${msSso}/nix/nixos-module.nix") ];
networking.networkmanager.enable = true;
nixpkgs.overlays = [ (import "${msSso}/nix/overlay.nix") ];
services.ms-sso-openconnect.enable = true;
environment.systemPackages = with pkgs; [
networkmanager-ms-sso
];
}Rebuild:
sudo nixos-rebuild switchFor headless servers, scripting, or users who prefer the terminal.
# Clone the repository
git clone https://github.com/FHNW-Security-Lab/ms-sso-openconnect.git
cd ms-sso-openconnect
# Make executable
chmod +x ms-sso-openconnect
# First run will automatically:
# - Create Python virtual environment
# - Install dependencies (playwright, keyring, pyotp)
# - Download Chromium browser
./ms-sso-openconnect --setup- Named Connections: Store multiple VPN configurations identified by custom names
- Multiple Credentials per Server: Same server can have different credentials under different names
- Multi-Protocol Support: Supports both Cisco AnyConnect and GlobalProtect protocols
- Headless Browser Authentication: Uses Playwright to automate Microsoft SSO login
- Secure Credential Storage: Stores credentials in system keychain (GNOME Keyring on Linux, Apple Keychain on macOS)
- Automatic TOTP Generation: Generates 2FA codes from stored secret
- Session Cookie Caching: Caches session cookies per connection for fast reconnection (12h TTL)
- Auto Re-authentication: Automatically re-authenticates when cookies expire
- Fast Reconnect: Detects already signed-in Microsoft accounts for instant reconnection
- Python 3.10+
- PyQt6
- OpenConnect
- PolicyKit (for passwordless operation)
- System keychain: GNOME Keyring or KWallet
- Python 3.10+
- PyQt6
- OpenConnect (via Homebrew)
- Apple Keychain (built-in)
- Ubuntu/Debian-based Linux with GNOME
- NetworkManager
- Python 3.8+ with pip
- GTK4 for the connection editor
- Python 3.8+
- OpenConnect
- System keychain (GNOME Keyring/KWallet on Linux, Apple Keychain on macOS)
core/ # Shared authentication & connection logic
├── auth.py # Microsoft SAML authentication via Playwright
├── config.py # Credential storage in system keyring
├── connect.py # OpenConnect subprocess management
├── cookies.py # Session cookie caching
└── totp.py # TOTP 2FA code generation
ms-sso-openconnect.py # CLI entry point
ui/ # Cross-platform Qt6 GUI (Linux + macOS)
├── src/vpn_ui/ # Application code
│ ├── main.py # Main application controller
│ ├── tray.py # System tray icon & menu
│ ├── worker.py # Async VPN operations (QThread)
│ ├── backend/ # Backend abstraction
│ └── platform/ # Platform-specific code
├── macos/daemon/ # macOS LaunchDaemon for root operations
└── scripts/ # Build scripts
gnome-nm-plugin/ # GNOME NetworkManager integration
├── src/ # D-Bus service & GTK4 editor
├── data/ # D-Bus configuration files
└── packaging/ # Debian packaging
- Opens VPN portal in headless Chromium browser
- Detects if user is already signed in (fast reconnect)
- Enters Microsoft credentials automatically if needed
- Handles "Use your password instead" if app-based login is shown
- Generates and enters TOTP code at the right moment
- Clicks through "Stay signed in?" prompt
- Extracts session cookies after successful auth
- Runs as a system tray application
- Uses PolicyKit (pkexec) for privilege escalation when connecting
- Installs a PolicyKit policy for passwordless VPN connections
- Sends SIGKILL to disconnect (keeps session alive for fast reconnect)
- Runs as a system tray/menu bar application
- Uses a LaunchDaemon running as root for VPN operations
- UI communicates with daemon via Unix socket (JSON-RPC 2.0)
- Sends SIGTERM for graceful disconnect (restores network properly)
- Registers as a VPN plugin with NetworkManager
- Provides a GTK4 connection editor in GNOME Settings
- Runs authentication via D-Bus service
- Credentials stored in GNOME Keyring
- Session cookies cached per connection name
- Linux GUI:
~/.cache/ms-sso-openconnect-ui/ - macOS GUI:
~/Library/Application Support/ms-sso-openconnect/ - CLI:
~/.cache/ms-sso-openconnect/ - Cookies expire after 12 hours or when rejected by server
./ms-sso-openconnect --setupYou'll be prompted for:
- Connection Name (e.g.,
work,office) - VPN Server Address (e.g.,
vpn.example.com) - Protocol (Cisco AnyConnect or GlobalProtect)
- Microsoft account email
- Password
- TOTP Secret (base32 secret from authenticator app setup)
# Connect to the only/default connection
./ms-sso-openconnect
# Connect by name
./ms-sso-openconnect work
# Force re-authentication (ignore cached cookie)
./ms-sso-openconnect --no-cache
# Show browser window for debugging
./ms-sso-openconnect --visible# Disconnect but keep session alive (for fast reconnect)
./ms-sso-openconnect -d
# Disconnect and terminate session
./ms-sso-openconnect --force-disconnect# List all saved connections
./ms-sso-openconnect --list
# Edit an existing connection
./ms-sso-openconnect --setup work
# Delete a connection
./ms-sso-openconnect --delete work./venv/bin/playwright install chromiumUse --visible to watch the browser:
./ms-sso-openconnect --visibleSome firewalls block DTLS (UDP). Use TCP-only mode:
./ms-sso-openconnect --no-dtlsThe Debian package installs a PolicyKit policy for passwordless operation. If you're still getting prompts, ensure the policy file is installed:
ls /usr/share/polkit-1/actions/org.openconnect.policy- Credentials stored in system keychain (encrypted at rest)
- Cookie cache files have 600 permissions (owner read/write only)
- TOTP secrets should be kept secure - treat them like passwords
- Browser runs headless by default for security
- macOS daemon socket has restricted permissions
MIT License
Contributions welcome! Please open an issue or pull request on GitHub.