Secure Shell (SSH)
SSH Authentication Methods: Proving Identity Securely
Read aloud is unavailable in this browser.
The Art of Proving Who You Are
Establishing an encrypted channel is only half the security equation. A perfectly encrypted connection to an attacker's machine provides no protection—we must verify we're talking to the right server and that the person on the other end is who they claim to be.
SSH's User Authentication Protocol (RFC 4252) solves this challenge through multiple mechanisms, each with distinct security properties, operational characteristics, and use cases. From simple passwords to cryptographic key pairs to hardware security tokens, SSH provides a sophisticated toolkit for identity verification.
By the end of this page, you will understand each SSH authentication method in depth: how it works cryptographically, its security properties, configuration options, and appropriate use cases. You'll be able to design authentication policies balancing security, usability, and operational requirements.
User Authentication Protocol Overview
The SSH User Authentication Protocol operates after the transport layer establishes encryption. All authentication messages are encrypted, protecting passwords, signatures, and other sensitive data.
Protocol Flow:
Authentication follows a structured negotiation:
SSH_MSG_USERAUTH_REQUEST Structure:
byte SSH_MSG_USERAUTH_REQUEST (50)
string user name (UTF-8)
string service name (typically "ssh-connection")
string method name ("password", "publickey", etc.)
... method-specific data
Authentication Methods Defined in Standards:
| Method | RFC | Description | Security Level |
|---|---|---|---|
| publickey | 4252 | Cryptographic signature proving key possession | High |
| password | 4252 | Traditional username/password | Medium (depends on password) |
| keyboard-interactive | 4256 | Challenge-response, supports MFA integration | Variable |
| hostbased | 4252 | Client host authentication + user mapping | Medium (depends on deployment) |
| gssapi-with-mic | 4462 | Kerberos/GSSAPI integration | High (within managed environment) |
| none | 4252 | No authentication (usually rejected) | None |
SSH clients try authentication methods in a configured order. OpenSSH defaults to: gssapi-keyex, gssapi-with-mic, publickey, keyboard-interactive, password. Servers advertise which methods they'll accept, and clients try methods until success or exhaustion of options.
Password Authentication
Password authentication is the simplest method: the client sends the user's password over the encrypted channel, and the server verifies it against its user database.
Protocol Exchange:
byte SSH_MSG_USERAUTH_REQUEST (50)
string user name
string "ssh-connection"
string "password"
boolean FALSE (not a password change)
string password (plaintext over encrypted channel)
Security Properties:
- •Simple to use — No key generation or distribution required
- •Familiar model — Users understand passwords
- •No client-side secrets — Works from any client
- •Encrypted transmission — Unlike Telnet, passwords are never exposed on the wire
- •Brute-forceable — Attackers can try many passwords
- •Phishing vulnerable — User types password into attacker's prompt
- •Reuse risk — Shared passwords across services enable credential stuffing
- •Server has secret — Compromised server exposes password (unless hashed)
- •No forward identity proof — Password proves knowledge, not possession of anything unique
Password Change Support:
SSH supports interactive password changes:
- Client sends password with change flag = TRUE
- Client includes old password and new password
- Server validates old password and applies change
- Server may respond with SSH_MSG_USERAUTH_PASSWD_CHANGEREQ to force change
This enables password expiration policies through SSH.
Hardening Password Authentication:
If passwords must be used, additional protections help:
# In /etc/ssh/sshd_config:
# Limit authentication attempts per connection
MaxAuthTries 3
# Reduce login timeout
LoginGraceTime 30
# Use PAM for password policies
UsePAM yes
# Consider fail2ban for brute-force protection
# External: fail2ban monitors auth.log and bans IPs
For internet-facing servers, disable password authentication entirely: PasswordAuthentication no. Public key authentication eliminates brute-force attacks. Password authentication introduces unnecessary risk that no amount of rate limiting fully mitigates.
Public Key Authentication
Public key authentication uses cryptographic key pairs to prove identity. The client demonstrates possession of a private key without revealing it, providing strong authentication that cannot be brute-forced.
The Fundamental Principle:
Public key cryptography enables:
- A private key that must remain secret
- A public key that can be freely distributed
- A one-way mathematical relationship: knowing the public key doesn't reveal the private key
- Operations only the private key owner can perform (signing)
- Operations anyone with the public key can perform (verification)
Authentication Protocol:
The Signature Proves Identity:
The signature covers:
string session identifier (from key exchange)
string SSH_MSG_USERAUTH_REQUEST constant
string user name
string service name
string "publickey"
boolean TRUE
string public key algorithm
string public key blob
The session identifier binding is critical—it proves the signature was generated specifically for this session, preventing replay attacks.
Key Types for Authentication:
| Algorithm | Key Command | Status | Notes |
|---|---|---|---|
| Ed25519 | ssh-keygen -t ed25519 | Preferred | Fast, secure, small keys |
| ECDSA (P-256) | ssh-keygen -t ecdsa -b 256 | Acceptable | NIST curve |
| ECDSA (P-384) | ssh-keygen -t ecdsa -b 384 | Acceptable | Higher security |
| RSA (4096-bit) | ssh-keygen -t rsa -b 4096 | Acceptable | Wide compatibility |
| RSA (3072-bit) | ssh-keygen -t rsa -b 3072 | Acceptable | Minimum recommended now |
| DSA | ssh-keygen -t dsa | Deprecated | Fixed 1024-bit, disabled by default |
Key File Locations:
# Private keys (user):
~/.ssh/id_ed25519
~/.ssh/id_ecdsa
~/.ssh/id_rsa
# Public keys (user):
~/.ssh/id_ed25519.pub
~/.ssh/id_ecdsa.pub
~/.ssh/id_rsa.pub
# Authorized keys (server):
~/.ssh/authorized_keys # One public key per line
authorized_keys Format:
# Format: [options] key-type base64-encoded-key comment
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGyz... user@laptop
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbm... user@desktop
# With options:
command="/bin/backup",no-port-forwarding ssh-ed25519 AAAAC... backup-agent
from="192.168.1.*" ssh-ed25519 AAAAC... internal-user
Private keys must be protected: (1) Restrict file permissions to owner-only (chmod 600), (2) Encrypt with a passphrase (ssh-keygen prompts for one), (3) Use SSH agent to cache decrypted keys, (4) Consider hardware keys (FIDO2) for critical access. The private key is your identity—its compromise is complete identity theft.
SSH Agent and Key Management
The SSH agent solves the usability problem of passphrase-protected keys. Rather than typing passphrases for every connection, the agent holds decrypted private keys in memory, signing authentication challenges on request.
How SSH Agent Works:
Agent Operations:
# Start the agent (usually automatic in desktop environments)
eval $(ssh-agent)
# Add key to agent (prompts for passphrase)
ssh-add ~/.ssh/id_ed25519
# Add with lifetime limit (key removed after timeout)
ssh-add -t 3600 ~/.ssh/id_ed25519 # 1 hour
# List keys in agent
ssh-add -l
# Remove specific key
ssh-add -d ~/.ssh/id_ed25519
# Remove all keys
ssh-add -D
# Lock agent (require passphrase to unlock)
ssh-add -x
Agent Forwarding:
SSH can forward agent connections through SSH sessions, enabling multi-hop authentication without copying private keys:
# Connect with agent forwarding
ssh -A user@jumphost
# From jumphost, authenticate to internal server using local key
ssh user@internal
The internal server's authentication request travels back through the SSH connection to the local agent.
Agent forwarding exposes your authentication capabilities to the intermediate host. A compromised jumphost could use your agent to authenticate as you to any server. Use ProxyJump (-J) instead when possible—it establishes direct encrypted tunnel without forwarding agent access.
Safer Multi-Hop Connections:
# Using ProxyJump (recommended): agent stays local
ssh -J jumphost user@internal
# Equivalent config in ~/.ssh/config:
Host internal
User user
ProxyJump jumphost
# Now simply:
ssh internal
ProxyJump establishes a tunnel through jumphost directly to internal server. Authentication to internal happens through this tunnel, with your agent accessed locally—never exposed to jumphost.
Certificate-Based Authentication
SSH certificates solve the scalability problem of authorized_keys management. Instead of distributing individual public keys to every server, a Certificate Authority (CA) signs user keys, and servers trust keys signed by that CA.
The authorized_keys Scaling Challenge:
With traditional public key authentication:
- Each user's public key must exist in
authorized_keyson every server they access - Adding users means updating hundreds of servers
- Revoking access means updating hundreds of servers
- Key rotation becomes a massive operational burden
SSH Certificates Solve This:
Certificate Contents:
SSH certificates contain:
- The user's public key
- The signing CA's identity
- A validity period (not before, not after)
- A serial number for revocation tracking
- Principals: authorized usernames
- Extensions: permitted capabilities
- Critical options: restrictions
Creating and Using Certificates:
# Generate CA key pair (do this once, protect the private key!)
ssh-keygen -t ed25519 -f /etc/ssh/ca_user_key -C "SSH User CA"
# Sign a user's public key to create certificate
ssh-keygen -s /etc/ssh/ca_user_key
-I "alice@example.com"
-n alice,admin
-V +52w
~/.ssh/id_ed25519.pub
# Output: ~/.ssh/id_ed25519-cert.pub
# Examine certificate
ssh-keygen -L -f ~/.ssh/id_ed25519-cert.pub
Server Configuration:
# In /etc/ssh/sshd_config:
# Trust keys signed by this CA
TrustedUserCAKeys /etc/ssh/ca_user_key.pub
# Optional: restrict authentication to specific principals
AuthorizedPrincipalsFile /etc/ssh/auth_principals/%u
| Option | Flag | Purpose |
|---|---|---|
| Serial Number | -z serial | Unique ID for revocation |
| Certificate ID | -I identity | Human-readable identifier for logging |
| Principals | -n user1,user2 | Usernames this cert can authenticate as |
| Validity | -V +1w or -V start:end | Time window certificate is valid |
| Extensions | -O | permit-X11-forwarding, permit-pty, etc. |
| Source Address | -O source-address=CIDR | Restrict to specific client IPs |
| Force Command | -O force-command=cmd | Limit to specific command execution |
Issue certificates with short validity periods (hours or days) instead of relying on revocation. Users request fresh certificates as needed. This eliminates revocation infrastructure complexity while ensuring access naturally expires even if the certificate can't be revoked.
Keyboard-Interactive Authentication
Keyboard-interactive authentication (RFC 4256) provides flexible challenge-response dialog. Unlike simple password authentication, it supports multiple prompts, variable challenges, and integration with external authentication systems.
Protocol Exchange:
Use Cases:
One-Time Passwords (OTP):
- First prompt: "Password:" → user's regular password
- Second prompt: "Verification code:" → TOTP from authenticator app
RADIUS Integration:
- Challenge from RADIUS server relayed to SSH client
- Response forwarded back to RADIUS for verification
Hardware Token Authentication:
- Server requests challenge-response from hardware token
- Client relays challenge to user; user provides token response
Adaptive Authentication:
- Different challenges based on source IP, time, or user history
- Risk-based additional verification steps
PAM Integration (Pluggable Authentication Modules):
On Linux/Unix, keyboard-interactive typically uses PAM:
# /etc/ssh/sshd_config:
ChallengeResponseAuthentication yes
UsePAM yes
# /etc/pam.d/sshd:
auth required pam_google_authenticator.so
auth required pam_unix.so
This configuration requires both password (pam_unix) and TOTP (pam_google_authenticator).
TOTP Configuration Example:
# User generates TOTP secret:
google-authenticator
# Creates ~/.google_authenticator with secret and config
# User scans QR code with authenticator app
# Subsequent SSH logins prompt for:
# 1. Password
# 2. Verification code from app
Password authentication is a single-exchange method with fixed semantics. Keyboard-interactive is a multi-round protocol that can implement password authentication AND additional factors. For MFA, keyboard-interactive is required—simple password authentication cannot prompt for a second factor.
FIDO2/WebAuthn Hardware Security Keys
Modern SSH supports FIDO2 (WebAuthn) hardware security keys like YubiKey. These devices store private keys in tamper-resistant hardware, requiring physical user presence to authorize signatures. This provides phishing-resistant authentication that software cannot fully replicate.
FIDO2 SSH Key Types:
| Algorithm | Key Type | Description |
|---|---|---|
| sk-ssh-ed25519@openssh.com | FIDO2 Ed25519 | Ed25519 key requiring hardware token |
| sk-ecdsa-sha2-nistp256@openssh.com | FIDO2 ECDSA | NIST P-256 ECDSA on hardware token |
How FIDO2 Keys Work:
- Key Generation: Private key generated and stored on the hardware device
- Public Key Export: Only the public key is extractable for server configuration
- Authentication: Server sends challenge; SSH client requests signature from device
- User Presence: Device requires physical touch/PIN before signing
- Response: Signed challenge returned to server for verification
The private key never leaves the hardware device—not even encrypted.
Resident vs Non-Resident Keys:
# Non-resident: key handle stored locally, device holds private key
ssh-keygen -t ed25519-sk
# Output: id_ed25519_sk, id_ed25519_sk.pub
# The .sk file contains a key handle, not the private key
# Resident: key fully stored on device, discoverable
ssh-keygen -t ed25519-sk -O resident
# Key can be retrieved from device without local files:
ssh-keygen -K # Download resident keys from device
Configuration and Usage:
# Generate FIDO2 key (prompts for device touch)
ssh-keygen -t ed25519-sk -O application=ssh:production-servers
# Require PIN verification (not just touch)
ssh-keygen -t ed25519-sk -O verify-required
# Deploy public key normally
cat ~/.ssh/id_ed25519_sk.pub >> authorized_keys
# SSH usage (device touch required for each connection)
ssh user@server # LED blinks, touch to authorize
FIDO2 authentication incorporates origin binding—the hardware key validates it's communicating with the correct server. An attacker cannot relay authentication to a different server. Combined with required physical presence, FIDO2 keys represent the highest practical security for SSH authentication.
KEEP LEARNING
There’s more to understand.
You’re reading the introduction. Create a free account to read the complete lesson, save notes and keep track of your progress.