WebSSH2 now supports secure Single Sign-On (SSO) authentication via HTTP POST requests, enabling integration with enterprise SSO solutions like F5 BIG-IP APM. This feature allows external authentication systems to automatically log users into SSH sessions without requiring manual credential entry.
Security Enhancement: As of the latest update, WebSSH2 uses session-only authentication, meaning all authentication data remains server-side in encrypted sessions.
- POST Authentication: Accept credentials via form-encoded POST requests
- Header-Based Authentication: Support for custom headers (e.g., X-APM-Username, X-APM-Password)
- Session-Only Security: Credentials never sent to client, stored only in server sessions
- Zero Credential Exposure: No passwords, usernames, or keys in HTML/JavaScript
- Backward Compatibility: Existing GET routes with Basic Auth remain unchanged
- Session Management: Credentials stored securely in HTTPOnly Express sessions
- CSRF Protection: Optional CSRF token validation for enhanced security
- Customizable Headers: Support for custom terminal headers and styling
WebSSH2 supports SSO configuration through both environment variables (preferred) and config.json file. Environment variables take precedence over config.json settings.
Configure SSO using the following environment variables:
# Enable SSO functionality
export WEBSSH2_SSO_ENABLED=true
# Enable CSRF protection (recommended for production)
export WEBSSH2_SSO_CSRF_PROTECTION=true
# Trusted proxy IPs (comma-separated list)
export WEBSSH2_SSO_TRUSTED_PROXIES="10.0.0.1,192.168.1.100"
# Header mapping for credentials
export WEBSSH2_SSO_HEADER_USERNAME="x-apm-username"
export WEBSSH2_SSO_HEADER_PASSWORD="x-apm-password"
export WEBSSH2_SSO_HEADER_SESSION="x-apm-session"Alternatively, add the following configuration to your config.json:
{
"sso": {
"enabled": true,
"csrfProtection": false,
"trustedProxies": ["10.0.0.1", "192.168.1.100"],
"headerMapping": {
"username": "x-apm-username",
"password": "x-apm-password",
"session": "x-apm-session"
}
}
}| Option | Environment Variable | Type | Description | Default |
|---|---|---|---|---|
enabled |
WEBSSH2_SSO_ENABLED |
boolean | Enable/disable SSO functionality | false |
csrfProtection |
WEBSSH2_SSO_CSRF_PROTECTION |
boolean | Enable CSRF token validation for POST requests | false |
trustedProxies |
WEBSSH2_SSO_TRUSTED_PROXIES |
array/string | IP addresses for trusted proxy servers (bypasses CSRF) | [] |
headerMapping.username |
WEBSSH2_SSO_HEADER_USERNAME |
string | Header name for username mapping | x-apm-username |
headerMapping.password |
WEBSSH2_SSO_HEADER_PASSWORD |
string | Header name for password mapping | x-apm-password |
headerMapping.session |
WEBSSH2_SSO_HEADER_SESSION |
string | Header name for session mapping | x-apm-session |
Note: Environment variables override config.json settings when both are present.
Authenticate and connect to the default configured host.
Request:
POST /ssh/host/
Content-Type: application/x-www-form-urlencoded
username=john&password=secret123&port=22Authenticate and connect to a specific host.
Request:
POST /ssh/host/myserver.example.com
Content-Type: application/x-www-form-urlencoded
username=john&password=secret123&port=2222| Parameter | Type | Description | Required |
|---|---|---|---|
username |
string | SSH username | Yes |
password |
string | SSH password | Yes |
host |
string | Target SSH server | No (uses URL param or default) |
port |
number | SSH port | No (default: 22) |
sshterm |
string | Terminal type | No (default: xterm-256color) |
header.name |
string | Custom header text | No |
header.background |
string | Header background color | No |
header.color |
string | Header text color | No |
allowreplay |
boolean | Enable session replay | No |
mrhsession |
string | Session recording ID | No |
readyTimeout |
number | Connection timeout (ms) | No |
In BIG-IP APM, create a WebSSO configuration:
- Navigate to Access > Single Sign-On > Forms-Based
- Create a new configuration with:
- Form action:
/ssh/host/* - Username field:
username - Password field:
password - Method: POST
- Form action:
Configure APM to map session variables to form fields:
session.logon.last.username → username
session.logon.last.password → password
For header-based authentication, use this iRule:
when HTTP_REQUEST {
if { [HTTP::uri] starts_with "/ssh/host/" } {
if { [ACCESS::session exists] } {
HTTP::header insert "X-APM-Username" \
[ACCESS::session data get session.logon.last.username]
HTTP::header insert "X-APM-Password" \
[ACCESS::session data get session.custom.ssh_password]
}
}
}<!DOCTYPE html>
<html>
<head>
<title>SSH Login</title>
</head>
<body>
<form action="/ssh/host/myserver.example.com" method="POST">
<input type="text" name="username" placeholder="Username" required>
<input type="password" name="password" placeholder="Password" required>
<input type="hidden" name="port" value="22">
<input type="hidden" name="header.name" value="Production Server">
<input type="hidden" name="header.background" value="red">
<button type="submit">Connect</button>
</form>
</body>
</html>async function connectSSH(host, credentials) {
const formData = new URLSearchParams({
username: credentials.username,
password: credentials.password,
port: credentials.port || 22,
'header.name': `SSH: ${host}`,
'header.background': 'green'
});
const response = await fetch(`/ssh/host/${host}`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: formData,
credentials: 'include'
});
if (response.ok) {
window.location.href = response.url;
} else {
console.error('Authentication failed');
}
}Use the provided test script:
./examples/test-sso.shOr test with curl:
# Test POST authentication
curl -X POST http://localhost:2222/ssh/host/localhost \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "username=myuser&password=mypass&port=22"
# Test with APM headers
curl -X POST http://localhost:2222/ssh/host/localhost \
-H "X-APM-Username: myuser" \
-H "X-APM-Password: mypass" \
-d "port=22"Run the test suite:
npm test -- tests/post-auth.test.js- Client sends credentials via POST or Basic Auth
- Server validates and stores in Express session
- Server returns HTML with only connection info (host/port)
- Client connects via WebSocket with session cookie
- Server authenticates using session credentials
- SSH connection established without client-side credentials
// Client receives only:
window.webssh2Config = {
socket: { url: "...", path: "/ssh/socket.io" },
ssh: { host: "server.com", port: 22 },
autoConnect: true
}
// No username, password, or private keys!- Always use HTTPS in production to encrypt credentials in transit
- Session-only authentication ensures credentials never reach the browser
- HTTPOnly cookies prevent JavaScript access to session tokens
- Enable CSRF protection when not using trusted proxies
- Configure trusted proxies carefully to prevent unauthorized access
- Validate all input on the server side
- Implement rate limiting to prevent brute force attacks
- Log authentication attempts for security auditing
- Use secure session storage with proper timeout configurations
- No credential caching in browser, proxy, or CDN logs
Existing deployments using Basic Auth will continue to work without changes. To migrate:
- Enable SSO in configuration
- Update client applications to use POST instead of GET
- Remove credentials from URLs
- Update any custom authentication logic
All existing routes remain functional:
GET /ssh/host/:hostwith Basic Auth headers- WebSocket authentication for interactive login
- URL parameter authentication (not recommended)
- 401 Unauthorized: Check username/password correctness
- 403 Forbidden: CSRF token validation failed
- Connection Timeout: Verify host is reachable
- Session Issues: Clear cookies and retry
Enable debug logging:
DEBUG=webssh2:* npm start// In browser console
fetch('/ssh/config').then(r => r.json()).then(console.log)For issues or questions:
- GitHub Issues: webssh2/issues
- Documentation: webssh2/docs