If you are a Java developer, then you are undoubtedly familiar with frameworks such as Spring, Play!, and Struts. While all three provide everything a web developer wants, I decided to write a RESTful web application using the Jersey framework. This sample app uses Java + Jersey on the back-end and Angular JS on the front-end.

Jersey annotation service makes it easy to do routing, injection, and other functions important to a RESTful web application. My goal was to demonstrate the use of the Stormpath Java SDK for user management and the protection of a REST endpoint using API Keys and Oauth Tokens, all while relying on Jersey.

You can check out the Stormpath Jersey sample app in github, and follow along here for the implementation details and concepts I found most important while building this application. I will explain Stormpath SDK calls, Jersey annotations, and the general flow of the application, so it the codebase is easy to decipher.

Let’s code!

Login

Stormpath provides username/password authentication in three lines of Java SDK method calls. That makes it very simple to launch a basic login form, securely.

As soon as a user enters their credentials and clicks the “Sign In” button, an AJAX request is made to the /login endpoint. Let’s take a look at the server side login code:

Here we see three examples of Jersey’s annotation feature. The @Path annotation acts as our router. The @Context annotation injects the HTTP Request object into our class. Finally, the @POST specifies the CRUD operation.

User authentication is done by first creating an Application object, creating an AuthenticationRequest object, and finally calling application.authenticationAccount(request) to ask Stormpath to authenticate this account.

Create Account

Creating an account is just as simple as logging in to the service:

All we had to do here, was create an Application and an Account, set the Account attributes, and call createAccount.

Generating an API Key ID/Secret

Once a user logs in, they will be given API Key credentials. In this application, generation of the Keys is a simple AJAX call to /getApiKey:

We use Jersey’s @CookieParam annotation to grab the account Href from the Cookie that was created at login. We create an account, and an ApiKeyList object. We then check if this account already has an API Key. If so, our job is to simply request it from Stormpath; if not, we tell Stormpath to make a new one for this account and return this back to the client. By Base64 encoding the API Key:Secret pair, a developer can now target our endpoint using Basic authentication:

Using a Jersey Filter

A cool feature of the Jersey framework is its Request filter. By implementing ContainerRequestFilter we can intercept an HTTP request even before it gets to our endpoint. To demonstrate, I added an additional level of security around API Key generation. Before a user is allowed to target the /getApiKey endpoint they must pass through the Jersey request filter, which will check if the client is actually logged in (a.k.a has a valid session in the form of a cookie).

If a client is trying to get an API Key without being logged in, they will get a 403 before even reaching the actual endpoint.

Exchanging your API Keys for an Oauth Token

Want even more security? How about trading your API Key for an Oauth Token? Using Oauth also brings the functionality of scope, which we can use to allow users to get weather from specified cities.

Let’s take a look at the code:

Notice the 10 lines of code right after the getToken() declaration. This is a workaround for Jersey’s lack of providing us with a complete request object. Calling request.getParamter() or request.getParameterMap() will always return null, and since creating an AccessTokenResult object requires the Request object with the body still intact, we must recreate the entire request ourselves.

Finally: Securing your REST endpoint

Ahh, the moment we’ve all been waiting for. Now that we have given our users the ability to target this weather endpoint using Basic and Oauth authentication, it is up to us to figure out which protocol they choose to use.

To do this we use a visitor. We create a visitor for each type of authentication protocol that we expect our clients to use (in our case Basic and Oauth). Based on the type of the ApiAuthenticationResult object, the appropriate visitor will be targeted. Notice how inside the OauthAuthenticationResult visitor, we check the scope of the Oauth token that we received, and appropriately give/forbid access to the requested cities.

When we generated our Oauth token in the sceenshot above, we gave access to view weather in London, Berlin, and San Francisco. Thus we can view London’s weather using Oauth:

However, since San Mateo was not included in the scope of the Oauth token, we cannot see its weather:

Conclusion

Jersey is yet another Java framework that seamlessly integrates with the Stormpath SDK to offer user management, API Key management, Oauth, and more. If you’d like to see more code and even run this application yourself please visit: https://github.com/rkazarin/sample-jersey-webapp