Friday, July 29, 2011

Using Apache Commons HttpClient for Digest Authentcation

HTTP Digest based authentication is much better alternative over HTTP Basic authentication.

In case of Basic authentication, user-name and password both are sent to the web server in clear-text and hence vulnerable to eves dropping.

In case of Digest bases authentication, client does a computation where user-name and password both get encrypted along with random value supplied by the web server. This computed result is irreversible and hence of no use to eves dropping. The web-server does the same computation and simply compares the computed result with the one received from the client.

Using Java's HttpURLConnection class, it boils down to application programmer to implement the client side computation/encryption of the various values as needed for the Digest authentication and put that in the HTTP header as a response to the "HTTP 401 Unauthorized" challenge thrown by the web-server.

Just to get idea about the complexities of the computation, here is the Wikipedia link which explains about it,
http://en.wikipedia.org/wiki/Digest_access_authentication

Thanks to the Apache guys, again!!, we have Apache Commons HttpClient that pretty much transparently handles the entire Digest computation for web-server digest authentication challenge.

Here are steps to use Apache Commons HttpClient in your HTTP client application for Digest authentication.

Create or modify your pom.xml to include the dependency,

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.1.1</version>
</dependency>


Here is the very simple Java code that uses the HttpClient API.

  public static String sendDigestAuthentication(
      String username, Sting password,
      String url, String host,
      int portNumber, String protocol) {

    HttpResponse response = null;
    HttpHost targetHost = new HttpHost(
          host, portNumber, protocol);

    DefaultHttpClient httpclient =
      new DefaultHttpClient();
    try {
      httpclient.getCredentialsProvider().
        setCredentials(
          new AuthScope(targetHost.getHostName(),
                targetHost.getPort()),
          new UsernamePasswordCredentials(username,
                        password));
    
      HttpGet httpget = new HttpGet(url);
      response = httpclient.execute(targetHost,
                    httpget);
    } catch (Exception exc) {
       logger.debug("Exception digesting Authentication");
    } finally {
      // When HttpClient instance is no longer needed,
      // shut down the connection manager to ensure
      // immediate deallocation of all system resources
      httpclient.getConnectionManager().shutdown();
    }
    return response.toString();
  }

2 comments:

  1. Sounds very useful.. Didn't understand it completely though. How do I use in browser based web app.
    May be 'hello world' exercise with digest would have been more helpful.

    Thanks anyway...

    Good work Atul. this blog..

    ReplyDelete
  2. Thanks so much for your comment and compliment. I am curious to know which part you didn't understand, I can certainly provide some help.

    As far as browser based web app is concerned, if you develop a web-app with digest auth, the chain of events that happen after client browser sends the request to the server are described here (again, its the same Wikipedia link)

    http://en.wikipedia.org/wiki/Digest_access_authentication#Example_with_explanation

    Basically in this case, browser does the MD5 based digest encryption which is one-way encryption and even server will not be able to decrypt it, it simply compares the one-way hash value of the password which it has stored somewhere.

    -Atul

    ReplyDelete