A few days ago I was in the middle of preparing for my
Spring One 2GX 2014 talk
Creating Modular Test-Driven SPAs (Slideshare) with
Spring and
AngularJS. Part of the presentation is a demo application I created called
botanic-ng. This application uses AngularJS on the client side and Spring (
Boot) on the server-side. As I wanted to not merely create a simplistic toy app, I also intended to add authentication and (simple) authorization to the application.
I did not want to go too crazy with this (e.g. implementing full-fledged
OAuth 2.0 integration). Nevertheless, I wanted to add (I hope) some meaningful security features inside my AngularJS application.
Disclaimer: I am not a security expert. Proceed with caution as this solution may not provide enough security for your application needs.
By chance I came across a demo application that Josh Long
created a while back. That application, while using Spring Security, did not integrate with
Spring Security to the fullest extends, and I felt that I could improve upon that implementation using
Spring Session which is new project created by Spring Security lead
Rob Winch.
Spring Session
The
Servlet 3.0 Specification (
JSR 315) introduced several ways to customize the handling of session cookies, for instance changing the name of the cookie (from the default JSESSIONID) and providing additional security relevant settings:
However, you're still pretty much bound to using cookies in order to store your Session IDs. For cases where you need more comprehensive flexibility for handling your sessions,
Spring Session comes in quite handy and provides
numerous advantages.
By default
Spring Session stores session information in Redis using the
RedisOperationsSessionRepository. Sessions expire by default after 30 minutes but this can be customized using the
setDefaultMaxInactiveInterval property. Beyond Redis a
MapSessionRepository is also provided to allow for easy integration with e.g.
Hazelcast.
For my use-case, I wanted to expose the Session ID not via a standard cookies but via an HTTP header. Luckily,
Spring Session provides various pluggable strategies to customize that behavior. As
Spring Session works as a Filter you have to configure a
SessionRepositoryFilter. On this filter you can set the used
HttpSessionStrategy. By default it uses the
CookieHttpSessionStrategy. For my use-case, though, I am using the
HeaderHttpSessionStrategy, which by default stores the Session ID in an HTTP header called
x-auth-token (This is customizable though).
On the client-side in my
AngularJS application, I am adding a HTTP header via
$http to every request.
$http.defaults.headers.common['x-auth-token'] = user.token;
This is configured upon successful login through the
LoginController.
Botanic-ng submits the login credentials to the server, which in turn uses them to authenticate the user using
Spring Security (
AuthenticationController) and if successful, the
AuthenticationToken containing the Session ID and user roles will be send back to the client.
The Session ID on the client is stored in memory only and if you refresh the client, the user must re-authenticate.
For the full source code, please see: