Google OAuth with Spring Security as separated Resource Server

There are a lot of great articles out there about OAuth 2.0, Spring Security, REST especially when you are about to have both the Resource and the Authorization server in the same application.

However, there are cases when you want to separate these. This is mainly true when you have microservices and the most straightforward way implementing these two is to use Spring Boot because what you need to do there is mostly configuration.

In this article, I’ll walk you through the implementation of a simple, secured resource server using Google OAuth (Implicit grant flow) with standard Spring. In case you are not familiar with OAuth, make sure you check it out before you continue reading.

First of all, let’s define the responsibilities. We will have a simple stateless backend with an endpoint which we want to secure with Google OAuth. The frontend can be any application which can consume the resources provided by the backend – for example an Angular application. The stateless nature of the backend is especially important when you are creating a REST backend as it’s a constraint. Stateless means that an incoming request have to contain all the necessary information for the server to send back a response. The consequence is that the client application have to send the access token to the backend when querying any resource and the server should validate whether the sent token is valid. This is done by going to the authorization server to a specific endpoint which validates the token.

An additional requirement for a real life application is to associate a google user with our user entity thus we need to query the user information from google (id, email, etc.). I’ll show you how you can create a custom Authentication object for this case.

Let’s start with a simple Spring MVC controller which defines one endpoint.

Now we want to secure all the endpoints – in this case only one – so we have the following configuration:

I’m not gonna go into every detail but what is important here is that we have the @EnableResourceServer annotation on the configuration class and we have the HTTP security configured. The first thing we have to do is to make the security stateless and the second thing is that we want to secure every endpoint on our server to be accessible for users which have USER role. Of course you can customize this and check whether a specific OAuth scope is present and so on.

The only thing left is to define a ResourceServerTokenServices bean. This is the place where you have to return an OAuth2Authentication object based on an access token which is passed in the request’s header.

For remote authorization server, you have the option to use Spring’s RemoteTokenServices class but as OAuth 2.0 is not specifying how to validate the access token with a remote authorization server, this implementation won’t fit in all the cases. Unfortunately the latter is the case for Google, but it’s not that complicated to implement on your own.

First of all, we have to create a custom ResourceServerTokenServices implementation, let’s call it GoogleTokenServices. There are 2 methods which you have to override, loadAuthentication and readAccessToken. For our case, only the first one is important.

Let’s go through the loadAuthentication method. First of all, according to Google, validating the token is a mandatory step so that’s what we have to do through an AccessTokenValidator. This is a custom interface I introduced. I’ll get back to the Google implementation of this class in a few lines below.

After we are certain that the token is ready for use – meaning it’s valid – we have to construct the OAuth2Authentication object. This is done by the getAuthentication method which basically uses a DefaultAccessTokenConverter to extract a basic OAuth2Authentication. This implementation is enough if you don’t want to have any information about the user which the token belongs to. If you want to have the Google userId, email of the token owner, you have to send another request to Google and this is how this implementation looks like. The getAuthenticationToken returns an Authentication object with a GooglePrincipal – custom class – which contains only the Google id of the user plus we are giving a default USER role. If you need for example the email of the Google user, you can put that info into the GooglePrincipal as well as any other necessary data.

Now let’s get back to our AccessTokenValidator.

This validator is written based on Google’s suggestion. That’s why we have a specialized ErrorHandler for the RestTemplate which checks for 400 status as it means that the token is expired, the permissions are revoked or something is not OK with the token. The core idea here is to check whether the returned JSON contains the application’s clientId as audiance or the token is intended to be used for other application.

The source can be found on GitHub. Feel free to reach me out in case of questions in the comments or on Twitter.

2 thoughts on “Google OAuth with Spring Security as separated Resource Server

  1. For some reason I end up with this error: Caused by: class path resource [app.yml] cannot be opened because it does not exist

    Any idea?

Leave a Reply

Your email address will not be published. Required fields are marked *