While Kerberos’ reputation as a Single Sign On solution is quite strong, its adoption outside the corporate VPN has been limited. One reason is that many host providers block port 88 traffic in the firewalls. What would it take to make Kerberos a viable solution in a web-only constrained situation?
Kerberos communicates over port 88 in order to secure tickets that will be used for authentication and (to a limited degree) authorization on other servers. This communication is done using the Kerberos wire protocols. First the user requests a ticket granting ticket (TGT). Later, the user will use that TGT to get a ticket specific to the service they are trying to talk to.
The connection to get the TGT is a two way street. There are multiple messages and back and forth as both sides performs steps necessary to prove to the other that they are indeed, who they claim to be. This cannot be done over straight HTTP without serious reworking, but it can be done using a techonology called websockets. With websockets, the connection between client and server remains open, and HTTP becomes a tunneling protocol for TCP.
Thus, the two things we need to do to get a TGT are:
- Place the Key Distribution Center (KDC) behind a websockets Proxy.
- Create a modified version of the kinit program that can talk websockets, or build a client side proxy.
There are other approaches, of course. FreeIPA can request a TGT on the server on behalf of the user. The user could download this TGT, and a Browser plugin could even stick it into the Kerberos Credentials Cache. But this bypasses the Kerberos ideal of the users password never crossing the wire.
The second step is trickier: getting the service ticket. This action is performed for the user automatically when visiting a web site that is protected by, for example, mod_auth_krb. The web server responds to a request with a 401 and enough information that the browser knows to try Kerberos…by way of two wrapper libraries called SASL and GSSAPI in turn. Unfortunately, this is a pipeline that is pretty much welded shut: without modifying either the browser or the Kerberos libraries, there is no way to automatically request and inject a service ticket on behalf of the user.
It would be possible for the user to do it explicitly, though. That might be an OK stop-gap measure. Again, a custom client of some sort could fetch the service ticket and push it into the Kerberos credential cache.
I think the most straight forward path would be to :
- Extend the Kerberos libraries to be able to talk Web Sockets as a tunnel for the Kerberos wire protocol.
- Allow a krb5.conf option that will specify that the KDC is reachable via websockets. This would be something along the lines of an krb5.conf line
kdc = wss://kerberos.younglogic.com/kdc
- This value should also be available as a SRV record out of DNS:
As a simple proof of concept, a websocket proxy can run on the client, listening on localhost:88 and talking via Websockets to the KDC. Then the krb5.conf file can point to the local proxy instead of the KDC Websocket proxy.
Websockets is a simple enough protocol that writing it into the Kerberos code base should not be prohibitive. If desired, it could be done as a separate shared object for the general consumption of the system.
It is not necessary to run the TGT fetching code over wss, the SSL version of web sockets, as the handshake already sets up encryption. But there is no drawback to running the whole thing over SSL and it will mask any KDC traffice that is not encrypted.
An additional advantage is that now kpasswd can be run on the same port as the rest of the KDC based services, just on a different URL.
Since Websockets is supported by all the major browsers, making browser plugins to communicate with the KDC is viable.
There might well be other issues of scale: protecting against DOS attacks and the like, but there is a path forward to a secure WebSSO.