RESTful Spring Security with Authentication Token

Recently I had to do some “research” how to use Spring Security for a RESTful API serving rich JavaScript UI. There were also questions whether to use Spring Security at all, but as of now, we’re still deciding to take this path. While it is possible to have a JSON API that is not really RESTful and we can have HTTP session behind it all, we decided to go with REST. That sets the scene: REST, Spring Security and token-based authentication.

HTTP authentication and tokens

Big question is what mechanism of authentication we want to use. If for nothing else, than at least for username (login) and password we will have SSL/TLS in place, so let’s say we will have HTTPS there all the time. This blurs the difference between classical HTTP Basic and Digest access authentication. So I decided to support Basic only for simplicity. For even easier development I introduced custom X-Username and X-Password headers, which allowed to test my solution with curl and similar tools entering plain values.

I’ve read more than a couple of articles and while I hardly became an expert on security, authentication (with HTTP or not), REST or tokens, I felt I got the basics. I also got familiar with enough ideas that I had to do some choices. I thought it would be easier, but obviously there are many ways how to construct a token. And people are probably still inventing more. So I decided to use randomly generated token that does not utilize user’s password at all – but it doesn’t really matter. You somehow create that token, that’s it. I aimed for solution that allows me to change this behavior easily.

There is also questions whether one token is enough, should you transfer it in HTTP headers or utilize HttpOnly cookie so that JavaScript can’t “share” it with some attacker, etc. Way too many questions and if you feel like, you can share your ideas and reasons in the comments. For I’ll focus on server side now, that is the part related to Spring Security. The landscape here is not that deserted actually – and I got lucky I stumbled upon this StackOverflow question which lead me to this demo on GitHub. I have to admit that some parts are from there and for other parts I used it at least as to check my solution.

Spring Security for REST?

Book Spring Security 3.1 by Robert Winch and Peter Mularien was another important source of understanding what is happening here. I tackled Spring Security before but never had a chance to go in-depth (that is beyond reactive Google/StackOverflow and some reference documentation reading), mostly because I tried to get in-depth with something else. Now was the time to understand what this framework is about. Good book, nice examples – maybe some UML class diagrams would help when introducing new important classes and interfaces and their roles.

The result is my take on RESTful Spring Security – it’s not really that revolutionary, but I tried to do couple of things differently. I even provided UML diagram. 🙂 So I’ll copy it from README.md right here, ok?

restful-spring-security-class-uml

Now what is going on here and – if you insist – how is this different from philipsorst’s solution?

  1. I wasn’t interested in real UI, so I tested it with any REST testing extension you can find, or with curl. In the end I even put together mini-framework based on bash and curl. 🙂
  2. I wasn’t interested in JPA/DB. I wanted as little frameworks thrown in as possible. So there is DAO with hardcoded users.
  3. I also wanted to come up with design that clearly separates the concept (package restsec) from any concrete implementation (secimpl), principles from details, Spring Security from the domain/application code (domain/mvc). Looking at the class diagram I think I did quite well.
  4. I wanted to try access control configured in XML and using annotations like @PreAuthenticate.
  5. Then there are some side-quests – I practiced some Gradle in combination with Spring Boot as my Bill Of Materials (kinda Maven style import scope) and I tested WildFly 8.1 (not really important).
  6. Finally – I wanted to document it sufficiently, both in code (comments) and in README + planned this post too. For self documentation. It pays off. I don’t remember what I need to do to make client certificates up and running on Tomcat, but I know where to look at (if it is not obsolete yet). And I used my own articles here and there already! (Actually, even my colleagues googled out my articles and found them helpful – you can’t imagine how it made me proud. ;-))

Spring Security going session-less

So how is it all working together? Because everything related to HTTP and authentication is concentrated essentially in TokenAuthenticationFilter, you don’t need any unprotected login URL. Filter is sitting in Spring Security filter chain, specifically in FORM_LOGIN_FILTER position. All you need is to provide authentication headers in any request. Because we are RESTful, we don’t want to utilize session at all. If you check spring-security.xml, this is set in http element:

