Hiện thực OAuth Authorization Server sử dụng Spring Authorization Server

Authorization Server trong OAuth có nhiệm vụ issue access token cho phép Client Application có thể sử dụng access token này để request tới resource mà nó cần sử dụng. Resource server sẽ validate access token này với Authorization Server mỗi khi Client Application request tới resource để quyết định có cho phép Client Application access tới resource mà nó muốn này không? Các bạn có thể sử dụng nhiều open source khác như Keycloak, Spring Security OAuth (đã deprecated) hay một project mới của Spring là Spring Authorization Server để hiện thực Authorization Server này. Trong bài viết này, mình sẽ hướng dẫn các bạn cách sử dụng Spring Authorization Server để hiện thực OAuth Authorization Server các bạn nhé!

Đầu tiên, mình sẽ tạo mới project Spring Boot project với Spring Web Starter, Spring Security Starter và OAuth2 Authorization Server Starter:

để làm ví dụ.

Kết quả:

Với cơ chế auto-configuration, hiện tại thì Spring Boot đã hỗ trợ cho Spring Authorization Server nên các bạn chỉ cần cấu hình một số thông tin bắt buộc như thông tin Client Application, thông tin user là có thể up và running một Authorization Server với Spring Authorization Server rồi.

Trong bài viết này, mình sẽ không sử dụng cơ chế auto-configuration này của Spring Boot các bạn nhé!

Cấu hình Authorization Server

Đầu tiên, mình sẽ tạo mới một class AuthorizationServerConfiguration để cấu hình cho Authorization Server.

Mặc định thì Spring Authorization Server hỗ trợ class OAuth2AuthorizationServerConfiguration với các cấu hình mặc định cho một Authorization Server. Nếu các bạn take a look vào code của class này, các bạn sẽ thấy nó có định nghĩa một phương thức applyDefaultSecurity() khởi tạo đối tượng OAuth2AuthorizationServerConfigurer với mục đích apply những cấu hình mặc định mà class OAuth2AuthorizationServerConfigurer này định nghĩa:

Như các bạn thấy, phương thức applyDefaultSecurity() định nghĩa security cho những endpoint mặc định của một Authorization Server.

Class OAuth2AuthorizationServerConfiguration còn định nghĩa một bean cho class SecurityFilterChain gọi tới phương thức applyDefaultSecurity() để đăng ký những cấu hình mặc định này với Spring Security của Authorization Server.

Các bạn có thể import class OAuth2AuthorizationServerConfiguration này sử dụng annotation @Import của Spring để sử dụng những cấu hình mặc định này:

hoặc nếu muốn add thêm custom code gì đó thì hãy khai báo một bean cho class SecurityFilterChain và gọi tới phương thức applyDefaultSecurity() như mình như sau:

Ở đây, mình add thêm code để nếu user không có permission request tới các endpoint mặc định của Authorization Server, Authorization Server sẽ redirect tới trang login.

Với một Authorization Server, một điều quan trọng mà chúng ta cần phải làm là định nghĩa JSON Web Key để verify thông tin trong access token mà user request tới Resource Server có phải do Authorization Server issue không? Bean JwtDecoder với đối tượng của class JWKSource được yêu cầu để hoàn thành phần cấu hình của Authorization Server này. Chúng ta có thể định nghĩa bean cho những đối tượng này như sau:

Các bạn cũng cần khai báo thêm một bean của class AuthorizationServerSettings để hoàn thành việc cấu hình thông tin cho Authorization Server. 

Class AuthorizationServerSettings cho phép chúng ta custom các cấu hình mặc định của Spring Authorization Server liên quan đến Issuer Identifier, JWK Set endpoint, và một số settings khác nữa. Các bạn có thể cấu hình bean cho class AuthorizationServerSettings như sau:

Cấu hình Spring Security

Khi Authorization Server redirect tới trang login do user chưa authenticated, chúng ta cần định nghĩa một SecurityFilterChain khác để handle request này và tất cả những request khác nữa của Authorization Server. Bởi vì class OAuth2AuthorizationServerConfiguration chỉ định nghĩa security cho những endpoint mặc định của Authorization Server.

Chúng ta có thể định nghĩa SecurityFilterChain này như sau:

Lúc này, trang login sẽ hiển thị nếu user chưa đăng nhập.

Đăng ký client với Authorization Server

