DevLog: SSH authentication via OAuth2
Traditionally, SSH supports authentication via a number of methods. Typically, you’d use passwords or SSH keys to log in. However, other methods are also possible: keyboard-interactive can be used to ask the connecting user a series of questions. This can be used for two factor authentication, for example. GSSAPI authentication allows for using Kerberos tokens obtained, for example, by logging into a Windows domain to be used as SSH credentials.
When SSH was first invented by by Tatu Ylönen in 1995 most terminal windows had the size of 80 by 25 characters. Netscape Navigator was barely a year old and systems like single sign-on weren’t even on the horizon.
The SSH protocol has, of course, evolved over the years, but even the most recent RFC’s that are implemented are over 10 years old.
Traditionally, large enterprises (telco providers, etc) relied on strong firewall rules to isolate their administrative (SSH) access from the Internet. In some cases central authentication was implemented, for example by means of authenticating from a central LDAP server, or via configuration management. This was rather the exception and implemented only when required by security standards such as PCI-DSS.
As companies moved ouside their traditional network environment into the cloud in recent years access control became more and more of a problem. However, this is not a new problem. SAML was introduced in 2005, but proved to be an unwieldy XML beast, difficult to implement.
Recently OpenID Connect (OIDC) became a very popular add-on to OAuth2 to manage single sign-on needs. (This is not to be confused with the traditional OpenID, the two are not related.) Microsoft Active Directory Federation Services offers OIDC support along with SAML 2.0, and Kubernetes also supports OIDC as an authentication method for administrator.
What’s missing? SSH. The method of accessing the servers running Kubernetes, or traditional workloads.
Of course, you can use GSSAPI to provide automatic login capabilities using your Windows domain, but in the age of Bring Your Own Device that’s no longer appropriate.
Ok, so it’s not 1995 any more, how can we get SSH to authenticate via a browser-based authentication flow?
The key lies in the
keyboard-interactive authentication method described in RFC 4256. This method is supported by almost all SSH clients and gives the SSH server the ability to send the client a list of questions the client needs to answer. It also allows the server to send the client an instruction text. This instruction text can be used to show the client a link.
From here it’s fairly simple. Option one is the authorization code flow: client logs in to the web browser and must then copy the code back into their console. The SSH server checks their identity and that’s it. See this 17 second video.
Option two is the device code flow, where the user is sent to a link and must enter a code from the SSH console. Here we don’t send a question, we simply poll the auth token endpoint for the code to be entered. See this 25 second video.
The latter would also lend itself to displaying a QR code, but OpenSSH, unfortunately, limits the length of the instruction field to 255 characters and doesn’t support UTF-8 either.
As of writing, we have tested the following clients:
- OpenSSH limits the instruction field to 255 characters and does not display non-ASCII characters.
- PuTTY displays the link, but breaks the link after 78 characters.
- WinSCP displays the instruction text, but the link is not clickable or copyable. The author of WinSCP has sent us a preview build which contains this feature.
- FileZilla exhibits a similar link breakage as PuTTY, but it also duplicates all
&characters as well. This has been fixed in a nightly build. It also does not display the instructions when no questions are sent. This is required for the device flow.
- Termius does not display the instruction field on mobile at all, and does not make it possible to copy or click the link on desktop. This issue has been forwarded to their dev team.
- Bitvise does not make it possible to copy or click the link. They are addressing this as a bug.
- JuiceSSH (Android) does not display the instruction field on mobile at all.
Soon. We don’t have an exact release date, it’s uncharted territory and we want to wait at least for the more popular SSH clients to release full support for this feature.
We would like to thank everyone who helped this project with ideas, input and testing.