Configuring Google as OAuth2 authorization provider in Spring Boot

Recently we have decided to give modern look and feel of our product wish.dreamix – a collective fundraising HR tool allowing employees in a company to improve the surrounding work environment. We know UI and UX of a web platform is a must have feature and led by the desire of RAD (Rapid Application Development) we […]

by Boyko Dimitrov

July 28, 2015

4 min read

cropped logo springbypivotal horizontal1 645x300 1 - Configuring Google as OAuth2 authorization provider in Spring Boot

Recently we have decided to give modern look and feel of our product wish.dreamix – a collective fundraising HR tool allowing employees in a company to improve the surrounding work environment. We know UI and UX of a web platform is a must have feature and led by the desire of RAD (Rapid Application Development) we have chosen a technology stack which consists of AngularJS + Material Design for the Front-End and Spring Boot for the Back-End.

As the title of the blog describes we are going to focus on the back-end and specifically authentication and authorization of resources with OAuth2 protocol using Spring Boot. If you want to get more familiar with how Spring Boot uses the OAuth2 check this very interesting blog post from @david_syer – Senior Engineering Consultant at Pivotal. There are many articles, describing how to achieve this type of security, but configuring the framework to work with Google as authorization provider is not so straightforward due to Bearer Token header authorization request issue. I will describe how to solve it later in the article, but first let’s set up the global picture.

I assume you have already prepared a Spring Boot application project. If not, you can use http://start.spring.io/ which is very convenient web tool to initialize a project with multiple checkboxes representing different dependencies. If you are heading to use this approach make sure to include OAuth2 and Cloud Security from the Cloud dependencies. If you are setting up the project manually and you are using Maven as a build tool, make sure your pom file includes the following lines:

[html]
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.0.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-security</artifactId>
<version>1.0.2.RELEASE</version>
</dependency>
[/html]

 

At the time I am writing this blog post these are the latest versions of the libraries.

Spring Security OAuth2 provides standard Spring and Spring Security programming models and configuration idioms for using OAuth2 protocol. Spring Cloud Security in combination with Spring Security OAuth2 will allow us to quickly create an application that implement common patterns like single sign on, token relay and token exchange.

As I said at the beginning of the blog post we have chosen Spring Boot framework, because we wanted to rebuild our product fast and in the same time to make it stable and easy to scale. Just with one annotation and a small amount of configuration we can add SSO feature to our project. Here is our main application class:

[html]
package eu.dreamix;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.security.oauth2.sso.EnableOAuth2Sso;

@SpringBootApplication
@EnableOAuth2Sso
public class WishApplication {

public static void main(String[] args) {
SpringApplication.run(WishApplication.class, args);
}
}

The configured application.yml file:

spring:
oauth2:
client:
clientId: 123
clientSecret: xxx
accessTokenUri: https://www.googleapis.com/oauth2/v3/token
userAuthorizationUri: https://accounts.google.com/o/oauth2/auth
clientAuthenticationScheme: query
scope: profile email
resource:
userInfoUri: https://www.googleapis.com/plus/v1/people/me
preferTokenInfo: false
[/html]

+

[html]
package eu.dreamix.configuration;

import org.springframework.http.client.ClientHttpRequest;
import org.springframework.security.oauth2.client.DefaultOAuth2RequestAuthenticator;
import org.springframework.security.oauth2.client.OAuth2ClientContext;
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
import org.springframework.security.oauth2.common.OAuth2AccessToken;

public class GoogleOAuth2Authenticator extends DefaultOAuth2RequestAuthenticator {

@Override
public void authenticate(OAuth2ProtectedResourceDetails resource,
OAuth2ClientContext clientContext, ClientHttpRequest request) {
OAuth2AccessToken accessToken = clientContext.getAccessToken();
String tokenType = OAuth2AccessToken.BEARER_TYPE;
request.getHeaders().set("Authorization", String.format("%s %s", tokenType, accessToken.getValue()));
}
}
[/html]

Second, create a class which implements UserInfoRestTemplateCustomizer:

[html]
package eu.dreamix.configuration;
import org.springframework.cloud.security.oauth2.resource.UserInfoRestTemplateCustomizer;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;

public class CustomOAuth2RestTemplate implements UserInfoRestTemplateCustomizer {

@Override
public void customize(OAuth2RestTemplate template) {
// TODO Auto-generated method stub
template.setAuthenticator(new GoogleOAuth2Authenticator());
}
}
[/html]

Finally, create an instance of the CustomOAuth2RestTemplate in your main application class:

[html]
package eu.dreamix;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.security.oauth2.sso.EnableOAuth2Sso;

import eu.dreamix.configuration.CustomOAuth2RestTemplate;

@SpringBootApplication
@EnableOAuth2Sso
public class WishApplication {

UserInfoRestTemplateCustomizer customOauth2Template = new CustomOAuth2RestTemplate;

public static void main(String[] args) {
SpringApplication.run(WishApplication.class, args);
}
}
[/html]

As a conclusion, I want to say that if you need fast time-to-market withĐľut compromising the quality and in the same time easy maintainability and scalability, you should consider the usage of Spring Boot.

I expect your questions in the comments below. What do you think  about this method and the mentioned tool?

Java Developer at Dreamix