IMPLEMENTING HTTP DIGEST AUTHENTICATION

2014-08-15

Recently, I was trying to add HTTP digest authentication on my
Home automation device.
The device exposes a REST interface trough a proxy server. My web server is setup like this

Now since my API is exposed to the world by proxying it like that, I wanted to add security
by implementing HTTP digest authentication. Whether or not Digest authentication with MD5 is
secure or not is a completely different story, but let's assume it is good enough for now.
I have a restricted access webpage that I go on to control my home automation device. This web page
makes requests to DHAS using javascript.
Since I've implemented digest authentication, I now need to put the credentials in the javascript so that
the calls made with XMLHttpRequest can succeed. Even though that javascript code will only be served to me, while
I am authenticated on the website, I felt uncomfortable to leave a hardcoded username and password in the JS source.
So this is what I came up with:

Note that messages sent from JS to DHAS are being proxied by Apache. Therefore, DHAS receives a GET for /insteon/listmodules and not
for /dhas/insteon/listmodules

use XMLHttpRequest to make a request to DHAS (through the proxy)

add a header "X-NeedAuthenticationHack" in the request

receive a 401

get the "X-WWW-Authenticate" header from the 401 response

Make a XMLHttpRequest to the server and send it the "X-WWW-Authenticate" data

Server side php script with hardcoded username/password for DHAS solves the challenge and returns the resonse

use XMLHttpRequest to make a request to DHAS (through the proxy) and append the response in a "Authorization" header

So basically, I just intercepted the 401 and instead of letting the browser prompt for a username password, I created the response myself.
And instead of doing in the JS, I did it on the server, limiting the exposition of the username/password. You may notice my two special
X headers. This is because if the server returns a 401 with WWW-Authenticate, the browser will prompt for your credentials. Event
if I have a handler defined to get the 401. So when I send my initial request, I set the X-NeedAuthenticationHack header to tell the server:
"Hey, don't send me a WWW-Authenticate, send a X-WWW-Authenticate instead so I can deal with it".

By the way, even if the information is easy to find, this is how the digest authentication is done: