Implementation of HTTP digest authentication for Android
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
docs/javadoc
gradle/wrapper
src
.gitignore
.travis.yml
LICENSE.md
README.md
build.gradle
gradle.properties
gradlew
gradlew.bat
settings.gradle

README.md

Build Status codecov API Download

bare-bones-digest, HTTP digest authentication for Android

bare-bones-digest is an implementation of the HTTP Digest authentication scheme for Android. With a small effort you can use it to get HTTP digest working with HttpURLConnection or any other HTTP stack.

bare-bones-digest aims to support all features of HTTP digest that is used in real-life applications. The goal is to be interoperable with any server with a HTTP digest implementation.

As of version 1.0.0, bare-bones-digest is stable. Changes will only be made as results of bug reports or feature requests.

Why?

Android's standard class for HTTP communication, HttpURLConnection, has no built-in support for HTTP Digest. If you need HTTP digest anyway here are some possible approaches:

  • Use the Apache HttpClient that is (or at least was) included in Android and that supports HTTP digest. Apache HttpClient has been included in Android from the very start, but Google recommends against using it unless you are targeting very old versions of Android (Froyo and older). The version of HttpClient included in Android is old and Google is not actively working on it and they have not been for some time. In API 23 the client was removed altogether. Read this blog post on the Android Developers blog for Google's stance.
  • Use a newer version of Apache HttpClient. Note however that Apache has discontinued the HttpClient for Android project.
  • Use OkHttp for HTTP requests. At the moment of this writing OkHttp does not natively support HTTP digest, but you can use a third-party authenticator such as okhttp-digest.

If none of the approaches above suit your needs you can use this library to implement HTTP digest on top of HttpURLConnection (or some other HTTP stack) without too much trouble.

How?

bare-bones-digest is available from jcenter, include it as a dependency in your project's build.gradle:

dependencies {
    compile 'com.albroco:bare-bones-digest:1.0.1'
}

Versioning follows semver. The public API for bare-bones-digest is the project javadoc.

Digest Authentication at a glance

HTTP Digest is defined in RFC 2617. Wikipedia has a good explanation, especially the example is good for a quick overview. The basics are as follows:

  • The client makes a HTTP request to the server.
  • The server responds with status code 401, Unauthorized, and a challenge in a WWW-Authenticate HTTP header.
  • The client sends the request again, now with an added Authorization HTTP header with a response to the challenge. The response contains a hash including the user's credentials, information about the request, and parts of the challenge.
  • To avoid sending each request twice, in subsequent requests the client can reuse the challenge. Only the first request will have to be sent twice.

Implementing HTTP Digest authentication

Here is an example of how to make a request and respond to a Digest challenge:

// Step 1. Create the connection
URL url = new URL("http://httpbin.org/digest-auth/auth/user/passwd");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();

// Step 2. Make the request and check to see if the response contains an authorization challenge
if (connection.getResponseCode() == HttpURLConnection.HTTP_UNAUTHORIZED) {
    // Step 3. Create a authentication object from the challenge...
    DigestAuthentication auth = DigestAuthentication.fromResponse(connection);
    // ...with correct credentials
    auth.username("user").password("passwd");

    // Step 4 (Optional). Check if the challenge was a digest challenge of a supported type
    if (!auth.canRespond()) {
        // No digest challenge or a challenge of an unsupported type - do something else or fail
        return;
    }

    // Step 5. Create a new connection, identical to the original one...
    connection = (HttpURLConnection) url.openConnection();
    // ...and set the Authorization header on the request, with the challenge response
    connection.setRequestProperty(DigestChallengeResponse.HTTP_HEADER_AUTHORIZATION,
        auth.getAuthorizationForRequest("GET", connection.getURL().getPath()));
}

DigestAuthentication is the main entry point of the API, read the documentation for more examples. Some other useful classes include:

  • WwwAuthenticateHeader which can be used to parse challenges from WWW-Authenticate headers, including challenges of other types than Digest.
  • DigestChallenge which provides functionality for parsing digest challenges.
  • DigestChallengeResponse which provides functionality for generating responses to digest challenges.

Features

  • Supports MD5, MD5-sess, SHA-256, and SHA-256-sess algorithms.
  • Supports auth, auth-int and RFC 2069 quality of protection.
  • Somewhat lenient parsing, where common server mistakes (such as not quoting the qop directive) does not cause the parsing to fail.

Interoperability

bare-bones-digest has been tested for interoperability with the following servers:

For each valid combination of qop and algorithm that the server supports a single request has been successfully authenticated.

bare-bones-digest has been tested with, and is not compatible with, the following servers:

Limitations

The implementation is based on RFC 2617. Features from RFC 7616 (which obsoletes RFC 2617) are only partially implemented.

Support

Please file a github issue if you have any problems! In particular, file an issue if bare-bones-digest is not interoperable with your server of choice.

References

  • RFC 2069 (obsolete): An Extension to HTTP : Digest Access Authentication.
  • RFC 2616 (obsolete): Hypertext Transfer Protocol -- HTTP/1.1.
  • RFC 2617 (obsolete): HTTP Authentication: Basic and Digest Access Authentication.
  • RFC 5234: Augmented BNF for Syntax Specifications: ABNF.
  • RFC 7230: Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing.
  • RFC 7235: Hypertext Transfer Protocol (HTTP/1.1): Authentication.
  • RFC 7615: HTTP Authentication-Info and Proxy-Authentication-Info Response Header Fields.
  • RFC 7616: HTTP Digest Access Authentication.
  • Wikipedia on Digest access authentication.
  • draft-smith-sip-auth-examples-00.txt: Digest Authentication Examples for Session Initiation Protocol (SIP).