
Bạn bấm “Đăng nhập bằng Google”, cho phép một ứng dụng xem lịch hoặc kết nối công cụ quản lý với tài khoản của mình. Ứng dụng không cần cầm mật khẩu Google, nhưng vẫn được cấp đúng quyền bạn cho phép. Phần đứng sau trải nghiệm đó thường liên quan đến OAuth 2.0.
Tóm tắt nhanh: OAuth 2.0 là framework ủy quyền, tức giúp một ứng dụng truy cập tài nguyên được bảo vệ thay mặt người dùng. Nó không tự có nghĩa là “xác thực danh tính”. Nếu cần biết người dùng là ai, hệ thống thường dùng OpenID Connect xây trên OAuth 2.0. Hiểu nhầm hai việc này là nguồn gốc của không ít thiết kế đăng nhập nguy hiểm.
OAuth 2.0 là gì?
OAuth 2.0 là framework chuẩn hóa cách một ứng dụng xin quyền truy cập tài nguyên từ một máy chủ khác. Thay vì đưa mật khẩu cho ứng dụng thứ ba, người dùng được chuyển tới máy chủ cấp quyền, xem phạm vi truy cập và đồng ý. Máy chủ sau đó cấp token để ứng dụng gọi tài nguyên.
Ví dụ: một công cụ quản lý lịch cần đọc lịch làm việc của bạn. Công cụ không cần biết mật khẩu tài khoản. Nó chỉ cần một access token có scope phù hợp, và token này có thể bị thu hồi mà không buộc bạn đổi mật khẩu toàn bộ tài khoản.
Bốn vai trò trong OAuth 2.0
RFC 6749 mô tả bốn vai trò chính:
- Resource owner: người hoặc thực thể có quyền đối với tài nguyên.
- Client: ứng dụng xin quyền và gọi tài nguyên thay mặt resource owner.
- Authorization server: nơi xác thực người dùng, nhận sự đồng ý và phát token.
- Resource server: nơi giữ API hoặc dữ liệu được bảo vệ, kiểm tra access token.
Một nhà cung cấp có thể dùng cùng một hệ thống cho authorization server và resource server, nhưng về mặt vai trò chúng vẫn là hai phần khác nhau. Tài liệu gốc nằm trong RFC 6749 của IETF.
Luồng OAuth 2.0 diễn ra thế nào?
- Ứng dụng báo cho người dùng biết nó muốn quyền gì.
- Người dùng được chuyển tới authorization server.
- Authorization server xác thực người dùng và hiển thị màn hình đồng ý.
- Ứng dụng nhận authorization code hoặc một loại grant phù hợp.
- Ứng dụng đổi code lấy access token, thường qua một kênh an toàn.
- Ứng dụng gửi access token khi gọi resource server.
- Khi access token hết hạn, ứng dụng có thể dùng refresh token nếu được cấp.

