OAuth 2.0 là chuẩn ủy quyền cho phép một ứng dụng truy cập tài nguyên của người dùng thông qua token, thay vì yêu cầu ứng dụng đó biết mật khẩu của người dùng. Trong EzyLogin, OAuth 2.0 được triển khai theo hướng Authorization Code Flow: client chuyển người dùng tới EzyLogin để xác thực và cấp code, sau đó client đổi code lấy access_tokenrefresh_token, rồi dùng access_token để lấy thông tin người dùng.

Kiến trúc tổng quát

sequenceDiagram
    participant User as Người dùng
    participant Client as Ứng dụng client
    participant EzyLogin as EzyLogin
    participant Store as Dữ liệu OAuth

    Client->>EzyLogin: GET /oauth2/auth<br/>client_id, redirect_uri, scope, response_type, state
    EzyLogin->>EzyLogin: Kiểm tra đăng nhập người dùng
    EzyLogin->>Store: Kiểm tra client, redirect_uri, scope
    alt Client yêu cầu phê duyệt
        EzyLogin-->>User: Hiển thị trang phê duyệt
        User->>EzyLogin: POST /oauth2/auth/approve
    end
    EzyLogin->>Store: Tạo hoặc lấy authorization code
    EzyLogin-->>Client: Redirect về redirect_uri?code=...&state=...

    Client->>EzyLogin: POST /v1/oauth2/token<br/>grant_type=authorization_code
    EzyLogin->>Store: Kiểm tra client_secret, redirect_uri, code
    EzyLogin->>Store: Tạo hoặc lấy refresh_token và access_token
    EzyLogin-->>Client: access_token, refresh_token, expires_in, scope

    Client->>EzyLogin: GET /v1/oauth2/user<br/>Authorization: Bearer access_token
    EzyLogin->>Store: Kiểm tra access_token
    EzyLogin-->>Client: Thông tin người dùng theo scope

Luồng cấp authorization code

Client bắt đầu bằng cách redirect người dùng tới:
GET /oauth2/auth
Các tham số chính:
  • client_id: định danh client đã đăng ký trong EzyLogin.
  • redirect_uri: URL nhận kết quả sau khi cấp quyền.
  • scope: danh sách quyền client muốn truy cập.
  • response_type: kiểu phản hồi, thường là code.
  • state: giá trị client gửi kèm để chống giả mạo request và khôi phục trạng thái phía client.
  • user_locale: ngôn ngữ hoặc locale của người dùng nếu client truyền vào.
EzyLogin xử lý theo thứ tự:
  1. Yêu cầu người dùng đã đăng nhập.
  2. Kiểm tra client_id đang hoạt động.
  3. Nếu cấu hình client bắt buộc phê duyệt, chuyển người dùng tới trang approve.
  4. Kiểm tra scope, response_typeredirect_uri.
  5. Tạo hoặc lấy lại authorization code gắn với client và người dùng.
  6. Redirect về redirect_uri kèm codestate.
Ví dụ redirect sau khi thành công:
https://client.example.com/callback?code=AUTH_CODE&state=STATE

Luồng phê duyệt

flowchart TD
    A[Client gọi /oauth2/auth] --> B{Client có bắt buộc phê duyệt?}
    B -- Không --> C[Kiểm tra scope, response_type, redirect_uri]
    B -- Có --> D[Hiển thị trang /oauth2/auth/approve]
    D --> E[Người dùng bấm approve]
    E --> C
    C --> F[Tạo hoặc lấy authorization code]
    F --> G[Redirect về redirect_uri kèm code và state]
Khi approvalPrompt của client được cấu hình ở chế độ bắt buộc, EzyLogin không cấp code ngay. Thay vào đó, hệ thống render trang phê duyệt để người dùng xác nhận yêu cầu. Sau khi người dùng approve, EzyLogin mới tiếp tục kiểm tra request và cấp authorization code.

Luồng đổi token

Sau khi nhận được code, client gọi:
POST /v1/oauth2/token
Với grant_type=authorization_code, request cần các tham số:
  • client_id
  • client_secret
  • redirect_uri
  • code
  • grant_type
