The vast majority of authenticated access from clients to servers on the Internet relies on tokens that are typically “bearer” tokens so that anyone who obtains the token can use it to access the protected resources associated with it. This holds for traditional cookies in browsers but also for identity tokens being transported between federated domains in SAML and OpenID Connect and of course OAuth 2.0 bearer tokens. The Token Binding (tokbind) Working Group in the IETF develops a set of specifications that allows for binding the token to a particular client so that even if a token gets stolen or lost, it can not be used outside of the client that it was intended for.
In essence the Token Binding mechanism consists of the client generating a public/private key pair (on-the-fly, in memory) that is associated with a specific client/server pair and by having the “token issuance service” including the public key (aka. “Token Binding ID”) in the token at token creation time. Whenever the client then sends a request to the resource server it will also need to present some proof of ownership of the private key that correlates to the Token Binding ID that is now embedded in the token.
The draft-ietf-tokbind-https document from the same Working Group maps that idea to HTTP requests running over TLS connections where the client needs to present the ownership of the private key by including a header in the HTTP request with a signed piece of data that consists of a unique reference (aka. EKM) to the TLS connection that was used to setup the initial connection to the server. This essentially binds the token to the TLS connection that a specific client has with a specific server. That is interesting stuff that allows for far more secure implementations of WebSSO flows – amongst other scenarios. That is why I did some research into leveraging Token Binding with mod_auth_openidc. In my case there are three prerequisites to make this work:
- the Apache server protecting the resources needs to support the Token Binding TLS extension on the TLS (mod_ssl) level, needs to verify the secure header and needs to pass up the verified Token Binding ID to the upper layer
- the browser needs to support generating the key pair, sending the Token Binding ID on TLS connection establishment, siging the EKM and sending the secure header that includes the EKM signature and the Token Binding ID
- mod_auth_openidc needs to issue a session cookie includes the Token Binding ID in the session cookie and on subsequent requests needs to compare that against the secure header
For 1. I added preliminary support for Token Binding in the Apache HTTP web server in a fork on Github here and for 2. I was able to use a nightly build of Chromium to prove that it actually works. This means that mod_auth_openidc’s session cookies can no longer be replayed outside of the original browser (without relying on obscure low-security tricks that exist today such as browser fingerprinting). I’m hoping to build out support to include “referred tokens” so that also 3rd-party issued id_tokens and Auth 2.0 tokens can be bound to the browser/Apache server as specified by http://self-issued.info/?p=1577.
It may look like quite a bit of work but it actually wasn’t that hard to develop so hopefully we get extensive support for Token Binding in regular releases of web servers and browsers as soon as the specification matures.