Điểm quan trọng: mật khẩu của người dùng chỉ được nhập ở nơi xác thực đáng tin cậy, không phải trong một form tự dựng của ứng dụng thứ ba. Ứng dụng nhận quyền có giới hạn chứ không nhận toàn bộ tài khoản.
Access token và refresh token khác nhau ra sao?
Access token là giấy thông hành ngắn hạn để gọi tài nguyên. Nó thường đi kèm scope và thời hạn. Nếu bị lộ, kẻ xấu có thể dùng nó trong phạm vi được cấp cho đến khi token hết hạn hoặc bị thu hồi.
Refresh token dùng để xin access token mới mà không bắt người dùng đăng nhập lại. Vì có thể sống lâu hơn, refresh token cần được bảo vệ nghiêm ngặt trong lưu trữ và truyền tải. RFC 6749 nhấn mạnh refresh token phải được giữ bí mật, chỉ chia sẻ giữa authorization server và client tương ứng.
Đừng nhầm access token với ID token. Access token dành cho gọi API. ID token thuộc OpenID Connect và mang thông tin phục vụ việc xác thực danh tính. Nếu ứng dụng chỉ đọc ID token để quyết định quyền API, thiết kế đó cần được xem lại.
Authorization Code và PKCE: lựa chọn thực tế hiện nay
Authorization Code flow tách bước xin quyền và bước đổi code lấy token. Với ứng dụng di động, trình duyệt và các client không thể giữ secret an toàn, PKCE thêm một cặp verifier và challenge để code bị đánh cắp khó đổi thành token.
OAuth.net liệt kê Authorization Code, PKCE, Client Credentials và Device Code trong nhóm flow phổ biến; implicit flow và password grant được xếp vào nhóm legacy. Đừng chọn flow chỉ vì một bài hướng dẫn cũ còn xuất hiện trên Google. Hãy xem client của mình có giữ được secret hay không và nhà cung cấp đang khuyến nghị flow nào.
Public client và confidential client
Confidential client là ứng dụng có thể giữ client secret an toàn, thường là backend chạy trên server do đội ngũ kiểm soát. Public client như ứng dụng chạy hoàn toàn trong trình duyệt hoặc trên điện thoại không thể giữ secret tuyệt đối, vì người dùng có thể phân tích ứng dụng.
Vì vậy, đừng nhúng client secret cố định vào JavaScript frontend hay APK rồi nghĩ rằng nó đã là bí mật. Với public client, thiết kế cần dựa vào redirect URI chặt chẽ, PKCE, scope tối thiểu và cơ chế lưu token phù hợp với nền tảng.
6 lỗi bảo mật thường gặp
1. Dùng OAuth như một hệ thống đăng nhập hoàn chỉnh
OAuth giải quyết ủy quyền. Nếu cần đăng nhập, hãy dùng OpenID Connect và kiểm tra ID token theo đúng tài liệu của nhà cung cấp.
2. Để redirect URI quá rộng
Redirect URI nên khớp chặt với địa chỉ đã đăng ký. Wildcard hoặc redirect tới domain không kiểm soát được có thể biến authorization code thành món quà cho kẻ tấn công.
3. Bỏ qua state và PKCE
State giúp liên kết yêu cầu với phiên người dùng và giảm nguy cơ request giả mạo. PKCE bảo vệ authorization code trong các client public. Thiếu hai lớp này, luồng tưởng như chạy được vẫn có thể bị đánh cắp.
4. Xin scope quá rộng
Ứng dụng đọc danh sách lịch không cần quyền xóa lịch. Scope càng rộng, hậu quả khi token lộ càng lớn. Hãy xin quyền tối thiểu và tách scope đọc, ghi nếu nhà cung cấp hỗ trợ.
5. Lưu token như lưu một chuỗi bình thường
Không đưa token vào URL, log, ảnh chụp màn hình hoặc kho mã nguồn. Hạn chế thời gian sống, bảo vệ nơi lưu trữ và có quy trình thu hồi khi thiết bị hoặc tài khoản bị mất.
6. Không kiểm tra issuer, audience và thời hạn
Resource server cần kiểm tra token được phát bởi ai, dành cho API nào, còn hạn hay không và có scope cần thiết không. Chỉ giải mã JWT rồi tin mọi nội dung bên trong là chưa đủ.
OAuth 2.0 có phù hợp với SME không?
Nếu doanh nghiệp chỉ có một website nội bộ đơn giản, tự dựng authorization server có thể là việc quá sức. Lựa chọn thực tế thường là dùng nhà cung cấp identity có tài liệu, log và cơ chế thu hồi rõ ràng, sau đó giới hạn scope và thiết kế backend làm nơi giữ bí mật.
Nếu kết nối nhiều công cụ, hãy lập bảng quyền: ứng dụng nào cần dữ liệu gì, token sống bao lâu, ai được thu hồi, log nào được lưu và chuyện gì xảy ra khi refresh token bị lộ. Một bảng như vậy hữu ích hơn việc ghi chung chung “bảo mật OAuth” trong tài liệu kỹ thuật.
Checklist trước khi triển khai
- Phân biệt rõ authorization với authentication.
- Chọn flow theo loại client, không theo code mẫu cũ.
- Dùng Authorization Code với PKCE khi phù hợp.
- Giới hạn redirect URI và scope.
- Kiểm tra state, issuer, audience, thời hạn và scope.
- Bảo vệ access token và refresh token khác nhau.
- Có cơ chế thu hồi, xoay vòng và xử lý khi token bị lộ.
Kết luận
OAuth 2.0 giúp ứng dụng nhận đúng quyền mà không cần cầm mật khẩu người dùng. Nhưng bản thân giao thức không tự làm hệ thống an toàn. An toàn đến từ lựa chọn flow đúng, scope nhỏ, redirect URI chặt, token được bảo vệ và resource server kiểm tra đầy đủ.
Việc nên làm ngay là vẽ bảy bước của luồng cấp quyền hiện tại, đánh dấu nơi token xuất hiện và thử trả lời một câu hỏi: nếu token này bị lộ trong 10 phút, kẻ xấu làm được chính xác điều gì?
Nguồn tham khảo
IETF – RFC 6749 OAuth 2.0
OAuth.net – OAuth 2.0
OAuth.net – Client types
Techzika – Passkey là gì?