The Trouble with HTTP Digest Authentication

The other day I emailed my friend Larry Marburger about the state of HTTP Digest Auth in Ruby, since I knew he had spent a lot of time thinking about authentication for the CloudApp API and client. His response was so enlightening that I asked him if I could re-post it here. Here is what he had to say:

Oh. Digest auth. Sigh… Such a disappointment on so many levels.

Firstly, we use Rails’ digest auth in the current CloudApp API. I doubt it does nonce checking. The new api uses Rails’s token auth scheme. I’m considering adding an HTTP Basic endpoint for clients to exchange credentials for a token. The GitHub API does this and it makes sense. Right now it fetches the user’s auth token using Collection+JSON templates and I’m not too happy with it as an authentication scheme. Authentication isn’t a hypermedia media type’s concern.

Secondly, client support for Digest is abysmal. I haven’t heard from anyone who built a CloudApp client and had a good experience with Digest auth. The common network libraries support Basic and token headers but never digest. It’s a mess.

Finally and most importantly, to use Digest, clients and servers need to store the HA1. It’s a shared secret computed locally by the client and server that’s never transferred over the wire. That was fine back in the day when a hashed, salted password was considered “secure” because a computer couldn’t brute force it before the heat death of the universe. We’re long past those days. An army of AWS instances can be dispatched to build a salted rainbow table in no time. It’s a liability to have HA1s and, quite frankly, it scares the crap out of me.

The only viable authentication schemes I found in my research were sending tokens in an Authorization header like Rails’ implementation (assuming tokens are randomly generated and not hashed passwords) or OAuth2. I’d love to be proven wrong here. The kicker is even after that decision is made, you now need to figure out how a client will exchange credentials for a token. (No, I don’t want to kick the user of a CLI out to their browser in order to authenticate.) I can’t stand hand-rolling token auth or using someone else’s hand-rolled token auth. It’s right up there with creating an API media type. Use one built by smarter people.

I really loved Digest auth. It was great a way to send authenticated messages over HTTP when the payload didn’t need to be encrypted. Now that we have the horsepower to run SSL everywhere and salted hashes can be brute forced, I can’t recommend HTTP Digest.