WebSSH2 supports multiple authentication methods depending on the route used. This document covers the authentication behavior and important considerations for each approach.
- URL:
http(s)://your-webssh2-server/ssh - Method: Interactive web form
- Features:
- User fills out connection form in browser
- Supports password and private key authentication
- Flexible credential input
- No pre-authentication required
⚠️ DEPRECATION NOTICE: HTTP Basic Authentication is deprecated and may be removed in a future version. We strongly recommend using HTTP POST Authentication for SSO integration and modern authentication workflows.
- URL:
http(s)://your-webssh2-server/ssh/host/:host - Method: HTTP Basic Auth
- Status: Deprecated but still functional
- Features:
- Quick connections to specific hosts
- Immediate SSH credential validation
- Standard HTTP authentication flow
- Migration: Use HTTP POST Authentication for new implementations
- URL:
http(s)://your-webssh2-server/ssh - Method: HTTP POST with credentials in request body
- Status: Recommended for SSO and modern authentication
- Features:
- Clean separation from Basic Auth routes (no session conflicts)
- Better integration with SSO systems
- More secure credential handling
- Compatible with CSRF protection
- Supports complex authentication flows
- Better suited for programmatic access
- Flexible parameter passing (body and/or query params)
POST authentication supports flexible parameter passing:
- Required in body:
username,password - Optional (body or query):
host/hostname,port,sshterm - Precedence: Body parameters override query parameters
This allows SSO systems to:
- Send credentials securely in POST body
- Specify target host via URL query parameters
- Mix and match based on security requirements
WebSSH2 validates SSH credentials immediately upon receiving HTTP Basic Auth credentials. This ensures only valid SSH credentials proceed to the terminal interface.
URL Format: http://localhost:2222/ssh/host/example.com
Flow:
- User navigates to URL
- Browser prompts for credentials (if not cached)
- WebSSH2 validates SSH credentials immediately
- Invalid credentials → 401 Unauthorized → Browser shows auth dialog → User can enter correct credentials → Success
- Valid credentials → 200 OK → Terminal interface loads
URL Format: http://user:pass@localhost:2222/ssh/host/example.com
Flow:
- Browser automatically uses embedded credentials
- WebSSH2 validates SSH credentials immediately
- Invalid credentials → 401 Unauthorized → No re-authentication possible
- Valid credentials → 200 OK → Terminal interface loads
This is standard HTTP Basic Auth behavior, not a WebSSH2 limitation:
- URLs with embedded credentials take absolute precedence over HTTP auth dialogs
- RFC 3986 defines this as the expected behavior for user info in URLs
- Security consideration: Prevents credentials from being cached or persisted inappropriately
WebSSH2 performs immediate SSH validation in the route handlers (app/routes.ts) and returns appropriate HTTP status codes based on the failure type:
// Validate SSH credentials before serving client
const validationResult = await validateSshCredentials(host, port, username, password, config)
if (!validationResult.success) {
switch (validationResult.errorType) {
case 'auth':
// Authentication failed - allow re-authentication
res.setHeader('WWW-Authenticate', 'Basic realm="WebSSH2"')
return res.status(401).send('SSH authentication failed')
case 'network':
// Network/connectivity issue - no point in re-authenticating
return res.status(502).send(`Bad Gateway: Unable to connect to SSH server`)
case 'timeout':
// Connection timeout
return res.status(504).send(`Gateway Timeout: SSH connection timed out`)
default:
// Unknown error
return res.status(502).send(`Bad Gateway: SSH connection failed`)
}
}-
401 Unauthorized: Invalid SSH credentials (authentication failure)
- Browser will prompt for new credentials (if not embedded in URL)
- Indicates credentials are wrong and re-authentication might help
-
502 Bad Gateway: Network/connectivity issues
- Host doesn't exist (DNS failure)
- Connection refused (port closed)
- Network unreachable
- Re-authentication won't help - it's an infrastructure problem
-
504 Gateway Timeout: SSH connection timeout
- Host is unreachable (no response)
- Connection attempt timed out
- Re-authentication won't help
This approach:
- ✅ Prevents invalid credentials from reaching WebSocket layer
- ✅ Provides immediate feedback on authentication failures
- ✅ Follows HTTP standards for proper status codes
- ✅ Differentiates between auth failures and network issues
- ✅ Prevents unnecessary re-authentication attempts for network problems
WebSSH2 uses content negotiation to provide appropriate error responses:
Browser Requests (Accept: text/html):
- Returns a styled HTML error page
- Shows error title, message, and connection details
- Includes "Try Again" button for 401 errors
API Requests (Accept: application/json):
-
Returns JSON with error details:
{ "error": "Authentication failed", "message": "All configured authentication methods failed", "host": "example.com", "port": 22 }
This ensures browsers display user-friendly error pages while API clients receive machine-readable JSON.
- SSO Integration: POST auth works better with SAML, OAuth, and other SSO systems
- Security: More secure credential handling with CSRF protection
- Programmatic Access: Better suited for API integration and automation
- Future-Proof: Basic Auth support may be removed in future versions
# Browser-based
curl -u "username:password" "http://localhost:2222/ssh/host/example.com"
# URL-embedded
curl "http://username:password@localhost:2222/ssh/host/example.com"# Standard POST request - all parameters in body
curl -X POST "http://localhost:2222/ssh" \
-H "Content-Type: application/json" \
-d '{
"username": "myuser",
"password": "mypass",
"host": "example.com",
"port": 22
}'
# Mixed mode - credentials in body, host/port in query params
curl -X POST "http://localhost:2222/ssh?host=example.com&port=22" \
-H "Content-Type: application/json" \
-d '{
"username": "myuser",
"password": "mypass"
}'
# With additional parameters
curl -X POST "http://localhost:2222/ssh?sshterm=xterm-256color" \
-H "Content-Type: application/json" \
-d '{
"username": "myuser",
"password": "mypass",
"host": "example.com",
"port": 22
}'POST authentication is ideal for SSO systems:
// Example: SAML/OAuth → WebSSH2 integration
async function authenticateWithSSO(ssoToken, targetHost, targetPort = 22) {
// Option 1: All parameters in body
const response = await fetch('/ssh', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${ssoToken}` // Your SSO token
},
body: JSON.stringify({
username: await getSSOUsername(ssoToken),
password: await getSSOPassword(ssoToken),
host: targetHost,
port: targetPort
})
});
// Option 2: Mix body and query params (more secure - host not in body)
const params = new URLSearchParams({ host: targetHost, port: targetPort });
const response2 = await fetch(`/ssh?${params}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${ssoToken}`
},
body: JSON.stringify({
username: await getSSOUsername(ssoToken),
password: await getSSOPassword(ssoToken)
})
});
if (response.ok) {
// Redirect to WebSSH2 terminal
window.location.href = response.url;
}
}-
For interactive re-authentication: Use URLs without embedded credentials
✅ Good: http://localhost:2222/ssh/host/example.com ❌ Problematic: http://user:pass@localhost:2222/ssh/host/example.com -
For scripted/automated access: Embed credentials in URL (no retry needed)
✅ Good: http://validuser:validpass@localhost:2222/ssh/host/example.com -
For development/testing: Always test authentication flows with clean URLs first
- Always use HTTPS when transmitting credentials via HTTP Basic Auth
- Configure proper SSL/TLS to protect credential transmission
- Monitor logs for authentication failures to identify issues
- Document this behavior for users to prevent confusion
Symptom: User enters wrong credentials, gets 401, enters correct credentials, but still getting 401
Cause: Credentials are embedded in URL - browser is not using new credentials
Solution: Have user manually edit URL to remove user:pass@ portion
Symptom: 401 response but no authentication dialog appears
Causes & Solutions:
- Embedded credentials in URL → Remove credentials from URL
- Browser cached credentials → Clear browser auth cache or use incognito mode
- CORS issues → Check server CORS configuration
Symptom: Manual browser access works, but curl/scripts fail
Solution: Ensure scripts are properly encoding credentials and handling 401 responses
Example curl command:
curl -u "username:password" "http://localhost:2222/ssh/host/example.com"- 200 OK: SSH credentials valid, terminal interface served
- 401 Unauthorized: SSH credentials invalid, includes
WWW-Authenticateheader - 400 Bad Request: Malformed request or invalid parameters
- 500 Internal Server Error: Server-side issues
- 502 Bad Gateway: SSH server unreachable (network/DNS issues)
- 504 Gateway Timeout: SSH connection timed out
401 Response Headers:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="WebSSH2"Enable debug logging to trace authentication flow:
DEBUG=webssh2:routes npm startLook for log entries like:
Validating SSH credentials for user@host:portSSH validation successful for user@host:portSSH validation failed for user@host:port
- CONFIG.md - Server configuration options
- SERVER_API.md - WebSocket API documentation
- DEVELOPMENT.md - Development and testing guidelines