springBoot with oauth2

Secure SpringBoot Microservice Using OAuth2 with simple steps.


In this tutorial we will learn how can we secure our SpringBoot microservice so that only authenticate user can access it and that user can also perform only those operation for which he is authorized.

So to do this we will create two SpringBoot application

  • SpringBoot Service which will generate token
  • SpringBoot Microservice that can be used only by authenticated token.

Lets understand this by one Example.

For this do following steps.

Create token generation SpringBoot service.

  • In eclipse go to File -> New -> Maven Project and provide information. In our case we have given following information.Clink on Finish



  • Add following dependency in pom.xml file.you can use any latest version.

  •  	
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    	<modelVersion>4.0.0</modelVersion>
    	<groupId>com.example.preparationforinterview</groupId>
    	<artifactId>myOAuth2Service</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    	<name>myOAuth2Service</name>
    	<description>OAuth2 Service</description>
    	<properties>
    		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    		<java.version>1.8</java.version>
    	</properties>
    	<parent>
    		<groupId>org.springframework.boot</groupId>
    		<artifactId>spring-boot-starter-parent</artifactId>
    		<version>1.4.4.RELEASE</version>
    	</parent>
    	<dependencyManagement>
    		<dependencies>
    			<dependency>
    				<groupId>org.springframework.cloud</groupId>
    				<artifactId>spring-cloud-dependencies</artifactId>
    				<version>Camden.SR5</version>
    				<type>pom</type>
    				<scope>import</scope>
    			</dependency>
    		</dependencies>
    	</dependencyManagement>
    
    	<dependencies>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-web</artifactId>
    		</dependency>
    
    		<dependency>
    			<groupId>org.springframework.cloud</groupId>
    			<artifactId>spring-cloud-security</artifactId>
    		</dependency>
    
    		<dependency>
    			<groupId>org.springframework.security.oauth</groupId>
    			<artifactId>spring-security-oauth2</artifactId>
    		</dependency>
    	</dependencies>
    </project>
    
  • run mvn install.It will download all dependency
  • right click on src.main.java and create one package.for example com.example.preparationforinterview
  • Create one class for example Application and paste below code.
  • Copy below code in Application.

  •  	
    package com.example.preparationforinterview;
    
    import java.security.Principal;
    import java.util.HashMap;
    import java.util.Map;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.security.core.authority.AuthorityUtils;
    import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
    import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
    import org.springframework.security.oauth2.provider.OAuth2Authentication;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @SpringBootApplication
    @RestController
    @EnableResourceServer
    @EnableAuthorizationServer
    public class Application {
    	
    	private static final String USER = "user";
    	private static final String AUTHORITIES = "authorities";
    	
        @RequestMapping(value = { "/user" }, produces = "application/json")
        public Map<String, Object> user(Principal principal) {
            Map<String, Object> userInfo = new HashMap<>();
            OAuth2Authentication oAuth2Authentication = (OAuth2Authentication) principal;
            userInfo.put(USER, oAuth2Authentication.getUserAuthentication().getPrincipal());
            userInfo.put(AUTHORITIES, AuthorityUtils.authorityListToSet(oAuth2Authentication.getUserAuthentication().getAuthorities()));
            return userInfo;
        }
    
    	public static void main(String[] args) {
    		SpringApplication.run(Application.class, args);
    	}
    }
    

    Explain

    We have four annotation here

    • @SpringBootApplication : It will create application as spring boot application
    • @RestController : This annotation enables application for REST.
    • @EnableResourceServer : To inform that this service is going act OAuth2 service
    • @EnableAuthorizationServer : To inform that this service is going act OAuth2 service
  • Now right click on src.main.java and create one more package.for example com.example.preparationforinterview.rest and create two more classes.
  • UserConfiguration.java


     	
    package com.example.preparationforinterview.oauth2;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.authentication.AuthenticationManager;
    import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    import org.springframework.security.core.userdetails.UserDetailsService;
    
    @Configuration
    public class UserConfiguration extends WebSecurityConfigurerAdapter {
    	@Override
    	@Bean
    	public AuthenticationManager authenticationManagerBean() throws Exception {
    		return super.authenticationManagerBean();
    	}
    
    	@Override
    	@Bean
    	public UserDetailsService userDetailsServiceBean() throws Exception {
    		return super.userDetailsServiceBean();
    	}
    
    	@Override
    	protected void configure(AuthenticationManagerBuilder auth)
    			throws Exception {
    		auth.inMemoryAuthentication().withUser("user1")
    				.password("password1").roles("USER").and()
    				.withUser("user2").password("password2")
    				.roles("USER", "ADMIN");
    	}
    	
    }
    

    Explain

    In above class we configured configure() method and there we configured user credentials and their roles.Using credentials we will create token and based on role, user can perform specific action.

    OAuth2Configuration.java


     	
    package com.example.preparationforinterview.oauth2;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.authentication.AuthenticationManager;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
    import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
    import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
    
    @Configuration
    public class OAuth2Configuration extends AuthorizationServerConfigurerAdapter {
    
    	@Autowired
        private AuthenticationManager authenticationManager;
    
        @Autowired
        private UserDetailsService userDetailsService;
    
        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            clients.inMemory()
                    .withClient("serviceClient")
                    .secret("mySecretKey")
                    .authorizedGrantTypes("refresh_token", "password", "client_credentials")
                    .scopes("webclient");
        }
    
        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
          endpoints
            .authenticationManager(authenticationManager)
            .userDetailsService(userDetailsService);
        }
    }
    

    Explain

    In above class we configured configure() method with ClientDetailsServiceConfigurer as parameter and there we have registered client application with authorized service. In our example we are using in memory store.ClientDetailsServiceConfigurer supports two type of stores, in memory and JDBC.In withClient we provide client application name and in secret we give a password that will be used to generate token. In authorizedGrantTypes we have grant type supported by OAuth2 service.



  • Now right click on src.main.resources and create one property file, for example application.properties and add following entry


  •  	
    server.port=8080
    
    spring.application.name=oAuth2Servicve
    
    server.contextPath=/auth
    
    spring.profile.active=default
    

    Explain

    • server.port : port on which this RESt service will deploy.
    • spring.application.name : logical name of the service that will be registered with Eureka


  • At the end we have following structure


  • Now right click on Application and run.It will start server on 8080.
  • Now we will hit following URL with form parameter.
  • http://localhost:8080/auth/oauth/token
  • It will give following output.Save this access_token that will be used to call secure microservice.


  • If we hit user endpoint then we can get about user and its role but we need to pass bearer with access_token in header as shown below.


  • Now we will create one secure SpringBoot microservice and will access that service with token generated in Oauth2Service.This secure microservice will contact to OAuth2Servivce and validate the user and its role , after validation user can perform action based on its role.
  • To create a microservice we will follow below steps.
  • In eclipse go to File -> New -> Maven Project and provide information. In our case we have given following information.Clink on Finish



  • Add following dependency in pom.xml file.you can use any latest version.

  •  	
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    	<modelVersion>4.0.0</modelVersion>
    	<groupId>com.example.preparationforinterview</groupId>
    	<artifactId>SecureMicroservice</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    	<name>SecureMicroservice</name>
    	<description>Secure Microservice</description>
    	<parent>
    		<groupId>org.springframework.boot</groupId>
    		<artifactId>spring-boot-starter-parent</artifactId>
    		<version>1.5.2.RELEASE</version>
    		<relativePath />
    	</parent>
    	<properties>
    		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    		<java.version>1.8</java.version>
    	</properties>
    	<dependencyManagement>
    		<dependencies>
    			<dependency>
    				<groupId>org.springframework.cloud</groupId>
    				<artifactId>spring-cloud-dependencies</artifactId>
    				<version>Camden.SR5</version>
    				<type>pom</type>
    				<scope>import</scope>
    			</dependency>
    		</dependencies>
    	</dependencyManagement>
    	<dependencies>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-web</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.cloud</groupId>
    			<artifactId>spring-cloud-security</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.security.oauth</groupId>
    			<artifactId>spring-security-oauth2</artifactId>
    		</dependency>
    	</dependencies>
    </project>
    
  • run mvn install.It will download all dependency
  • right click on src.main.java and create one package.for example com.example.preparationforinterview
  • There we will create two classes as shown below.
  • First Create Application.java and paste below code
  • Application.java


     	
    package com.example.preparationforinterview;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    
    @SpringBootApplication
    @EnableResourceServer
    @RestController
    public class Application {
    
    	public static void main(String[] args) {
    		SpringApplication.run(Application.class, args);
    	}
    
    	@RequestMapping(value = "/api", method = RequestMethod.GET)
    	public String getMessage(@RequestParam("name") String name) {
    		return "Hello" + " " + name;
    	}
    
    	@RequestMapping(value = "/api", method = RequestMethod.PUT)
    	public void updateMessage() {
    		System.out.println("Message is updated");
    	}
    }
    

    Explain

    We have three annotation here

    • @SpringBootApplication : It will create application as spring boot application
    • @RestController : This annotation enables application for REST.
    • @EnableResourceServer : To inform that this service is going act OAuth2 service

    ServiceConfiguration.java


     	
    package com.example.preparationforinterview;
    
    import org.springframework.context.annotation.Configuration;
    import org.springframework.http.HttpMethod;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
    
    @Configuration
    public class ServiceConfiguration extends ResourceServerConfigurerAdapter {
    
    	@Override
    	public void configure(HttpSecurity http) throws Exception {
    		http.authorizeRequests()
    				.antMatchers(HttpMethod.PUT, "/api/**")
    				.hasRole("ADMIN").anyRequest().authenticated();
    	}
    }
    
    

    Explain

    In above class we configured configure() method and there we configured user that have ADMIN rights can operate put operation.



  • Now right click on src.main.resources and create one property file, for example application.properties and add following entry


  •  	
    server.port=8888
    
    management.security.enabled=false
    
    spring.application.name=secureMicroservice
    
    security.oauth2.resource.userInfoUri=http://localhost:8080/auth/user
    

    Explain

    • server.port : port on which this REST service will deploy.
    • spring.application.name : logical name of the service.
    • security.oauth2.resource.userInfoUri : This will be pointed to our myOAuth2Service..


  • At the end we have following structure


  • Now right click on Application and run.It will start server on 8888.
  • Now we will hit following URL with header Authorization and value will be bearer with token generated in myOAuth2Service.
  • http://localhost:8888/api



  • As above use has ADMIN role so he could update request but we created one more user which has only USER role.If we create token with that user and will try update request then we will get 403.Lets check with an example.

  • Again hit /token endpoint with another user which has only USER role



  • Now with this token try to update service



Download source code

OAuth Service
Secure Microservice



Visit Others Links

Spring Boot Introduction
Spring Boot Setup
REST API Example Using Spring Boot
Spring Boot REST API Test with Mock MVC Using standaloneSetup
Spring Boot REST API Test with Mock MVC Using webAppContextSetup
Spring Boot REST API Test with Embedded Server
Actuator In Spring Boot
Deployment Of Spring Boot In External Tomcat
Spring Boot with OAuth
Top Spring Boot Interview Question