Spring Boot OAuth2 Part 2 - Getting the Access Token and Using it to fetch data | JavaInUse




Spring Boot OAuth2 Part 2 - Fetching and using the Access Token

In previous tutorial we learnt OAuth2 - Getting the Authorization Code.
In this tutorial we will see how to use the authorization code to get the access token and then get the json data using the access token. We had in the previous tutorial done the following -
  • The Resource Owner will ask the Client Application to get some data from the Resource Server.
  • The Resource Server asks the Resource Owner to authenticate itself and as for authorization to share data.
  • After successful authentication the Resource Server shares an authorization code with the client application
In the next tutorial we will do the following flow -
  • The Client Application using the Authorization code and Secret key ask for the Access Token from the Resource Server.
  • The Resource Server shares the Access Token with the Client Application.
  • Using the shared Access Token the Client Application can now get the required JSON data from the Resource Server

Spring Boot Security - Implementing OAuth2

Spring Boot Security - Introduction to OAuth Spring Boot OAuth2 Part 1 - Getting The Authorization Code Spring Boot OAuth2 Part 2 - Getting The Access Token And Using it to fetch data.

Video

This tutorial is explained in the below Youtube Video.

Lets Begin?

  • Getting the Access Token


    For getting the access token from the resource server the changes are only required at the client application end.
    In a previous tutorial we had implemented code to get the Authorization code from the Resource Server.
    Using the Authorization Code received from the resource server we can get the access token.
    As can be seen the authorization code is received as a request parameter. And the resource server is trying to contact the client application using the redirect uri. So we will write a controller to get the Authorization code as a request parameter. Then using this authorization code we get the Access Token.
    package com.oauth.controllers;
    
    import java.io.IOException;
    import java.util.Arrays;
    
    import org.apache.commons.codec.binary.Base64;
    import org.springframework.http.HttpEntity;
    import org.springframework.http.HttpHeaders;
    import org.springframework.http.HttpMethod;
    import org.springframework.http.MediaType;
    import org.springframework.http.ResponseEntity;
    import org.springframework.stereotype.Controller;
    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.client.RestTemplate;
    import org.springframework.web.servlet.ModelAndView;
    
    import com.fasterxml.jackson.core.JsonProcessingException;
    
    @Controller
    public class EmployeeController {
    
    	@RequestMapping(value = "/getEmployees", method = RequestMethod.GET)
    	public ModelAndView getEmployeeInfo() {
    		return new ModelAndView("getEmployees");
    	}
    
    	@RequestMapping(value = "/showEmployees", method = RequestMethod.GET)
    	public ModelAndView showEmployees(@RequestParam("code") String code) throws JsonProcessingException, IOException {
    		ResponseEntity<String> response = null;
    		System.out.println("Authorization Code------" + code);
    
    		RestTemplate restTemplate = new RestTemplate();
    
    		// According OAuth documentation we need to send the client id and secret key in the header for authentication
    		String credentials = "javainuse:secret";
    		String encodedCredentials = new String(Base64.encodeBase64(credentials.getBytes()));
    
    		HttpHeaders headers = new HttpHeaders();
    		headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
    		headers.add("Authorization", "Basic " + encodedCredentials);
    
    		HttpEntity<String> request = new HttpEntity<String>(headers);
    
    		String access_token_url = "http://localhost:8080/oauth/token";
    		access_token_url += "?code=" + code;
    		access_token_url += "&grant_type=authorization_code";
    		access_token_url += "&redirect_uri=http://localhost:8090/showEmployees";
    
    		response = restTemplate.exchange(access_token_url, HttpMethod.POST, request, String.class);
    
    		System.out.println("Access Token Response ---------" + response.getBody());
    
    		return null;
    	}
    }
    
    Start the client application and the resource server. Go to localhost:8090/getEmployees and follow the same steps we followed in previous tutorials.
    We can see that the client application is getting the access token as response.
  • Using the Access Token to get the JSON data


    • Resource Server Changes
      In the Resource Server module we add a configuration class. This class allows any request with valid access token and scope to get the requested resource. We use this to configure the access rules for secure resources
      package com.javainuse.config;
      
      import org.springframework.context.annotation.Configuration;
      import org.springframework.security.config.annotation.web.builders.HttpSecurity;
      import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
      import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
      
      @Configuration
      @EnableResourceServer
      class ResourceServer extends ResourceServerConfigurerAdapter {
          //Here we specify to allow the request to the url /user/getEmployeesList with valid access token and scope read 
      	@Override
      	public void configure(HttpSecurity http) throws Exception {
      		http.requestMatchers().antMatchers("/user/getEmployeesList/**").and().authorizeRequests().anyRequest()
      				.access("#oauth2.hasScope('read')");
      	}
      }
      
      
      Spring Security maintains a filter chain internally where each of the filters has a particular responsibility and filters are added or removed from the configuration depending on which services are required. The ordering of the filters is important as there are dependencies between them. If using Spring 1.5 and above there is a ResourceServerProperties issue Next in the properties file add the following property
      security.oauth2.resource.filter-order = 3
      
    • Client Application Changes
      First create the domain class Employee in the client application, similar to the resource server module.
      package com.oauth.model;
      
      public class Employee {
      
          private String empId;
          private String empName;
      
          public String getEmpId() {
              return empId;
          }
      
          public void setEmpId(String empId) {
              this.empId = empId;
          }
      
          public String getEmpName() {
              return empName;
          }
      
          public void setEmpName(String empName) {
              this.empName = empName;
          }
      
          @Override
          public String toString() {
              return "Employee [empId=" + empId + ", empName=" + empName + "]";
          }
      
      }
      
      In the client application using the access token as validation call the url to get the JSON data.
      package com.oauth.controllers;
      
      import java.io.IOException;
      import java.util.Arrays;
      
      import org.apache.commons.codec.binary.Base64;
      import org.springframework.http.HttpEntity;
      import org.springframework.http.HttpHeaders;
      import org.springframework.http.HttpMethod;
      import org.springframework.http.MediaType;
      import org.springframework.http.ResponseEntity;
      import org.springframework.stereotype.Controller;
      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.client.RestTemplate;
      import org.springframework.web.servlet.ModelAndView;
      
      import com.fasterxml.jackson.core.JsonProcessingException;
      import com.fasterxml.jackson.databind.JsonNode;
      import com.fasterxml.jackson.databind.ObjectMapper;
      import com.oauth.model.Employee;
      
      
      @Controller
      public class EmployeeController {
      
      	@RequestMapping(value = "/getEmployees", method = RequestMethod.GET)
      	public ModelAndView getEmployeeInfo() {
      		return new ModelAndView("getEmployees");
      	}
      
      	@RequestMapping(value = "/showEmployees", method = RequestMethod.GET)
      	public ModelAndView showEmployees(@RequestParam("code") String code) throws JsonProcessingException, IOException {
      		ResponseEntity<String> response = null;
      		System.out.println("Authorization Ccode------" + code);
      
      		RestTemplate restTemplate = new RestTemplate();
      
      		String credentials = "javainuse:secret";
      		String encodedCredentials = new String(Base64.encodeBase64(credentials.getBytes()));
      
      		HttpHeaders headers = new HttpHeaders();
      		headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
      		headers.add("Authorization", "Basic " + encodedCredentials);
      
      		HttpEntity<String> request = new HttpEntity<String>(headers);
      
      		String access_token_url = "http://localhost:8080/oauth/token";
      		access_token_url += "?code=" + code;
      		access_token_url += "&grant_type=authorization_code";
      		access_token_url += "&redirect_uri=http://localhost:8090/showEmployees";
      
      		response = restTemplate.exchange(access_token_url, HttpMethod.POST, request, String.class);
      
      		System.out.println("Access Token Response ---------" + response.getBody());
      
      		// Get the Access Token From the recieved JSON response
      		ObjectMapper mapper = new ObjectMapper();
      		JsonNode node = mapper.readTree(response.getBody());
      		String token = node.path("access_token").asText();
      
      		String url = "http://localhost:8080/user/getEmployeesList";
      
      		// Use the access token for authentication
      		HttpHeaders headers1 = new HttpHeaders();
      		headers1.add("Authorization", "Bearer " + token);
      		HttpEntity<String> entity = new HttpEntity<>(headers1);
      
      		ResponseEntity<Employee[]> employees = restTemplate.exchange(url, HttpMethod.GET, entity, Employee[].class);
      		System.out.println(employees);
      		Employee[] employeeArray = employees.getBody();
      
      		ModelAndView model = new ModelAndView("showEmployees");
      		model.addObject("employees", Arrays.asList(employeeArray));
      		return model;
      	}
      }
      
      
      Next we will define the jsp named showEmployees to display the Employee info recieved.
      <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
      <%@page session="false"%>
      <html>
      <head>
      <title>Show Employees</title>
      </head>
      <body>
      
      	<h3 style="color: red;">Show All Employees</h3>
      	<ul>
      		<c:forEach var="listValue" items="">
      			<li></li>
      		</c:forEach>
      	</ul>
      </body>
      </html>
      
    Next start the boot-resource-server and the boot-client-application. Go to localhost:8090/getEmployees
    Click on Get Employee Info Button.
    Enter the credentials as 'admin' and 'admin'
    Authorize the Resource Owner to share the data
    We see the json data as follows.

Download Source Code

Download it -
Spring Boot OAuth - Client Application
Spring Boot OAuth - Resource Server