<http realm="Protected API"
        use-expressions="true"
        create-session="stateless"
        entry-point-ref="unauthorizedEntryPoint"
        authentication-manager-ref="restAuthenticationManager">

It is important to set it to stateless (don’t use session at all), not to never (which allows Spring Security to use if it somehow exists already, just don’t create it).

Let’s stop at this statelessness for a while, shall we? This does not mean that there is no server-side state at all. It just means that we don’t work with HTTP session. We still need to remember valid tokens – we may do so within DB, application context, shared distributed memory, wherever – that is definitely stateful. But from HTTP standpoint, we should be RESTful enough now. Also we utilize Spring’s SecurityContextHolder because it makes sense if you want to benefit from other Spring Security stuff, like their annotations, etc. This way we smuggle our security information using a thread-local variable (default behavior) during each single request.

Anonymous access

Before we get to business, let us see how anonymous access works first. For that assume that these are our first request and we didn’t authenticate before. In the following sequence diagrams, grey stuff is from Spring, rest is ours.

anonymous-access-allowed

As any other model, this one is not complete or exact. Our filter is part of Spring Security chain and definitely is not called directly by browser. But in any case it’s the first moment we are interested in. Virtually every request goes through this filter (unless it avoids part of the application secured Spring Security completely). If we are accessing something available for unauthenticated user, we get what we want.

Second scenario tries to access something protected. This will not get to our Spring MVC controller:

anonymous-access-denied

It actually gets all the way to its proxy (in our case CGLib based, because our Controller does not implement any interface) and there an implementation of AccessDecisionManager finds out that anonymous user can’t access the method and AccessDeniedException is thrown. This is caught by ExceptionTranslationFilter (part of Spring Security chain) which calls authentication entry point for this kind of exception. Normal applications use the entry point it to redirect to a login screen. We don’t want to do that, but we need to implement it, so it sets the HTTP response status (401).

It’s very easy to debug it all and it’s very nice to browse through Spring code. Maybe Spring got big and complex (well it does a lot of things now), but their code is on the positive side of quality spectrum – understandable and well documented.

Login, login! Login this lap!

(Sorry, F1 race today, you know.) Four things may be happening in our application. You may be anonymous, you may be authenticated already, you’re logging in, or logging out. My implementation tries not to mix things together much, you should do just one of these things in a single request. Let’s log in to get authenticated. Login request can continue to the REST resource and return data, but I chose otherwise. This can be reimplemented of course – TokenAuthenticationFilter#checkLogin would call doNotContinueWithRequestProcessing only if the response is not 200. But currently it works this way. Here is the diagram:

login

If our filter finds information that looks like login (and it must be POST), it will pass username/password to AuthenticationService. This is still our part of solution and glues the filter with the rest of Spring Security. It calls Springs AuthenticationManager, which in turns calls our implementation of UserDetailsService, which provides username and password (in our case plain, not a good solution of course). Not to plague the diagram with stuff, I skipped Spring’s PasswordEncoder which helps authentication manager to decide if we can go on. If we can, we get back to our security service, which populates Spring’s SecurityContextHolder and now is the time to get the token.

For this we have separate component – TokenManager – which creates and stores the token for the user. Currently only one token per user is supported, but you can implement your own approach here. Actually if you reimplement AuthenticationService considerably, there may be nothing to call TokenManager. There’s a lot of freedom here, but I think TokenManager is the place where most of the customization can go into. How to create the tokens? How to store them? How to check them? Or expire them? However you want to answer these questions, TokenManager is your guy. You still may need to adjust authentication service or filter – for instance to add some HTTP related information (IP address?) into token.

Long story short? If everything is alright, HTTP response returns status 200 and the header X-Auth-Token contains the token next requests should use to prove who you are.

