Simple Basic Authentication for a Jersey JAX-RS Server

If you are working on an MVP for a start-up you are probably doing many things you have never done before. If one of those things is a REST server please make sure AT THE VERY LEAST to require that clients use HTTPS and that you add an API KEY and SECRET for your REST server using Basic Auth.

To learn the basics about basic auth go here or just google around.

For this post I assume you are using some language that can make use of Jersey JAX-RS version 2.7 or higher.

Okay, so you have written a fucking awesome REST server for your mobile apps to use. You are such a bad ass because it is also running on something like heroku. The REST server does what the client needs, the clients are basically done, so you are ready to go live with your MVP. STOP!! Stop what you are doing and ask yourself this. Have you added at least a basic layer of security? If you haven’t you will most definitely regret it later. Once you have released a client without HTTPS and Basic Auth it is hard to go back and require it. That’s because those HTTP clients will still need to be supported even after you introduce a new version that has some security. So stop what you are doing and follow these simple steps.

  1. Go to my GitHUB repository and add this code to your project.
  2. Annotate your resource classes with @BasicAuthentication
  3. Add the BasicAuthenticationFeature to your ResourceConfig.
  4. Distribute your new API KEY and API SECRET to your client to use.
  5. Have the client modify its REST calls to your API to use Basic Auth.
  6. Feel a lot better about everything in the universe.

You don’t really need to read on at this point. The unit tests show you how to annotate some resources and generate keys.  You can always add layers of user specific authentication or authorization on top of this but at least start with Basic Authentication and HTTPS.

If you are going to make your entire REST API authenticated you will only need a ContainerRequestFilter that performs the authentication. This will work in most cases but sometimes you will also have some unauthenticated resources in your API. For example, an HTML resource that you want anyone to be able to hit (not just your authenticated mobile client). For those cases I created an annotation named @BasicAuthentication. If present code will be authenticated. If not present or set to false (e.g. @BasicAuthentication(false)) then the authenticating filter will not be invoked for that resource method.

All the code you need is in GitHUB at Jester.

To use it in your server you need to generate a KEY and SECRET for your API and install the feature.

To generate the API key and secret I just use the result of calling UUID.nextRandom().toString() twice. Once for the KEY and again for the SECRET. Then I create my Jersey ResourceConfig like this:

public class JerseyResourceConfiguration extends ResourceConfig {

    private static final String API_KEY = "8694c2e7-a9c4-4646-acdb-8dbe8e8829af";
    private static final String API_SECRET = "75c4bca4-5bf9-4c91-99cc-e640ee6cded7";

    public JerseyResourceConfiguration() {
        packages("com.myapp.rest.service");
        register(new BasicAuthenticationFeature(API_KEY, API_SECRET));
        // whatever else you register
    }
}

That’s pretty much it. I keep my source and jars in a secure location so I embed the string literals into the source. You may want to take another approach to ensure the privacy of these strings. You should find lots of examples in the test directory of the GitHUB project.

Next give these strings to your client developers and tell them to make REST calls with basic auth. You can also use curl to test your API.

curl
-u "8694c2e7-a9c4-4646-acdb-8dbe8e8829af:75c4bca4-5bf9-4c91-99cc-e640ee6cded7" https://myrestapi/dosomething

I’ll try to expand on all this later but I wanted to get something up quickly for those of you who would otherwise push an unsecured REST API onto Heroku.