Retrofit 2 — Hawk Authentication on Android

Hawk authentication is sort of the underdog in the class of authentication types. It’s been officially around since November 2012 when Eran Hammer (aka hueniverse) published the first version. Since than, the HTTP authentication scheme has evolved to its current version 6.x.

This tutorial guides you through the setup on client side using Android. Additionally, this guide is Retrofit 2 only.

Retrofit Series Overview

Why Is This Post Retrofit 2 Only?

The Hawk authentication scheme requires you to generate the HTTP Authorization header including the request url. On Retrofit 1, there is no simple setup to get the request url. This behavior changes with Retrofit 2, because the HTTP layer is completely driven by OkHttp which allows access to the request url using a request interceptor.

Hawk Authentication

Hawk is an HTTP authentication scheme allowing authenticated client requests with partial cryptographic request (and response) verification. The verification includes the HTTP method, request URI, host and optionally the request payload.

We won’t dive deeper into the details of Hawk and assume that you’re already familiar with the authentication scheme. And due to the fact that you’re reading this article, you’ve decided to give it a shot. If you need more information about Hawk, please visit the GitHub project repository and follow the information provided within the Readme.

Add Hawk Dependencies

There are already implementation available for Node.js, Java, Ruby, Python and F#/.Net. We’re using the Java implementation from wealdtech to handle the hawk credentials and header generation on client side (Android). Add the following line to your build.gradle and sync the project in Android Studio.

compile 'com.wealdtech.hawk:hawk-core:1.2.0'  

Once the synchronization process finishes, move on with the next paragraph and integrate Hawk into your project.

Integrate Hawk Authentication

Generally, the implementation of Hawk authentication on Android is similar to every other authentication type (like basic, token, or OAuth). Depending on the implementation of your API, you’ll need to send an appropriate value for the HTTP Authorization header field.

If you read the previous articles within the Retrofit series, you’re already familiar with our concept of the ServiceGenerator. We’re using this class to generate service clients from your interface definitions using Retrofit annotations. The following code depicts the createService() method which does all the magic in regard to authorization header generation.

public class ServiceGenerator {

    public static final String API_BASE_URL = "https://your.api-base.url";

    private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder();

    private static Retrofit.Builder builder =
        new Retrofit.Builder()
            .baseUrl(API_BASE_URL)
            .addConverterFactory(GsonConverterFactory.create());


    public static <S> S createService(
            Class<S> serviceClass, final HawkCredentials credentials) {
        if (credentials != null) {
            HawkAuthenticationInterceptor interceptor =
                    new HawkAuthenticationInterceptor(credentials);

            if (!httpClient.interceptors().contains(interceptor)) {
                httpClient.addInterceptor(interceptor);

                builder.client(httpClient.build());
                retrofit = builder.build();
            }
        }

        return retrofit.create(serviceClass);
    }
}

Let’s review the code and what’s actually going on here. The method parameters for createService() are the class you want to be generated (actually it’s the interface) and second the Hawk credentials. After clearing the already defined request interceptors, we’re creating a new one and intercept the request to add the desired header fields.

For the generation of the Authorization header, we need at least the request URI and request method. The used Java library will automatically add the required host information while generating the header.

Once the required authorization header is created, we’re taking the original request as the base reference to create a new one. We set the appropriate header fields and proceed the request chain using our newly created request.

Usage

It’s important to understand, that you need to request your Hawk credentials first before you’re able to use the authentication. Request your credentials like you would for any other authentication type using a login via username and password. Your API should return the Hawk credentials in response which you’ll use for further requests against API endpoints.

Let’s look at the following interface definition which only describes the /me endpoint requiring authentication before returning the User object.

public interface UserService {  
    @POST("me")
    Call<User> me();
}

This article guides you through the setup and usage of the Hawk authentication scheme using Android as the client. We assume that you have already requested your Hawk credentials from the API you’re consuming. If you need to get those credentials first, you may benefit from our basic authentication on Android tutorial as well.

For illustration purposes, we’re using the test credentials from Hawk’s GitHub repository. On server side, we’re using a Node.js server which requires Hawk authentication for the /me endpoint.

HawkCredentials hawkCredentials =  
    new HawkCredentials.Builder()
        .keyId("dh37fgj492je")
        .key("werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn")
        .algorithm(HawkCredentials.Algorithm.SHA256)
        .build();

UserService userService = ServiceGenerator.create(UserService.class, hawkCredentials);  
Call<User> call = userService.me();  
User user = call.execute().body();  

Use the Java library to create a HawkCredentials object. Pass this object to the createService() method while generating the service client using the ServiceGenerator. Get the Call object for your request and execute it (synchronous or asynchronous) to receive the response object. The defined OkHttp interceptor will add the authorization token before executing requests.

That’s all the magic! You’re now able to authenticate your requests using the Hawk scheme.

Outlook

We’ve already covered basic and token authentication as well as OAuth on Android. This guide shows you how to create an Android client consuming API’s which require Hawk authentication. You’ve learned how to intercept the request and add the required authorization token based on your credentials.

The next tutorial will show you a generally applicable method to handle errors using Retrofit 2.


Additional Resources


Explore the Library

Find interesting tutorials and solutions for your problems.