EzyLogin sẽ:
  1. Kiểm tra client_idclient_secret.
  2. Kiểm tra redirect_uri thuộc danh sách đã đăng ký.
  3. Kiểm tra grant_type.
  4. Với authorization_code, kiểm tra code có thuộc client hiện tại không.
  5. Tạo hoặc lấy refresh_token.
  6. Tạo hoặc lấy access_token.
  7. Trả về token dạng Bearer.
Response có dạng:
{
  "token_type": "Bearer",
  "access_token": "...",
  "refresh_token": "...",
  "expires_in": 3600,
  "scope": "profile email"
}

Luồng refresh token

sequenceDiagram
    participant Client as Ứng dụng client
    participant EzyLogin as EzyLogin
    participant Store as Dữ liệu OAuth

    Client->>EzyLogin: POST /v1/oauth2/token<br/>grant_type=refresh_token
    EzyLogin->>Store: Kiểm tra client_id, client_secret, redirect_uri
    EzyLogin->>Store: Kiểm tra refresh_token thuộc client
    EzyLogin->>Store: Tạo hoặc lấy access_token mới
    EzyLogin-->>Client: access_token, refresh_token, expires_in, scope
Với grant_type=refresh_token, client gửi refresh_token thay cho code. EzyLogin kiểm tra refresh token còn hợp lệ và thuộc đúng client, sau đó trả về access token để client tiếp tục gọi API.

Luồng lấy thông tin người dùng

Client gọi:
GET /v1/oauth2/user
Authorization: Bearer ACCESS_TOKEN
Request cũng yêu cầu client_secret. EzyLogin kiểm tra client secret, trích xuất access token từ header Authorization, xác thực token thuộc client tương ứng, sau đó trả về thông tin người dùng theo các scope mà client được cấp.

Các view

ViewMethodMục đích
/oauth2/authGETĐiểm bắt đầu luồng authorization code. Kiểm tra client và cấp code hoặc chuyển tới trang phê duyệt.
/oauth2/auth/approveGETHiển thị trang phê duyệt quyền truy cập OAuth 2.0.
/oauth2/auth/approvePOSTXử lý khi người dùng approve, sau đó cấp authorization code.
/oauth2/loginGETRedirect người dùng tới URL đăng nhập OAuth 2.0 của provider bên ngoài nếu có providerName.
/oauth20-client-idsGETTrang quản trị danh sách OAuth 2.0 client.
/oauth20-client-ids/addGETTrang thêm OAuth 2.0 client.
/oauth20-client-ids/{id}GETTrang chi tiết OAuth 2.0 client.
/oauth20-client-ids/{id}/editGETTrang chỉnh sửa OAuth 2.0 client.
/settings/oauth20GETTrang cấu hình OAuth 2.0 provider bên ngoài.

Các API

APIMethodMục đích
/v1/oauth2/tokenPOSTĐổi authorization code hoặc refresh token lấy access token.
/v1/oauth2/userGETLấy thông tin người dùng bằng Bearer access token.
/ezylogin/api/v1/{providerName}/oauth20-urlGETLấy URL đăng nhập OAuth 2.0 theo provider.
/api/v1/oauth20-client-idsGETLấy danh sách OAuth 2.0 client có phân trang và bộ lọc.
/api/v1/oauth20-client-ids/addPOSTTạo OAuth 2.0 client.
/api/v1/oauth20-client-ids/{id}PUTCập nhật OAuth 2.0 client.
/api/v1/oauth20-client-ids/{id}DELETEXóa OAuth 2.0 client và redirect URI liên quan.
/api/v1/settings/oauth20/savePUTLưu cấu hình OAuth 2.0 provider bên ngoài.

Điểm cần lưu ý

EzyLogin kiểm soát chặt các bước quan trọng của OAuth 2.0: client phải hợp lệ, client_secret phải đúng khi đổi token, redirect_uri phải nằm trong danh sách đã đăng ký, scope phải được client cho phép, và token phải thuộc đúng client khi dùng để lấy thông tin người dùng. Luồng hiện tại tập trung vào authorization_coderefresh_token, với access token kiểu Bearer.