Bỏ qua để đến nội dung

Authentication & Permissions

Level: L7 — MCP, API & Connectors (Bài 6/11 theo thứ tự sản xuất — · Đối tượng: Người đã học bài 65-69 (API/Webhook/Tool Calling/MCP),

Sau bài này, bạn có thể:

  • Phân biệt 2 kiểu xác thực phổ biến: API key (tĩnh) và OAuth (có đồng ý, có thể thu hồi) — biết khi nào gặp cái nào.
  • Giải thích 4 vai trò trong OAuth 2.0 và vai trò Builder (Client) của chính bạn trong đó.
  • Mô tả đúng luồng đăng ký + xác thực OAuth 3 bước từ góc nhìn người xây tích hợp.
  • Áp dụng nguyên tắc “phạm vi quyền tối thiểu” (least privilege) khi chọn scope cho 1 tích hợp thật.

Bước 1 — Concept: bài 65 dạy header Authorization chứa credential xác thực — nhưng credential đó có thể là 1 trong 2 loại rất khác nhau, và Builder cần biết phân biệt trước khi xây bất kỳ tích hợp nào.

API key (tĩnh): 1 chuỗi cố định do dịch vụ cấp cho bạn, dùng lại cho mọi request, thường không hết hạn tự động (trừ khi bạn tự thu hồi). Đơn giản, nhưng: nếu lộ, nó có hiệu lực vĩnh viễn cho tới khi bạn thu hồi thủ công (đã học bài 62, L6: “biện pháp khắc phục chính khi phát hiện lộ secret là xoay vòng ngay lập tức”).

Bước 2 — Open standard (OAuth 2.0, vendor-neutral): OAuth 2.0 là “chuẩn ngành cho việc ủy quyền (authorization)” [S107]. Vấn đề nó giải quyết: không có OAuth, người dùng phải đưa mật khẩu thật cho mọi ứng dụng cần truy cập dữ liệu của họ ở dịch vụ khác — rủi ro ứng dụng dùng sai mục đích hoặc lưu trữ không an toàn. OAuth loại bỏ việc chia sẻ mật khẩu bằng mô hình ủy quyền (delegation) [S107].

4 vai trò OAuth 2.0 [S107]:

  1. Resource Owner — người dùng sở hữu dữ liệu, cấp quyền.
  2. Clientchính là ứng dụng của bạn (Builder) — xin quyền truy cập.
  3. Authorization Server — dịch vụ xác minh danh tính, phê duyệt quyền.
  4. Resource Server — dịch vụ lưu trữ dữ liệu thực sự được yêu cầu.

Access token và Scope [S107]: thay vì chia sẻ mật khẩu, authorization server cấp 1 access token — credential chứng minh Client được phép truy cập tài nguyên cụ thể, thu hồi được bất cứ lúc nào bởi người dùng. Scope định nghĩa token cho phép làm gì — người dùng chỉ phê duyệt đúng quyền ứng dụng cần, không phải toàn quyền vô hạn.

Bảng đối chiếu API key vs OAuth (tổng hợp của người viết):

API key OAuth
Đại diện cho Chính ứng dụng của bạn Quyền của 1 người dùng cụ thể trên dữ liệu của họ
Người dùng có đồng ý rõ ràng không? Thường không (bạn tự lấy key từ tài khoản của bạn) Có — màn hình OAuth yêu cầu đồng ý tường minh
Thu hồi Thủ công, do bạn chủ động Người dùng có thể tự thu hồi bất cứ lúc nào
Phù hợp khi Ứng dụng gọi API thay mặt chính bạn Ứng dụng cần truy cập dữ liệu của người dùng khác

Cả 4 bài tích hợp thật sắp học (70-73: Google, Notion, CRM, Database) đều cần bạn thiết lập xác thực đúng cách trước khi kết nối được. Hiểu sai API key và OAuth — hoặc xin scope rộng hơn cần thiết — là nguồn rủi ro bảo mật phổ biến nhất khi xây tích hợp, đúng như đã cảnh báo ở bài 56 (L6, số liệu CodeRabbit về lỗ hổng bảo mật khi thiếu kỷ luật).

Bước 3 — Architecture (luồng OAuth 3 bước, tổng quát):

  1. Ứng dụng của bạn (Client) chuyển hướng người dùng tới Authorization Server, kèm theo scope đang xin.
  2. Người dùng đăng nhập (nếu chưa) và thấy màn hình đồng ý — đây chính là màn hình đã học ở Ch02, góc nhìn end-user.
  3. Nếu đồng ý, Authorization Server cấp cho ứng dụng của bạn 1 access token (thường qua 1 bước trung gian, xem mục 6).

Bước 4 — Real implementation (luồng cụ thể 3 bước từ góc nhìn Builder) [S108]:

  1. Yêu cầu danh tính người dùng — chuyển hướng người dùng tới URL authorize của dịch vụ, kèm client_id (định danh ứng dụng của bạn, nhận khi đăng ký), redirect_uri, scope (danh sách quyền cách nhau bằng dấu cách), và state (chuỗi ngẫu nhiên chống giả mạo request).
  2. Đổi authorization code lấy access token — dịch vụ chuyển hướng người dùng về kèm 1 code tạm thời; ứng dụng của bạn đổi code đó lấy access token, cần cả client_id client_secret (2 credential đại diện cho chính ứng dụng, nhận khi đăng ký — khác access token đại diện cho 1 người dùng).
  3. Dùng access token — gửi trong header Authorization: Bearer <token> khi gọi API (đúng header đã học bài 65).

Tiếp nối ẩn dụ mạng lưới nhà cung cấp: API key giống 1 thẻ thành viên riêng của cửa hàng bạn — bạn tự lấy, dùng để mua hàng thay mặt chính cửa hàng. OAuth giống việc bạn (cửa hàng) xin phép 1 khách hàng cụ thể cho phép bạn thay mặt họ lấy đồ từ kho của họ — khách hàng đó phải tự tay ký giấy đồng ý (màn hình OAuth), và có thể rút lại giấy đồng ý đó bất cứ lúc nào. client_secret giống con dấu riêng của cửa hàng bạn — chứng minh đúng là cửa hàng bạn đang xin, không phải ai giả danh.

Checklist thiết lập xác thực cho 1 tích hợp mới (tổng hợp của người viết, dựa trên S107/S108 + nguyên tắc bài 62/L6):

  1. Xác định loại xác thực dịch vụ yêu cầu — API key đơn giản, hay OAuth đầy đủ? (đọc tài liệu API — đã học bài 65 mục 6).
  2. Nếu OAuth: đăng ký ứng dụng với dịch vụ, nhận client_id + client_secret.
  3. Chọn scope tối thiểu cần thiết — không xin quyền ghi nếu chỉ cần đọc (nguyên tắc đã học Ch02, tái áp dụng ở đây từ góc nhìn Builder).
  4. Lưu client_secret và access token đúng cách — biến môi trường (bài 63, L6), không hardcode (bài 62, L6).
  5. Với API key: lưu tương tự qua biến môi trường; xác nhận dịch vụ có cơ chế thu hồi/xoay vòng key khi cần.

Bước 5 — Vendor example (GitHub OAuth Apps): khi đăng ký 1 OAuth App trên GitHub, bạn nhận client_idclient_secret. Muốn đọc danh sách repository riêng tư của người dùng, bạn xin scope repo khi chuyển hướng họ tới màn hình đồng ý; nếu chỉ cần đọc thông tin công khai, scope hẹp hơn (hoặc không cần OAuth, chỉ cần gọi API công khai như đã học bài 65) là đủ — đúng nguyên tắc least privilege.

Khung yêu cầu thiết lập xác thực (tái sử dụng):

Tôi cần kết nối [ứng dụng của tôi] với [dịch vụ bên ngoài].
Dịch vụ này dùng API key hay OAuth?
Nếu OAuth: hướng dẫn tôi đăng ký ứng dụng, và đề xuất scope tối thiểu
cần thiết cho việc [mục tiêu cụ thể — ví dụ: chỉ đọc tài liệu, không
cần quyền ghi].
Hướng dẫn tôi lưu credential qua biến môi trường, không hardcode.

Checklist trước khi coi 1 tích hợp đã xác thực đúng cách:

[ ] Đã xác định đúng loại xác thực (API key vs OAuth)?
[ ] Nếu OAuth: đã chọn scope tối thiểu cần thiết, không xin dư quyền?
[ ] client_secret/API key đã lưu qua biến môi trường, không hardcode?
[ ] Biết cách thu hồi/xoay vòng credential nếu cần?
1. Gửi yêu cầu đăng nhập2. Người dùng phê duyệt quyền3. Nhận Authorization Code4. Đổi Code lấy Access Token5. Dùng Token gọi API
Hình 7.10 — Authentication: luồng OAuth 5 bước, đối chiếu API key đơn giản.
  1. Chọn 1 trong 4 dịch vụ sắp học (Google/Notion/CRM/Database — bài 70-73). Tra cứu: dịch vụ đó dùng API key hay OAuth?
  2. Nếu OAuth, xác định: scope tối thiểu cần cho dự án Notes App (dự án tích lũy) là gì?
  3. Dùng khung ở mục 8 để lên kế hoạch thiết lập xác thực cho dịch vụ đó.
  4. Áp dụng checklist mục 8 (phần thứ 2) trước khi coi việc thiết lập đã hoàn chỉnh.

(Suy luận từ nguyên tắc [S107, S108], không phải quan sát độc lập.)

  • Xin scope rộng hơn cần thiết — “để phòng sau này cần” — vi phạm nguyên tắc least privilege, tăng rủi ro nếu credential bị lộ.
  • Nhầm client_secret với access tokenclient_secret đại diện cho ứng dụng (dùng lại nhiều lần khi đổi code lấy token), access token đại diện cho 1 phiên quyền của 1 người dùng cụ thể — 2 khái niệm khác nhau, không dùng lẫn.
  • Hardcode client_secret hoặc API key trong code — đúng rủi ro đã cảnh báo ở bài 62 (L6), áp dụng lại ở đây trong ngữ cảnh cụ thể hơn.
  • Bỏ qua state (chống CSRF) khi tự triển khai luồng OAuth — mở đường cho 1 dạng tấn công giả mạo request.

13. Giới hạn & khi nào KHÔNG nên áp dụng

Phần tiêu đề “13. Giới hạn & khi nào KHÔNG nên áp dụng”
  • Bài này không dạy lại góc nhìn end-user (đọc màn hình OAuth trước khi đồng ý) — xem Ch02 nếu cần ôn lại.
  • Bài này không dạy các luồng OAuth nâng cao khác (ví dụ: Client Credentials Flow cho giao tiếp server-to-server không có người dùng trung gian, hay PKCE đầy đủ cho ứng dụng di động/SPA) — chỉ dạy luồng phổ biến nhất (Authorization Code Flow) đủ cho phần lớn tích hợp cá nhân/dự án nhỏ.
  • Không dạy rủi ro/quản trị dữ liệu sau khi đã xác thực xong — đó là bài 75 (“vào rồi thì cẩn thận điều gì”).

client_secret và access token đều là secrets theo đúng định nghĩa đã học bài 62 (L6: “API key, mật khẩu, token”) — nguyên tắc “không bao giờ đặt trong code, luôn lưu tách biệt” áp dụng cho cả 2, không có ngoại lệ vì chúng “chỉ dùng cho OAuth.” Nguyên tắc least privilege (scope tối thiểu) là lớp phòng vệ bổ sung: kể cả nếu 1 token bị lộ, thiệt hại giới hạn đúng trong phạm vi scope đã xin — đây là lý do không nên “xin dư” bao giờ, dù có vẻ tiện lợi hơn về sau.

  1. Luôn chọn scope tối thiểu cần thiết cho mục tiêu hiện tại, mở rộng sau nếu thực sự cần — không xin trước “cho chắc.”
  2. Lưu client_secret/API key/access token qua biến môi trường, không bao giờ hardcode (dẫn chiếu bài 62/63, L6).
  3. Luôn dùng state (hoặc cơ chế chống CSRF tương đương) khi tự triển khai luồng OAuth.
  4. Định kỳ rà soát các ứng dụng/tích hợp đã cấp quyền, thu hồi cái không còn dùng — áp dụng lại nguyên tắc đã học Ch02 từ góc nhìn Builder.
16. Nội dung nâng cao (không bắt buộc)

Ngoài Authorization Code Flow (dạy ở bài này), OAuth 2.0 còn định nghĩa các luồng khác cho ngữ cảnh khác: Client Credentials Flow (khi không có người dùng trung gian — 2 hệ thống tự xác thực với nhau trực tiếp, phù hợp cho tích hợp server-to-server thuần túy) và các cơ chế bảo mật bổ sung như PKCE (Proof Key for Code Exchange — bắt buộc cho ứng dụng không thể giữ bí mật client_secret an toàn, ví dụ ứng dụng di động). Vượt phạm vi người mới bắt đầu của Level 7, nhưng đáng biết tên gọi nếu gặp trong tài liệu 1 dịch vụ cụ thể sau này.

  • [S107] OAuth 2.0, oauth.net — 4 vai trò, access token, scope, vấn đề OAuth giải quyết.
  • [S108] Authorizing OAuth Apps, GitHub Docs — luồng 3 bước cụ thể, client ID/secret, ví dụ thực tế.
  • Dẫn chiếu (không trích dẫn mới): bài 62 (nguyên tắc secrets, L6); bài 63 (biến môi trường, L6); bài 65 (header Authorization); Ch02 (góc nhìn end-user OAuth, L7).

Nội dung kiểm chứng qua nguồn Tier 1 (S107, S108) ngày 2026-07-13. Khái niệm OAuth 2.0/4 vai trò là chuẩn ngành ổn định (RFC 6749); chi tiết triển khai cụ thể của 1 dịch vụ (URL, tên tham số) có thể đổi — cần re-verify khi áp dụng cho dịch vụ cụ thể ở bài 70-73.