Last Updated: February 25, 2016
· jpkrohling

REST API Authentication with TOTP

Most of the APIs that we consume as a developer requires some sort of authentication. Usually, the provider and the consumer agrees in a pair of keys: access key and secret key (you should avoid the words "public" and "private" keys, as it might be interpreted as the equally named terms from the encryption world, not appropriate for this case).

This practice is fine, as long as the secret keys are safely stored and transmitted from one side to the other. Having separate keys for developers and for live systems is a good start, as well as having all the communication via SSL. But if one side is using a library with a flawed SSL implementation, then a man-in-the-middle might be able to extract both the access key and the secret key. Not to mention that some companies offer access to their APIs via plain HTTP connection. Too bad.

You, as an API provider, have also the option to agree with the caller in an algorithm to digest a message, that would be used by the other side to authenticate the origin. The problem is that agreeing on a random message is not always easy or secure enough, as the message itself must be known to both parties.

A good solution for this use case is to use Time-based One-time Password, or TOTP for short. You might know this as the standard behind Google Authenticator. The advantage is that as both sides know the secret, they can generate a TOTP and come up with the same results.

For my pet project, I've decided to delegate the authentication of external applications to a separate module. In this case, I just call a REST endpoint sending the access key and TOTP, granting/refusing access based on the response code I've got from my authentication service. But it can also be implemented as a Servlet Filter, RESTEasy PreProcessInterceptor or similars.

The key files for this implementation can be found on the app-info module and utils module, specially these files:

  • TOTP implementation, based on the RFC but spiced up with a couple extra methods.
  • Unit tests, to make sure that our implementation conforms with the RFC
  • AppService, that uses the accessKey to retrieve an application from the data store and use the secretKey to generate the TOTP. If it's a match, send a 200 OK back to the caller.