Oauth2
Hãy đi sâu vào OAuth2 trong bối cảnh bảo mật ứng dụng và cách Spring Security hỗ trợ nó. Tôi sẽ giải thích các vai trò (Resource Owner, Client, Authorization Server, Resource Server), các loại Grant Types (Authorization Code, Implicit, Password, Client Credentials), và vai trò của Refresh Token cùng Access Token.
1. Các vai trò trong OAuth2
OAuth2 định nghĩa bốn vai trò chính trong luồng xác thực và phân quyền:
a. Resource Owner
Định nghĩa: Là người sở hữu tài nguyên (dữ liệu) được bảo vệ, thường là người dùng cuối (end-user).
Vai trò: Cấp quyền cho ứng dụng (Client) truy cập tài nguyên của họ thông qua Authorization Server.
Ví dụ: Bạn (người dùng) cho phép ứng dụng bên thứ ba (như một app ghi chú) truy cập Google Drive của bạn.
b. Client
Định nghĩa: Là ứng dụng hoặc dịch vụ muốn truy cập tài nguyên của Resource Owner.
Vai trò: Gửi yêu cầu đến Authorization Server để lấy token, sau đó dùng token để truy cập Resource Server.
Loại Client:
Confidential Client: Có thể giữ bí mật (client secret), như ứng dụng server-side.
Public Client: Không giữ bí mật, như ứng dụng mobile hoặc SPA (Single Page Application).
Ví dụ: Một ứng dụng web cần đọc email của bạn từ Gmail.
c. Authorization Server
Định nghĩa: Server chịu trách nhiệm xác thực Resource Owner và cấp token (Access Token, Refresh Token) cho Client.
Vai trò: Xác minh danh tính người dùng, cấp quyền, và phát hành token.
Ví dụ: Google, Keycloak, Okta là các Authorization Server phổ biến.
d. Resource Server
Định nghĩa: Server lưu trữ tài nguyên được bảo vệ (API, dữ liệu) và chỉ chấp nhận truy cập với token hợp lệ.
Vai trò: Xác minh Access Token từ Client trước khi trả về tài nguyên.
Ví dụ: API của Gmail (nơi lưu email của bạn).
Luồng cơ bản:
2. Grant Types trong OAuth2
Grant Type là cách Client lấy Access Token từ Authorization Server. Dưới đây là bốn loại chính:
a. Authorization Code
Mô tả:
Client (thường là ứng dụng web) yêu cầu Resource Owner cấp quyền thông qua Authorization Server, nhận mã code, sau đó đổi code lấy Access Token.
Luồng:
Client chuyển hướng người dùng đến Authorization Server (với
client_id
,redirect_uri
).Người dùng đăng nhập và đồng ý cấp quyền.
Authorization Server trả về mã code qua
redirect_uri
.Client gửi code +
client_secret
đến Authorization Server để lấy Access Token.
Ưu điểm: An toàn vì token không được gửi trực tiếp qua trình duyệt.
Ứng dụng: Web app server-side.
Trong Spring Security:
Cấu hình Client:
application.properties
:
b. Implicit
Mô tả:
Client (thường là SPA hoặc ứng dụng không có backend) nhận Access Token trực tiếp từ Authorization Server mà không qua bước code.
Luồng:
Client chuyển hướng người dùng đến Authorization Server.
Sau khi người dùng đồng ý, token được gửi về qua
redirect_uri
(trong fragment URL:#access_token=...
).
Ưu điểm: Đơn giản, không cần backend.
Nhược điểm: Token lộ qua trình duyệt, kém an toàn hơn.
Ứng dụng: SPA, ứng dụng không giữ được secret.
Trong Spring Security: Ít được dùng trực tiếp, thường thay bằng Authorization Code với PKCE (xem bên dưới).
c. Password (Resource Owner Password Credentials)
Mô tả:
Client lấy username/password trực tiếp từ Resource Owner và gửi đến Authorization Server để nhận Access Token.
Luồng:
Client gửi
username
,password
,client_id
,client_secret
đến Authorization Server.Authorization Server trả về Access Token.
Ưu điểm: Đơn giản, không cần redirect.
Nhược điểm: Yêu cầu Client đáng tin cậy tuyệt đối (ít dùng trong ứng dụng hiện đại).
Ứng dụng: Ứng dụng nội bộ hoặc legacy.
Trong Spring Security:
Dùng với Resource Server hoặc custom logic, ít phổ biến trong Spring Boot.
d. Client Credentials
Mô tả:
Client dùng thông tin của chính nó (
client_id
,client_secret
) để lấy Access Token, không liên quan đến Resource Owner.
Luồng:
Client gửi
client_id
,client_secret
đến Authorization Server.Nhận Access Token để truy cập tài nguyên.
Ưu điểm: Phù hợp cho giao tiếp server-to-server.
Ứng dụng: Microservices, API không cần người dùng.
Trong Spring Security:
Cấu hình Resource Server:
PKCE (Proof Key for Code Exchange):
Là phần mở rộng của Authorization Code, tăng cường bảo mật cho Public Client (như mobile app) bằng cách thêm
code_verifier
vàcode_challenge
.
3. Refresh Token và Access Token
a. Access Token
Định nghĩa:
Là chuỗi (thường là JWT) được Client dùng để truy cập Resource Server.
Đặc điểm:
Có thời hạn ngắn (thường 5 phút - 1 giờ).
Mang thông tin quyền (scope) và danh tính (nếu là JWT).
Ví dụ:
b. Refresh Token
Định nghĩa:
Là chuỗi được dùng để lấy Access Token mới khi token cũ hết hạn, mà không cần người dùng đăng nhập lại.
Đặc điểm:
Thời hạn dài hơn Access Token (ngày, tuần, hoặc tháng).
Chỉ gửi đến Authorization Server, không dùng trực tiếp với Resource Server.
Luồng:
Client gửi Refresh Token đến Authorization Server (endpoint
/token
).Nhận Access Token mới (và đôi khi Refresh Token mới nếu được cấu hình).
Ví dụ:
Trong Spring Security
Client lấy token:
Spring Boot hỗ trợ thông qua
OAuth2AuthorizedClientService
.
Resource Server xác minh:
Refresh Token:
Spring Security không tự động xử lý refresh, cần gọi endpoint Authorization Server thủ công hoặc dùng thư viện như
RestTemplate
.
Tóm tắt
Vai trò:
Resource Owner: Người dùng sở hữu tài nguyên.
Client: Ứng dụng truy cập tài nguyên.
Authorization Server: Cấp token.
Resource Server: Bảo vệ tài nguyên.
Grant Types:
Authorization Code: An toàn cho web app.
Implicit: Đơn giản cho SPA (ít dùng).
Password: Legacy, ít an toàn.
Client Credentials: Server-to-server.
Refresh Token và Access Token:
Access Token: Ngắn hạn, truy cập tài nguyên.
Refresh Token: Dài hạn, làm mới Access Token.
Last updated