Spring Authorization Server sử dụng class RegisteredClient để khai báo thông tin của một client đăng ký với Authorization Server và sử dụng implementation của interface RegisteredClientRepository để lưu thông tin của tất cả các client này.

Chúng ta có thể khai báo thông tin client sử dụng memory hoặc một database nào đó:

Để đơn giản, mình sẽ sử dụng memory như sau:

Có mấy thuộc tính quan trọng của một client cần phải có là: client Id và authorization grant type được enable cho client Id này.

Client Id thì mình không cần phải giải thích nhỉ! Còn authorization grant type thì Spring Authorization Server support tất cả grant types của OAuth 2.

Client secret thì tuỳ theo client type mà chúng ta muốn định nghĩa, nếu client của chúng ta là confidential, xem thêm Các loại client types trong OAuth 2.0, thì client secret là bắt buộc các bạn nhé. Ở đây, các bạn cần khai báo cách mã hoá client secret bằng PasswordEncoder, nếu không muốn mã hoá với mục đích testing, chúng ta có thể sử dụng NoOpPasswordEncoder bằng cách khai báo “{noop}” ở đầu client secret như mình làm ở trên. Nhớ là chỉ cho mục đích testing thôi nha các bạn!

Client Authentication method cũng được yêu cầu nếu client của chúng ta là confidential, được khai báo để định nghĩa cách chúng ta authenticate với một số endpoint sử dụng client secret như thế nào?

Tuỳ theo grant type của client các bạn đang định nghĩa, một số thông tin required khác mà chúng ta cần phải khai báo. Ví dụ như trong trường hợp của mình thì mình đang định nghĩa một client với grant type authorization_code nên mình phải định nghĩa thêm redirect_uri. Ở đây, mình sẽ sử dụng công cụ https://oidcdebugger.com/ để lấy authorization code nên mình định nghĩa redirect_uri với giá trị https://oidcdebugger.com/debug như các bạn thấy.

Tuỳ theo nhu cầu, các bạn hãy định nghĩa thông tin client cho phù hợp nhé.

Đăng ký user với Authorization Server

Thông tin user đăng nhập vào Authorization Server, mình sử dụng memory với khai báo như sau:

OK, đến đây thì chúng ta đã hoàn thành những cấu hình cơ bản cho Authorization Server rồi.

Để kiểm tra kết quả, mình sẽ sử dụng công cụ https://oidcdebugger.com/ như mình có nói ở trên, với khai báo như sau:

Nhấn Send request trong trang này, các bạn sẽ thấy trang login của Authorization Server hiển thị như sau:

Hiện thực OAuth Authorization Server sử dụng Spring Authorization Server

Đăng nhập bằng thông tin mà chúng ta đã khai báo ở trên, các bạn sẽ thấy kết quả như sau:

Hiện thực OAuth Authorization Server sử dụng Spring Authorization Server

Sử dụng authorization code này cùng với client secret mà chúng ta đã khai báo, các bạn có thể lấy được access token cho client này như sau:

Hiện thực OAuth Authorization Server sử dụng Spring Authorization Server

8 thoughts on “Hiện thực OAuth Authorization Server sử dụng Spring Authorization Server

  1. anh ơi cho em hỏi em ấn send request thì nó thành công luôn không phải login nữa á mà khi lấy được code rồi điền trong postman thì nó báo 401 Unauthorized

  2. dạ em có build 1 cái client để soo qua server mà khi đăng nhập nó báo về lỗi là :
    This application has no explicit mapping for /error, so you are seeing this as a fallback.
    dạ cái này có phương pháp giải quyết nào ko ạ, em cảm ơn ạ

  3. Cho em hỏi là với OAuth2 grant_type = password thì có phải là mình gửi usernam/password cho server và server sẽ trả về access token phải ko ạ ?
    Spring Authorization Server có làm được tính năng này không ạ?
    Theo em hiểu thì grant_type = authorization_code thì sẽ ko phù hợp với đồ án kiểu sinh viên sử dụng mô hình microservices nho nhỏ của em. và grant_type = password thì sẽ phù hợp hơn đúng ko anh.
    Em search thì thấy code>grant_type = password có vẻ không được hỗ trợ Spring Authorization Server link=> https://stackoverflow.com/questions/71225713/spring-authorization-server-with-authorizationgranttype-password.
    Cảm ơn anh về bài viết này !

Add Comment