Introduction to WebAuthn for SSH
During our recent infrastructure audit of a mid-sized Indian fintech firm, we observed that over 90% of their developer workstations stored unencrypted SSH private keys in ~/.ssh/id_rsa. This common practice creates a single point of failure: if a laptop is compromised by infostealer malware, the entire server fleet is at risk. The release of OpenSSH 8.2 in February 2020 introduced a paradigm shift by supporting FIDO2/WebAuthn hardware security keys. This allows us to move away from file-based secrets toward hardware-backed credentials that never leave the physical device.
What is WebAuthn and How Does it Apply to SSH?
WebAuthn is a core component of the FIDO2 project, designed to provide a standardized interface for authenticating users via public-key cryptography. In the context of SSH, WebAuthn replaces the traditional private key file on your hard drive with a "key handle" that refers to a private key stored inside a hardware security key like a YubiKey or SoloKey. When you attempt to log in, the SSH client sends a challenge to the hardware key. The key requires a physical gesture (a touch or a PIN) to sign that challenge and return it to the server.
I found that this mechanism effectively decouples the identity from the filesystem. Even if an attacker gains root access to your local machine, they cannot steal your SSH key because the actual signing material is trapped inside the secure element of the hardware token. This implementation uses two new key types: [email protected] and [email protected]. The "sk" prefix stands for "Security Key."
The Evolution of SSH Authentication: From Passwords to FIDO2
SSH authentication has historically moved through three distinct phases. First, password-based authentication, which is vulnerable to brute-force and credential stuffing. Second, public-key authentication (RSA/Ed25519), which solved brute-forcing but introduced the risk of key theft. We are now in the third phase: hardware-backed authentication. This phase mandates physical presence and significantly raises the cost of an attack.
In the Indian context, the Digital Personal Data Protection (DPDP) Act 2023 emphasizes "reasonable security practices" to protect PII. For Indian IT service providers managing international client data, moving to FIDO2-backed SSH is no longer optional; it is a critical compliance step to meet global standards and security frameworks like the OWASP Top 10. We have seen a surge in interest from local firms looking to harden their jump servers against targeted phishing attacks by implementing a browser based SSH client.
Why Hardware-Backed Security is the New Standard
Hardware-backed security provides "non-exportability." Unlike a standard Ed25519 key that you can copy to a USB drive or upload to a cloud storage bucket, a FIDO2 SSH key is logically bound to the silicon. When we tested various attack vectors, including remote session hijacking, we found that without the physical touch on the YubiKey, the authentication sequence simply times out. This physical barrier is the only reliable defense against automated, remote exploitation of SSH credentials.
How WebAuthn for SSH Works
Understanding FIDO2 and CTAP2 Protocols
The interaction between the OpenSSH client and the hardware key relies on the Client-to-Authenticator Protocol (CTAP2). When you run ssh-keygen with a security key type, the client communicates with the key via libfido2. The hardware key generates a new key pair internally and returns the public key and a "key handle" to the host. The host saves this key handle in a file that looks like a standard private key but contains no sensitive material.
I observed that during the ssh login process, the server sends a challenge. The client forwards this to the hardware key using CTAP2. The key's internal processor signs the challenge only after the user satisfies the configured User Verification (UV) or User Presence (UP) requirements. This ensures that the person initiating the SSH session is physically at the machine.
The Role of U2F (Universal 2nd Factor) in Secure Shell
While FIDO2 is the modern standard, many older hardware keys only support U2F. OpenSSH is backward compatible with U2F, but it lacks some of the advanced features like "resident keys" (discoverable credentials). In our testing, using a U2F-only key still provides a massive security upgrade over file-based keys, but it requires you to carry the key handle file (e.g., id_ecdsa_sk) to every machine you want to use for SSH access.
Public Key Cryptography vs. Hardware-Bound Credentials
Standard public key cryptography relies on the secrecy of a file. If id_ed25519 is leaked, the identity is compromised. Hardware-bound credentials change the threat model. The "private key" on disk is actually just an encrypted blob that the hardware key can decrypt. Without the specific hardware key that generated that blob, the file is useless. This is why we recommend FIDO2 for all "Tier 0" administrative access in any production environment.
Key Benefits of Implementing WebAuthn for SSH
Phishing Resistance and Protection Against Man-in-the-Middle Attacks
WebAuthn is inherently resistant to phishing because the credential is tied to an "origin" or application string. In SSH, this is often the ssh: prefix. Even if an attacker tricks a developer into connecting to a malicious proxy, the hardware key can be configured to verify the server's identity or simply fail because the challenge-response fails the integrity check. This mitigates risks associated with NIST NVD listed vulnerabilities like CVE-2023-48795 (Terrapin Attack), similar to the techniques discussed in our guide on Implementing SIEM Rules for MFA Proxy Bypass.
Eliminating the Risk of Stolen Private Key Files
We recently analyzed a breach where an attacker used a compromised Slack token to find a developer's .ssh backup in a private channel. With WebAuthn, that backup would be worthless. Since the private key material never leaves the YubiKey's secure element, there is nothing for an attacker to "steal" from the filesystem that would allow them to log in from another device. This effectively kills the "lateral movement" phase of many modern cyberattacks, which can be monitored via advanced threat detection systems.
Simplified Multi-Factor Authentication (MFA) for Developers
Traditional MFA for SSH often involves TOTP (Google Authenticator) codes which are tedious to type and break automated scripts. WebAuthn provides a "Single-Step MFA." By requiring a PIN or touch during the public key exchange, you satisfy both "something you have" (the key) and "something you are/know" (the touch/PIN) in a single cryptographic operation. This improves the developer experience while simultaneously increasing the security posture.
Prerequisites for Using WebAuthn with SSH
OpenSSH Version Requirements (8.2 and Above)
The most significant hurdle for many Indian SMEs is legacy infrastructure. We found that many local VPS providers still offer Ubuntu 18.04 or CentOS 7 by default, which ship with OpenSSH versions older than 8.2. To use WebAuthn, both the client and the server must be running OpenSSH 8.2 or higher. You can verify your version with the following command:
$ ssh -V
OpenSSH_8.9p1 Ubuntu-3ubuntu0.10, OpenSSL 3.0.2 15 Mar 2022
If your server is running an older version, you must upgrade the openssh-server package. On RHEL-based systems, this might require enabling the EPEL repository or compiling from source.
Compatible Hardware Security Keys (YubiKey, SoloKeys, Google Titan)
Not all FIDO2 keys are created equal. We recommend keys that support FIDO2/L2 certification. Common choices include:
- YubiKey 5 Series: The gold standard, supporting both
ed25519-skandecdsa-sk. - SoloKeys / Somu: Open-source alternatives that are cost-effective for smaller teams.
- Google Titan: Reliable, though often harder to procure in India due to shipping constraints.
Note: In India, purchasing a YubiKey 5 NFC can cost upwards of ₹5,500 due to import duties. I suggest checking local distributors like Polymath or ordering in bulk to reduce per-unit costs.
Operating System and Client Support
On Linux, you need libfido2 installed to interface with the hardware. On Ubuntu/Debian, install it via:
sudo apt update
sudo apt install libfido2-1 libfido2-dev
Windows users must use OpenSSH for Windows (included in modern Windows 10/11) or a recent version of PuTTY (0.75+). macOS has native support in its built-in OpenSSH client since Monterey.
Step-by-Step Guide: Generating WebAuthn SSH Keys
Choosing Between sk-ecdsa-sha2-nistp256 and sk-ssh-ed25519
I prefer ed25519-sk because it is faster and uses shorter keys. however, some older FIDO2 keys only support ecdsa-sk (NIST P-256). You should test your key's compatibility by attempting to generate an Ed25519 key first. If it fails with "Key type not supported," fall back to ECDSA.
Creating Resident Keys (Discoverable Credentials) for Portability
Resident keys are stored directly on the hardware key's memory. This means you can walk up to any computer, plug in your YubiKey, and run ssh-add -K to load your keys into the agent without needing any files from a .ssh directory. This is the ultimate "roaming" setup.
# Generate a resident key with a custom application string
ssh-keygen -t ed25519-sk -O resident -O application=ssh:production_access -f ~/.ssh/id_ed25519_sk_prod
The application flag is crucial. It allows you to partition your YubiKey so that different environments (e.g., staging vs. production) use different internal slots. When prompted, you must touch the key and enter a PIN if one is set.
Generating Non-Resident Keys for Standard Use
If you don't need portability, or your key's resident storage is full (most YubiKeys hold only 25 resident credentials), use a non-resident key. This creates a small "key handle" file on your disk.
ssh-keygen -t ed25519-sk -f ~/.ssh/id_ed25519_sk
This will produce two files: ~/.ssh/id_ed25519_sk (the handle) and ~/.ssh/id_ed25519_sk.pub (the public key). You must keep these files on your machine, but they are useless without the physical hardware key.
Setting Up a PIN and Touch Requirement
To enforce maximum security, we should require both a PIN (User Verification) and a touch (User Presence). This is configured during key generation using the verify-required option:
ssh-keygen -t ed25519-sk -O verify-required -f ~/.ssh/id_ed25519_sk_secure
When you use this key, the SSH client will prompt for your YubiKey PIN in the terminal before asking for the physical touch. This protects you even if someone steals your YubiKey, as they would still need the PIN to authenticate.
Configuring the SSH Server for WebAuthn Authentication
Updating the authorized_keys File on the Remote Server
The public key generated by ssh-keygen -t ed25519-sk looks slightly different from standard keys. It includes the [email protected] prefix. Copy this to your server's ~/.ssh/authorized_keys file:
# Example authorized_keys entry
[email protected] AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIP... user@workstation
I recommend adding the verify-required option directly into the authorized_keys file on the server. This forces the server to reject any authentication attempts that didn't involve a PIN check at the client side.
# Enforce PIN verification on the server side
verify-required [email protected] AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAA...
Server-Side Configuration (sshd_config) Best Practices
To fully secure the server, you must disable legacy authentication methods. Edit /etc/ssh/sshd_config and ensure the following parameters are set. This reduces the attack surface for automated bots targeting your infrastructure.
# /etc/ssh/sshd_configPubkeyAuthentication yes PasswordAuthentication no KbdInteractiveAuthentication no MaxAuthTries 3
Explicitly allow the security key algorithms
CASignatureAlgorithms ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-ed25519-sk,ecdsa-sha2-nistp256-sk
After modifying the config, always test the syntax before restarting the service to avoid locking yourself out:
sudo sshd -t
sudo systemctl restart ssh
Testing the Connection with Hardware Verification
When you connect, use the -v flag to observe the hardware interaction. You should see the client waiting for the "authenticator" (your key).
$ ssh -v [email protected]... debug1: Expecting SSH2_MSG_USERAUTH_PK_OK debug1: Confirming with security key...
[Terminal pauses here until you touch the YubiKey]
debug1: ssh_sk_sign: succeeded debug1: Authentication succeeded (publickey).
Advanced Configurations and Use Cases
Using WebAuthn with SSH Agents
Typing your PIN for every single SSH connection or Git pull is frustrating. You can load your security key into ssh-agent. If you are using a resident key, use the -K flag to pull the credentials from the hardware into the agent.
# Start the agenteval $(ssh-agent)
Load resident keys from hardware
ssh-add -K
For non-resident keys, just add the handle file as usual: ssh-add ~/.ssh/id_ed25519_sk. The agent will still prompt for a touch when the key is actually used for a signature, maintaining the security boundary.
Managing Multiple Security Keys for Redundancy
Hardware keys can break or be lost. I always recommend registering at least two keys for every server. One stays on your keychain, and the other stays in a secure safe. In the authorized_keys file, simply list both public keys on separate lines.
# Primary Key (YubiKey 5C)[email protected] AAAAG...
Backup Key (SoloKey)
[email protected] AAAAH...
Integrating WebAuthn SSH with GitHub and GitLab
GitHub and GitLab both support sk- key types. This is excellent for protecting your source code. To add your key, copy the output of cat ~/.ssh/id_ed25519_sk.pub and paste it into the "SSH and GPG keys" section of your profile settings. This ensures that even if your GitHub personal access token is leaked, an attacker cannot push code to your repositories without your physical hardware key.
Troubleshooting and Common Issues
Handling 'Key Type Not Supported' Errors
If you see Key type [email protected] not supported, it usually means one of three things:
- Your OpenSSH version is too old (< 8.2).
- Your hardware key does not support Ed25519 (try
ecdsa-skinstead). - The
libfido2library is missing or thessh-sk-helperis not in your path.
On Linux, check if your user has permissions to access the USB device. You might need to add a udev rule. Create /etc/udev/rules.d/70-u2f.rules with the appropriate vendor ID for your key.
What to Do if You Lose Your Hardware Security Key
Loss of a key is a "break glass" scenario. If you have a backup key registered, use it to log in and remove the lost key's public entry from authorized_keys immediately. If you have no backup, you will need console access (via IPMI or a cloud provider's web console) to restore access. This highlights why redundancy is the most important part of a FIDO2 rollout.
Debugging Connection Failures in OpenSSH
If the connection fails silently, use triple verbosity: ssh -vvv user@host. Look for lines containing debug3: ssh_sk_sign. If you see "sign request failed," ensure your key is plugged in and that you have set the PIN correctly using the YubiKey Manager or a similar tool. Sometimes, a simple replugging of the USB device clears the CTAP2 state.
Conclusion: The Future of Secure Remote Access
The transition to WebAuthn for SSH marks the end of the "stolen key" era. By binding identity to physical hardware, we eliminate the most common path for lateral movement in enterprise networks. We have moved from a world where "possession of a file" equals identity, to one where "possession of a device and physical presence" is the minimum requirement.
Moving Toward a Passwordless Infrastructure
We are seeing more Indian organizations adopt a "Zero Trust" approach where passwords are completely removed from the developer workflow. By combining WebAuthn SSH with SSO-based short-lived certificates, you can create an environment where access is both highly secure and friction-free. The hardware key acts as the root of trust for the initial SSO login, which then issues the necessary SSH certificates.
Summary of Security Gains with WebAuthn for SSH
The primary gain is the mitigation of credential theft. Even in the face of sophisticated attacks like the "Terrapin" protocol downgrade or the "regreSSHion" race condition, having a hardware-backed identity layer provides a final line of defense. It ensures that even if the server-side software has a vulnerability, the attacker cannot impersonate a valid user without the physical token.
Next Command: Verify your current hardware key capabilities by running fido2-token -L to see supported algorithms and resident key capacity.
