Client authentication
What OpenSSH can authenticate with, and why the list looks the way it does.
The methods
Section titled “The methods”Six, counting none. The server’s method table
(auth2.c:77) and the client’s
(sshconnect2.c:387) agree:
| Method | Implementation | Notes |
|---|---|---|
none | auth2-none.c:66 | Not real authentication — it probes the server’s method list, or succeeds outright if PermitEmptyPasswords applies |
publickey | auth2-pubkey.c:876 | Plus the [email protected] variant (sshconnect2.c:1332) |
password | auth2-passwd.c:76 | Plaintext password inside the encrypted channel |
keyboard-interactive | auth2-kbdint.c:68 | Generic challenge/response front-end |
hostbased | auth2-hostbased.c:266 | The client host key signs, for host-to-host trust |
gssapi-with-mic | auth2-gss.c:327 | Compiled in only under #ifdef GSSAPI — Kerberos and friends, portable OpenSSH only |
Two things that look like separate methods but are not:
keyboard-interactive back-ends are pluggable devices, not methods: BSD Auth
or PAM (auth2-chall.c:64). PAM is where LDAP, TOTP and
RADIUS actually live.
publickey credential types all ride the one method — plain key files,
certificates, FIDO/U2F security keys (sk-*), agent-held keys, and PKCS#11
tokens.
keyboard-interactive
Section titled “keyboard-interactive”What it is
Section titled “What it is”A server-driven prompt loop. Rather than defining what the user proves, it defines a way for the server to say “print this text, read a line, send it back” — for as many rounds as it likes. Standardised as RFC 4256, Generic Message Exchange Authentication.
The server sends SSH2_MSG_USERAUTH_INFO_REQUEST (message 60,
ssh2.h:127) carrying a name, an instruction string, and N
prompts, each with an echo flag:
name, instruction, language, num_prompts, { prompt[i], echo[i] }The client is deliberately ignorant of what any of it means.
input_userauth_info_req loops over the prompts,
prefixes each with (user@host) so a malicious server cannot spoof local
output, calls read_passphrase with RP_ECHO taken from the echo flag, and
returns the strings in INFO_RESPONSE (61).
sequenceDiagram
participant C as ssh
participant S as sshd
participant P as PAM / BSD Auth
C->>S: USERAUTH_REQUEST "keyboard-interactive"
S->>P: device->query()
P-->>S: name, instruction, prompts, echo flags
S->>C: INFO_REQUEST (msg 60)
Note over C: render prompts, read answers
C->>S: INFO_RESPONSE (msg 61)
S->>P: device->respond()
P-->>S: more prompts, or done
S->>C: another INFO_REQUEST, or SUCCESS / FAILURE
Why it was needed
Section titled “Why it was needed”password authentication (RFC 4252
§8) has exactly one shape:
one hidden field called “password”, plus a single fixed “your password expired”
branch. Real-world authentication does not fit inside that:
- Challenge/response — S/Key, RSA SecurID, RADIUS challenge. The server must display a challenge before the user can answer.
- Multi-step — password, then a token code, then perhaps a new-password confirmation, with the number of steps decided at runtime.
- Server-supplied text — “Enter code for token #42”, “Password expires in 3
days”.
num_prompts = 0is legal, making it a pure display message. - Per-field echo — a username or token serial should be visible; a PIN should not.
The decisive property is that the client needs no knowledge of the
mechanism. Deploy TOTP, RADIUS, or a new PAM module on the server and every
existing SSH client already works. That is exactly PAM’s model — its
conversation function maps one-to-one onto this exchange — which is why the
whole method is built as a pluggable KbdintDevice with query/respond
callbacks, PAM or BSD Auth plugged in at
auth2-chall.c:64.
When it arrived
Section titled “When it arrived”The IETF secsh draft dates from around 1999–2001; RFC 4256 was not published
until January 2006, long after everyone had shipped it. OpenSSH’s
implementation carries Copyright (c) 2001 Markus Friedl and Copyright (c) 2001 Per Allansson, which is the era it landed.
The tree keeps the fossil record in its configuration aliases. Both
servconf.h:261 and readconf.c:224
still map these onto KbdInteractiveAuthentication:
| Alias | Origin |
|---|---|
ChallengeResponseAuthentication | The pre-standardisation name; demoted to an alias in OpenSSH 8.7 (2021) |
SKeyAuthentication | The S/Key one-time-password scheme it was first built for |
TISAuthentication (client only) | Inherited from SSH1’s TIS Firewall Toolkit auth — the original “server asks an arbitrary question” method |
Combining methods
Section titled “Combining methods”AuthenticationMethods in sshd_config composes the list above into a
multi-factor sequence:
AuthenticationMethods publickey,keyboard-interactiveThat requires public key authentication followed by keyboard-interactive.
Only methods that come next in one or more lists are offered at each stage, so
the client cannot reorder them. Each completed stage returns a
USERAUTH_FAILURE with the partial flag set rather than a success — see
reading sshconnect2.c for how the client handles
that, and server-side authentication for how the server
consumes the lists to decide when you are done.
A keyboard-interactive stage can be pinned to one device:
AuthenticationMethods publickey,keyboard-interactive:bsdauth