Authenticated request

Here we don’t care what HTTP method is used. After login, this should be easy to understand:

authenticated-access

You already know all the players, here we just first check whether provided token is indeed one of those we know – and if so, we populate SecurityContextHolder. In case of 401, we don’t even bother calling the rest of the chain. The rest (cases 200 and 403) is in Spring’s hands.

Hence we can rush towards…

Logout

Logout should invalidate user’s sess… ehm, token, obviously. That implies valid token is provided. We also insist on POST and require specific URL. We could also request logout with another HTTP header, or with “logout” mentioned in X-Auth-Token, etc. Here it is:

logout

And that’s it really!

Conclusion

You could see all the important players on the diagrams, some of them are our classes, some of them are part of Spring Security “auto-magic”. I’m sure even XML configuration is much clearer now. There is great deal of freedom here – you may bypass Spring Security authentication manager altogether, for instance – don’t know why, but there may be reasons.

I’m not done yet. Later we’ll need to integrate this with some reliable Windows Domain SSO authentication (so far we count on Waffle), not to mention with the rest of the application.

That “demo app” is a mix of XML configuration and annotations, so check those out, check the comments, README, etc. I really tried different things just to find out how it all works (like that mandatory ROLE_ prefix!) and I’m still probably just skimming the surface. But still better than two weeks ago. 🙂

And that concludes my post and my first campaign in this war.

Advertisements

About virgo47
Java Developer by profession in the first place. Gamer and amateur musician. And father too. Naive believer in brighter future. Step by step.

