Stateless Spring Security Part 3: JWT + Social Authentication

This third and final part in my Stateless Spring Security series is about mixing previous post about JWT token based authentication with spring-social-security. This post directly builds upon it and focusses mostly on the changed parts. The idea is to substitude the username/password based login with “Login with Facebook” functionality based on OAuth 2, but still use the same token based authentication after that.

Login flow


The user clicks on the “Login with Facebook” button which is a simple link to “/auth/facebook”, the SocialAuthenticationFilter notices the lack of additional query parameters and triggers a redirect leading the user of your site to Facebook. They login with their username/password and are redirected back, again to “/auth/facebook” but this time with “?code=…&state=…” parameters specified. (If the user previously logged in at facebook and had a cookie set, facebook will even instantly redirect back and no facebook screen is shown at all to the user.) The fun part is that you can follow this in a browsers network log as it’s all done using plain HTTP 302 redirects. (The “Location” header in the HTTP response is used to tell the browser where to go next)


After the redirect from facebook to “/auth/facebook?code=…&state=…” the SocialAuthenticationFilter now sees the proper parameters and will trigger two server calls to facebook. The first is to acquire an Access Token for the logged in user, the second is test if the whole process was succesful by acquiring user details using the access token. After this is all done the user is considered to be logged in and he can be redirected back to the root of the application using yet another 302 redirect (to “/”).


Some words on Spring Social

Spring Social is a complete framework for dealing with social networks and has a scope far beyond a mere login scenario. Apart from the different social network adapters, there is also a small integration library called Spring Social Security that implements the social authentication use-cases in such a way that it integrates better with Spring Security. It comes with an SocialAuthenticationFilter that maps to “/auth”, this is what we’ll use.

So setting up social authentication requires configuring Spring Social itself as well as Spring Security using the neat little Spring Social Security library.

Spring Social

Configuring it basically involves extending the SocialConfigurerAdapter. First you tell it what social networks to support:

It also needs to know how to acquire the user id for current user:

Finally it needs a UsersConnectionRepository. Which is basically in charge of the relation between a user and his connections to a social network. Spring Social comes with two implementations of its own (jdbc or in-memory). I choose to roll my own as I wanted to re-use my Spring Data JPA based UserDetailsService.

Spring Security

As in last blog post, configuring it basically involves extending the WebSecurityConfigurerAdapter. Apart from the usual stuff like configuring and exposing an AuthenticationManager and UserDetailsService, it now needs to configure and plug-in the SocialAuthenticationFilter. This basically involves very little code as the SpringSocialConfigurer does most of the work. It could be as simple as:

Considering I wanted to plug-in the Token based authentication, my own succesHandler and userIdSource; I had to make some configuration changes:

If you wanted to you could also subclass the SpringSocialConfigurer and provide a more elegant setter for a custom successHandler…

Past the Boilerplate (kudos to you for making it here)

It’s now time to focus on some of the more interesting bits.

Right after an initial successful connection to facebook is established a custom ConnectionSignUp is triggered:

As you can see my version simply persists the user with its connection data as a single JPA object. Purposely supporting only one-to-one relations between a user and an identity on facebook.

Note that I ended up excluding the connection properties from the actual token generated from the user. Just like I previously excluded the password field (which is no longer part of the User object at all):

Going this route does mean that any call to the facebook API needs a database query for the additional connection fields. More on this later on.

Right after the user is authenticated the custom AuthenticationSuccessHandler is triggered:

This looks a lot like the code from previous blog post but I had to make some changes in the TokenAuthenticationService. Because the client is loaded after a redirect, to preserve the token on the client-side until then, it must be send to client as a cookie:

This ends up being part of the final redirect response looking like this:


The final redirect back to the client after succesful login

The last and best part is of course where all code comes together to form a pretty sweet API. Because Spring Social already takes care of creating a user specific request-scoped ConnectionRepository, a connection specific API of it can be created by adding the following bean code to the SocialConfigurerAdapter:

This user specific facebook bean can be used in a controller like so:

client-side implementation

As mentioned the token is now passed to the client as a Cookie. However just like previous time, the server-side still only accepts tokens send into a special HTTP header. Granted that this is pretty arbitrary and you could have it simply accept the cookie. I prefer it not to as it prevents CSRF attacks. (Because the browser can’t be instructed to automatically add the proper authentication token to a request.)

So before retrieving the current user details the init method of the front-end now first tries to move the cookie to local storage:

The placement of the custom HTTP header is handled in a the same http interceptor as last time.

The actual “Login with Facebook” button is just a link to trigger the whole redirect frenzy:

To check if the actual Facebook API works, I’ve included another button to display the user details from facebook after login.

Final words (of advice)

It’s been quite a ride to integrate my custom version of JWT with social authentication. Some parts were less than trivial. Like finding a good balance between offloading database calls to JWT tokens. Ultimately I choose not to share facebook’s access token with the client as it’s only needed when using Facebook’s API. This means that any query to Facebook requires a database call to fetch the token. In fact it means that any REST API call to any controller that has an @Autowired Facebook service results in an eagerly fetched access token as part of the request-scoped bean creation. This is however easily mitigated by using a dedicated controller for facebook calls, but definitely something to be aware of.

If you plan on actually using this code and making Facebook API calls, make sure your JWT token expires before the facebook token does (currently valid for 60ish days). Better yet implement a forced re-login when you detect a failure as any re-login will automatically store the newly acquired facebook token in the database.

You can find a complete working example at github. Details on how to run it can be found there as well. I’ve included both maven and gradle build files.

5 thoughts on “Stateless Spring Security Part 3: JWT + Social Authentication

  1. Thanks for the post.

    I made several adjustments to support LinkedIn instead of Facebook.

    I run the application and got the following exception when calling /auth/linkedin An Authentication object was not found in the SecurityContext$VirtualFilterChain.doFilter($VirtualFilterChain.doFilter($VirtualFilterChain.doFilter(

    • Are you sure that the /auth/** endpoint is configured to permit all?

      Furthermore you seem to have a BasicAuthenticationFilter filter configured. Maybe this could be removed?

  2. Hi, thanks for the code everything works fine, but I can’t really figure out how to proceed with disconnecting the provider? I have added the ConnectController bean which provides the endpoints, but at some point the getUserId() from UserAuthenticationUserIdSource gives back anonymous user and ends up with exception. Any ideas?

  3. Pingback: Stateless Spring Securiy w/ Spring Social | 我爱源码网

  4. Hi, if by any chance you are readin this, I would have a question how would would explicit signup look like using restful solution? If ConnectionSignUp interface isn’t implemented then Spring Social filters automatically want to redirect to /signup or whatever url you specify via 302. Also angular or javascript cannot handle any 302 requests so I don’t see any way to intercept that redirect and for example route client to registration page. Thanks!