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. Spring Boot + OAuth 2 Client Credentials Grant - Hello World Example. Spring Boot + OAuth 2 Password Grant - Hello World Example. Facebook Authentication Using Spring Boot + Spring Social Simple Example.
This tutorial is explained in the below Youtube Video.
- 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 < ResponseEntityresponse = 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 request = new HttpEntity(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
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 + "]"; >>
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 < ResponseEntityresponse = 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 request = new HttpEntity(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 entity = new HttpEntity<>(headers1); ResponseEntityemployees = 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; > >
Show All Employees
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 ‘javainuse’ and ‘javainuse’
Authorize the Resource Owner to share the data
We see the json data as follows.