41 Responses to RESTful Spring Security with Authentication Token

  1. Shahar says:

    Great post…

    Do you have code samples for it?

  2. Dan Slack says:

    Great overview of this btw – really clarified some spring related issues I was having!

    Thanks!

  3. Anonymous says:

    hi, this article is very useful to me . What is the difference between the Oauth2 and this way ,can they use together ? Thanks!

  4. Pingback: JIRA: SP0012 - Firecrest Clinical Platform

  5. Anonymous says:

    Hi,
    i wanted just ask about concurrent access in TokenManagerSingle. Is it thread safe ? What happens when two threads want to access (put/remove) the token Map ?
    Otherwise great tutorial. I learnt a lot from you. Thanks 🙂

    • virgo47 says:

      You’re right, it’s not synchronized in any way – and (shame on me) I haven’t give it a thought at all in this case. Except for extreme loads putting synchronized on relevant public methods should do the trick (and I’d prefer it for the simplicity).

      Also – we adopted similar solution on our project, but the TokenManager interface morphed slightly, so I’d not claim it final in the demo project, obviously. 🙂 I’m glad it helped.

  6. srufus says:

    Firstly, great tutorial ! Helped me understand basic stuff about Spring security.
    Just had a question. I am using Advanced REST client on chrome and added the Authorization header with user name and password.
    Is there a specific end point that I have to configure to call to get the token ?

    • virgo47 says:

      I don’t think there is. You’ll get the token with the response to any filtered URL. Filter’s checkLogin prevent from filter chain to go on when you “log in”, so only requests with token are processed properly. This enforces the usage of the token instead of sending user/password with each request – but it can be changed. If you removed doNotContinueWithRequestProcessing(…) calls from checkLogin, it would return the token and process request too. (But I didn’t try this scenario, so maybe it’s not the only change necessary.)

      Long story short – no specific URL, choose any, e.g. base URL that is filtered by that security servlet filter.

  7. saurabh jain says:

    Thank you. This is exactly what I wanted to do.

  8. stewe says:

    Is it valid idea to put tokens into the database? Can be TokenManager “database-aware”? My thought is that after I get some token, I update user in the database with that token.

    The thing is that after your server is down and you start it again, all token information will be lost and every client would have to re-login becase all tokens were just in memory …

  9. virgo47 says:

    This is completely up to your decision/architecture. It reminds me old PHP sessions stored in DB 🙂 but it may be perfectly legitimate usage if you need it. I was originally thinking somewhere along the lines of using HazelCast (or other distributed cache) for this, so my requests can be balanced to any “worker” application without the need of token re-negotiation. There are many possible scenarios – this is “stateless” from the point of the HTTP request (no session), but it is not stateless from the back-end point of view at all. But every single request (wherever it is physically landed) consults the token manager that can consult some distributed cache, or DB, or whatever. This is completely separated from the core of this demo.

  10. Anonymous says:

    Thanks for the details and code, really helpful. I’m new into security and I was reading about OAuth 2.0 Password Grant flow, it’s very similar to what’s happening here but instead you have to pass a ClientID/ClientSecret along with the request. But to think about it, the Client Secret will have to be hard-coded inside the mobile application, making it un-secure. So did you read about OAuth 2.0 Password Grant? Do you think the approach you described is the best way to secure mobile REST apis? I think I’m going with the approach that you described as I can’t think of any other way.

    Also, in the way you described, the User/Pass are saved on the server, which is fine in my opinion. But I’ve heard it’s possible to not save User/Pass on server and maybe use something like Refresh Tokens? I’m really new into security so excuse me for my ignorance, I would just like to hear your opinion about it.

    Thanks again, learned a lot from you! 🙂

    • virgo47 says:

      I’m no security expert, sometimes one just has to read what is available around and decide for a solution. I’ve read a lot, but I always manage to forget how OAuth exactly works, because I’ve never worked with it. This is pure client/server thing without any other party incorporated. Having user/password on the server is OK for many applications, especially when single sign-on is not needed (SSO requirement of course changes it completely). Of course you hash the passwords with something like SHA-256 or similar, use SSL, etc.

      However, as I mentioned in the article, I’m not an expert on security. If I was about to create highly mission-critical system, I’d ask someone who really is.

      • Anonymous says:

        You could still implement OAuth 2.0 while being the Authorization Server and the Resource Server yourself. This way you’re the 3rd party provider, you’re just implementing oauth specs/flows. As I said the Password Grant flow (https://tools.ietf.org/html/rfc6749#section-4.3) is very similar to the flow that you described, however in spring-oauth2 its required to send a client id + client secret along with the initial authentication (you could leave the client secret to blank). Although in my opinion client id + client secret in mobile apps are pretty much useless because they need to be hard-coded, which means its pretty much insecure.

        Anyway as I said I’m going to implement something very similar to your flow, using Filters and TokenManager. I read above that the code evolved since you uploaded it to github, are you planning to share the updates with us? or are the updates mainly customized to your project?

        Again thanks for this very resourceful post.

      • virgo47 says:

        TokenManager interface changed a little bit, mostly to reflect our application, although I think it’s a bit more logical now, but there is nothing crucial that would require me to update this post significantly. 🙂

  11. Michal Aron says:

    Zdravim Riso :D,

    When I saw this article I just told myself I wouldn’t be surprise if he would be from cesko/slovensko..(know a lot good bloggers which are slovaks or czechs 😉

    I am at the moment implementing security to my webapp and hesitating whether use cookie based or token based authentication. Your explanation in this article sums up pretty much what I went through as well.

    Let me ask you some questions 🙂

    1) If I may ask what is your opinion about cookie based and token based authentication (at the moment I have implemented cookie one, will I be able to achieve 2) with token based?)?

    2) What I am trying to implement is to authenticate user using LDAP. Then based on user role in LDAP (user group in AD, like helpdesk, support, IT, network and so..) grant user a ROLE_ (or multiple ROLE_s = ROLE_HELPDESK, ROLE_NETWORK.. (hope you get the idea)) and I need to store this ROLEs for my frontend – Angular in this case.. so I can recognize there what kind of user is using my angular module (secure views/functions and so..)

    Anyway very nice article indeed 🙂

    • virgo47 says:

      Hi Michal 🙂
      With all my previous disclaimers still applied (no security expert, etc.) I’d say that whatever method you use to communicate authentication between client (browser) and server (application), if you want to let frontend know what role the user is, I’d create some API like /user/context to get information about the user. We did the same in times of GWT, we do the same now with JS vs REST API.
      You still have to consider privacy of such information, but frontend knowing what roles the user has probably isn’t any problem and may help offering some features/screens, etc. Of course, you can never rely on what frontend tells you about user’s roles – these must be still kept on server side in the UserContext/UserDetails.
      Another way how to approach feature/screen/menu items visibility is kind of “capability” model. Don’t spread the knowledge about what is secured how between frontend and backend. Create model on the backend and let frontend ask “can I offer this?” (link, menu item, save button (ACL style), whatever). Don’t ask on a screen within frontend code “does this user has BANK_ADMIN role?” instead let the frontend ask the backend “can this user edit banks?” or “what are ACLs for these items?” or just proactively send some ACLs with the list of banks.
      Of course, it may be overkill for simple apps, but it keeps the whole security model more focused. UI just asks about features. It has some inherent knowledge there is some security model, but it doesn’t know its setup. It just uses it.

      • Michal Aron says:

        that was fast.. Thanks for the suggestions. I found redundant to create API for such a thing since I found simpler to store user role somewhere in a header when authenticated (or maybe within token?).
        However after reading your concern “you can never rely on what frontend tells you” I realized you are right.. The best idea is then having frontend asking and backed granting..

        Concern here: “I’d create some API like /user/context to get information about the user”. How do we pass to “/user/context” API which user? Do we use some stored information from the frontend(probably not trustworthy?!?)? Or since we go to /user/context with our token, we can identify there what user is asking for his roles?

        Thanks a lot!

      • virgo47 says:

        First we authenticate, and then we ask for /user/context. It doesn’t work for arbitrary user provided by parameter – there is no parameter, it works for current user. Based on the token we know who is the current user. This idea is again completely independent from authentication mechanism. With GWT app we got user context info based on current session that remembered the user on the server side. When using tokens, these work as a “session” identification and – again – server knows what user matches the token.
        Token is trustworthy because you got it from the backend based on some authentication procedure (could be username/password). Nobody else can forge your token easily – here the problem is the same like getting sessionId for session-based communication.
        This does not consider MiM attacks and similar, from which you have to protect your application on different level anyway – and this is completely out of scope of the post.
        BTW: Session nicely shows that cookies or URL params (or headers) – it just doesn’t matter where you put the “token”, you just have to send it with every request that requires to be authenticated. Whatever works for you. I don’t like cookies that much, but if you want your login to survive browser restart, they may be handy. Headers of AJAX requests set by JavaScript are less messed with by browser (it doesn’t store them), so I prefer these. But for longer sessions cookies can be good (of course, set cookie timeout).

  12. Michal Aron says:

    Thank you for explanation. Looks like stateless authentication is better.. there is nice article which might help others which one to choose for similar scenario as mine (https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/). Going to implement it using your example 🙂

  13. Hi virgo47, Help me understand Spring base64 encode and decode. When i decoded token in checkBasicAuthorization function then it return wrong result for loginPassword. I think it caused by generated token randomly ?.

    • virgo47 says:

      Hi, I don’t understand where is the problem, because it works OK here. I had some troubles to make the whole project run again – so I upgraded it to Spring Boot 1.3 which moved me to Spring Security 4.x as well. Now some parts don’t work properly (need to fix ignored annotations, etc.), but the filter itself is working fine and provided test.sh can “log in” using curl – no problem there. So basic authentication must work.

      • Hi virgo47, This error occur when I using Authorization header follow below format:
        “Authorization: Basic $X_AUTH_TOKEN”
        It will be called checkBasicAuthorization function. I think after decode loginPassword is “$username:$password”. But it return wrong result. Please help me check this funtion.

      • virgo47 says:

        Please, you have to understand that I cannot investigate problems like this. I can’t even reproduce it and you provided little specific information anyway. When you find specific problem with my sources you can file an Issue/bug on Github and I may look at it. I’m answering questions if I know the answer right away or I can quickly find it out. But I cannot investigate problems specific to a code I don’t know at all and cannot reproduce. Also realize, that this is just a demo, not a library or any pre-baked solution ready to be used.

  14. hi virgo47,
    How can i access UserContext/UserDetails from SecurityContextHolder?
    I tried UserContext userContext= (UserContext)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    but got java.lang.ClassCastException.

    Thank you.

    • virgo47 says:

      You’ll get what you put there. There are places in my example, where I put UserDetails there, e.g.:

      Authentication securityToken = new PreAuthenticatedAuthenticationToken(
      	userDetails, null, userDetails.getAuthorities());
      SecurityContextHolder.getContext().setAuthentication(securityToken);
      

      I do that when I evaluate token in AuthenticationService (not derived from Spring) which I use in TokenAuthenticationFilter (derived from Spring’s GenericFilterBean and part of my security filter chain). They may be other ways how to do it automagically but you have to somehow provide it before you get to the security/business code, e.g. in the filter. I cannot help you more, unless you ask really specific question about the project. Also, use debugger to find out what is happening, what class you get, etc. I always debug, Spring code is quite readable.

      • Thx for your reply, i want to get user information which is from table instead username/password example address information. so i added function User getUser(){return this.user} in UserContext and i want to get that info.

      • virgo47 says:

        As I said before, I cannot help you with your code. I highly recommend Spring Security 3.1 book from Packt, after reading just first four chapters you’ll probably know exactly what to do with your application. “Instant solutions” really don’t help you, explanations in the book were very beneficial for me.

  15. Pingback: Autenticación web y API con Spring Security | Cleventy

  16. M J says:

    Hi there,
    Thanks for this post !! My app currently uses AD/LDAP authentication. I’m yet to make it SSO-enabled for intranet users. I’m looking for a sample where I could see Waffle in action. Could you provide me some pointers to working samples ?
    Thanks,
    M

  17. Great article, thank you

  18. Mark says:

    Great Stuff, one question. Why should I use token based security instead of basic authentication or diggest. Can you explain me what the advantages are?

    • virgo47 says:

      You still need to get the token somehow – so you need to login. How to login – that’s the question. Demo supports basic and digest (IIRC), we actually use login form sending login/password in the POST. These are two different things: 1) authenticate somehow and backend will give you a token, 2) use the token in following requests.

      It may be confusing, but this is actually not about the process of authenticating. All these troubles are still up to you to solve. I just showed some design how to put this into Spring Security in the context of HTTP API (let’s not tease Fielding with using the R-word) and how to generate random token. I don’t believe in tokens embedding login/session info, I’m not an expert here, but we heard about some vulnerabilities using them. So we need to track the session on the server (be it DB, or something stateful on the app-server) but we’re not using HTTP sessions, but tokens instead. Well, we might as well use the token in the session ID cookie, really. Just use random token.

      We still need to protect the connection (HTTPS) and not giving out our token (which may be invalidated, but still is critical for the security).

  19. Anonymous says:

    Virgo, I’m wondering about one thing, what would be the difference if I allow requests to /login and do the login logic in my Controller/Service and keep my CustomAuthFilter only to handle requests that have a token header? It’s a bit different than your design, letting the filter only auth requests with tokens. Would there by any security risks with such design? Thanks for the quality article.

    • I see no problem excluding login controller/service requests from authentication chain, functionally it’s pretty much equivalent solution. I even though about it as it pollutes the filter less. There still will be logout logic though (if supported). I don’t see any security risks assuming you configure Spring Security properly. Being rest API it should be still easy to test, even with CURL, as I did in test.sh or in project README.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s