Spring Boot OAuth2 Part 2 – Fetching and using the Access Token
NỘI DUNG BÀI VIẾT
Trong bài hướng dẫn trước, chúng ta đã học OAuth2 – Getting the Authorization Code.
Trong hướng dẫn này, chúng ta sẽ xem cách sử dụng Authorization code để lấy thông báo truy cập và sau đó lấy dữ liệu JSON bằng mã thông báo truy cập. Trong phần hướng dẫn trước, mình đã thực hiện như sau:
- Resource Owner sẽ yêu cầu Client Application lấy một số dữ liệu từ Resource Server.
- Resource Server yêu cầu Resource Owner xác thực chính nó và cho phép chia sẻ dữ liệu.
- Sau khi xác thực thành công, Resource Server chia sẻ mã ủy quyền với client application.
Trong hướng dẫn tiếp theo, chúng ta sẽ thực hiện các bước sau:
- Client Application sử dụng mã ủy quyền và Secret key yêu cầu Access Token từ Resource Server.
- Resource Server chia sẻ Access Token cùng với Client Application.
- Sử dụng Access Token được chia sẻ Client Application hiện có thể nhận dữ liệu JSOn cần thiết từ Resource Server.
Getting the Access Token
Để nhận được mã thông báo truy cập từ máy chủ tài nguyên, các thay đổi chỉ được yêu cầu ở phần cuối của Client Application. Trong hướng dẫn trước, mình đã triển khai mã ủy quyền từ Resource Server.
Sử dụng Authorization Code(mã ủy quyền) nhạn được từ Resource Server, chúng ta có thể nhận được access token.
Như đã thấy Authorization Code được nhận dưới dạng request parameter. Và resource server đang cố gắng liên hệ với ứng dụng Client Application bằng cáh điều hướng uri(Uniform Resource Identifier). Vì vậy chúng ta viết 1 Controller để lấy Authorization code như 1 request parameter. Sau đó dùng authorization code này chúng ta lấy được 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;
}
}
Code language: JavaScript (javascript)
Khởi động Client Application và Resource Server. Truy cập localhost:8090/getEmployees và làm theo các bước tương tự như bài viết trước.
Chúng ta có thể thấy rằng Client application đang nhận được accestoken như response.
Sử dụng Access Token để lấy dữ liệu JSON.
Resource Server Changes
Trong module Resource Server chúng ta thêm 1 class configuration. Clas này cho pháp bất cứ request nào có phạm vi và access token truy cập hợp lệ để lấy tài nguyên được yêu cầu. Chúng ta sử dụng điều này để cấu hình các quy tắc truy cập cho các tài nguyên an toàn.
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')");
}
}
Code language: JavaScript (javascript)
Spring Security duy trì một chuỗi bộ lọc trong nội bộ nơi mỗi bọ lọc có trách nhiệm cụ thể và các bộ lọc được thêm vào hoặc xóa khỏi cấu hình tùy thuộc vào dịch vụ nào được yêu cầu. Thứ tự của các bộ lọc rất quan trọng vì có sự phụ thuộc giữa chúng. Nếu sử dụng Spring 1.5 trở lên có vấn đề về ResourceServerProperties issue. Tiếp theo trong tệp thuộc tính, hãy thêm:
security.oauth2.resource.filter-order = 3
Client Application Changes
Employee.java
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 + "]";
}
}
Code language: JavaScript (javascript)
EmployeeController.java
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;
}
}
Code language: JavaScript (javascript)
showEmployees.jsp
<%@ 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>
Code language: HTML, XML (xml)
Tiếp theo, khởi động boot-resource-server và boot-client-application. Truy cập localhost:8090/getEmployees.
Nhập thông tin đăng nhập là ‘javainuse’ và ‘javainuse’
Cho phép Resource Owner chia sẻ dữ liệu.
Chúng ta thấy dữ liệu json như sau.
Nguồn:
https://www.javainuse.com/spring/spring-boot-oauth-access-token
Leave a Reply