sshd keyboard-interactive
sshd runs PAM through keyboard-interactive authentication, and relays the
module’s message to the client, where the person logging in reads it in their
own terminal. That makes an approval usable as an SSH authentication step –
either on its own, or as a second factor behind a public key.
This is always the browser flow. PAM_RHOST is set for an SSH session, so
mode=auto never picks the console flow here.
The sshd stanza
Section titled “The sshd stanza”auth sufficient pam_ssoossh.so server=https://ssoossh.example.com \ trusted-ca-file=/etc/ssoossh/ca.pub \ principals-map=/etc/ssoossh/principals.yaml \ timeout=90s
# then the distribution's include:# Debian, Ubuntu @include common-auth# RHEL, Alma, Rocky auth substack password-auth# Alpine auth include base-authSome distributions gate the whole sshd PAM stack with pam_nologin.so or
pam_listfile.so before authentication. Leave those where they are – they are
policy about who may log in at all, and an approval should not bypass them.
sshd_config
Section titled “sshd_config”The stanza does nothing until sshd is actually consulting PAM’s auth stack:
UsePAM yesKbdInteractiveAuthentication yesOn OpenSSH older than 8.7 the second directive is spelled
ChallengeResponseAuthentication yes.
Public-key logins are not affected by any of this: sshd only consults PAM’s
auth stack for keyboard-interactive. So on a host where people already log in
with ssoossh user certificates, adding the stanza changes nothing about those
logins.
As a second factor
Section titled “As a second factor”To require both a valid certificate or key and a human approval:
UsePAM yesKbdInteractiveAuthentication yesAuthenticationMethods publickey,keyboard-interactivesshd then runs the methods in order: the client proves possession of the key
(or of a certificate signed by
TrustedUserCAKeys), and only then is the PAM
auth stack run, where pam_ssoossh asks for an approval. The comma is a
sequence, not a choice – both must succeed.
To offer the approval as an alternative rather than an addition, list two method sets:
AuthenticationMethods publickey keyboard-interactiveSpace-separated sets are alternatives, so either one on its own is enough.
Testing safely
Section titled “Testing safely”An /etc/pam.d/sshd mistake costs you SSH to the machine, and unlike sudo
there may be nothing else listening. Test in this order.
-
Keep an existing SSH session open, and confirm you have console or out-of-band access as well. An already-authenticated session survives a
sshdrestart; a new one is what you are about to risk. -
Back up both files you are touching:
/etc/pam.d/sshdand/etc/ssh/sshd_config. -
Check the config parses before restarting anything:
Terminal window sshd -tThat catches
sshd_configsyntax errors and a badAuthenticationMethodsvalue. It does not read/etc/pam.d/sshd, so it cannot tell you the PAM stack is right. -
Try a second
sshdon another port first, if you want the PAM stack proven before it is in the path of real logins:Terminal window /usr/sbin/sshd -d -p 2222Connect to port 2222 from another machine, watch the debug output, and confirm the approval message reaches your client and that an approval logs you in.
-
Reload the real one only then –
systemctl reload sshd– and immediately open a new session from a different terminal. Keep the old session open until that succeeds. -
Test the failure paths from that new terminal: Ctrl-C at the approval prompt, and a denial in the browser. Confirm you end up somewhere you can still authenticate.
If a new session fails and you still have the old one, restore the backups from it and reload. That is the recovery path, and it only exists while that session is open.
What the approver sees
Section titled “What the approver sees”The approval page names the machine, the PAM service (sshd), the tty, the
account being authenticated, and the remote host the module reported –
PAM_RHOST, so the address the SSH client connected from – alongside the
source address the server observed for the request itself. Everything the
module reported is a claim by an unauthenticated caller and the page labels it
as one.
That pairing is the useful part on an sshd stack: the reported remote host is
where the person logging in says they are, and the observed source address is
where the host is. A mismatch between the two is a question worth asking.