+3

OIDC (OpenID Connect) Là Gì? Đừng Nhầm Lẫn Giữa "Chìa Khóa" Và "Căn Cước Công Dân"!

Chào anh em! Nếu bạn đang làm việc với các hệ thống Backend hiện đại hoặc Microservices, chắc chắn bạn đã từng nghe đến sếp hoặc lead yêu cầu: "Tích hợp đăng nhập bằng Google/Facebook vào hệ thống nhé!". Và thế là chúng ta lao vào search Google, copy một mớ cấu hình OAuth 2.0 về chạy thử thấy thành công là ăn mừng.

Nhưng khoan đã! Có một cú lừa lịch sử mà rất nhiều anh em mắc phải: OAuth 2.0 KHÔNG PHẢI LÀ GIAO THỨC ĐỂ XÁC THỰC NGƯỜI DÙNG (AUTHENTICATION). Để giải quyết cú lừa này, thế giới mới sinh ra OIDC (OpenID Connect). Hôm nay, với những kinh nghiệm "đổ máu" từ các dự án đập đi xây lại hệ thống Auth, tôi sẽ giúp anh em thông não khái niệm này một cách dễ hiểu nhất.

1. Bản chất vấn đề: Sự vô dụng của OAuth 2.0 trong việc "Nhận diện"

Để hiểu OIDC, trước tiên phải hiểu giới hạn của thằng đàn anh OAuth 2.0.

Hãy tưởng tượng OAuth 2.0 giống như chiếc thẻ từ mở cửa phòng khách sạn (Access Token). Khi bạn quẹt thẻ vào cửa (Resource Server / API), cái cửa chỉ kiểm tra: "Thẻ này có quyền mở phòng 204 không? Có hết hạn chưa?". Nếu đúng, nó mở (Authorization).

Cái cửa hoàn toàn KHÔNG BIẾT bạn là ai. Tên bạn là gì? Bao nhiêu tuổi? Tròn méo ra sao? Nếu bạn làm rơi thẻ và một tên trộm nhặt được, hắn vẫn mở cửa vào phòng bình thường.

Đó chính là lỗ hổng khi các hệ thống dùng OAuth 2.0 để làm chức năng "Login". Ứng dụng của bạn cầm được Access Token, nhưng lại không có cách nào chuẩn hóa để biết người dùng đó là ai (Profile, Email, Avatar...). Thế là OIDC xuất hiện như một đấng cứu thế.

2. OIDC (OpenID Connect) là gì?

Nói một cách ngắn gọn mang tính học thuật: OIDC là một lớp danh tính (Identity Layer) được xây dựng đè lên trên nền tảng của giao thức OAuth 2.0.

Nói theo ngôn ngữ giang hồ: Nếu OAuth 2.0 cấp cho bạn cái Chìa khóa khách sạn, thì OIDC cấp thêm cho bạn một cái Căn Cước Công Dân (CCCD) đính kèm vào cái chìa khóa đó.

Khi một ứng dụng sử dụng OIDC, thay vì Authorization Server chỉ trả về access_token trống rỗng, nó sẽ trả về thêm một món bảo bối mang tên: id_token.

ID Token là cái quái gì?

id_token luôn luôn được định dạng dưới chuẩn JWT (JSON Web Token). Nó chứa mọi thông tin cơ bản nhất về người dùng mà hệ thống của bạn cần biết. Khi Backend của bạn giải mã (decode) cái id_token này, nó sẽ nhận được một payload dạng như sau:

{
  "iss": "https://accounts.google.com", // Ai cấp cái thẻ này? (Google)
  "aud": "my-client-id-12345",          // Thẻ này cấp cho ứng dụng nào? 
  "sub": "1076915035000615071511",      // ID duy nhất của người dùng (Google ID)
  "email": "hieu.backend@example.com",
  "name": "Hiếu",
  "picture": "https://url-to-avatar.png",
  "exp": 1699999999                     // Thời gian hết hạn
}

Nhờ có id_token, Backend của chúng ta lập tức biết được: "À, anh chàng tên Hiếu, email này vừa đăng nhập hệ thống", từ đó tự động tạo user trong Database hoặc cấp phiên đăng nhập (Session) mà không cần phải gọi thêm API lằng nhằng nào khác.

3. Bài học thực chiến: Những cú vấp ngã với OIDC

Hồi mới chập chững thiết kế hệ thống Identity phân tán, tôi từng trả giá bằng những lỗi bảo mật khá ngớ ngẩn. Anh em chú ý né những "bãi mìn" này ra nhé:

  • Bãi mìn 1: Dùng Access Token để xác thực người dùng Tuyệt đối không! Access Token sinh ra để gọi API, không sinh ra để chứa thông tin User. Rất nhiều anh em cố gắng nhét thông tin User (email, role) vào Access Token. Việc này làm Token phình to vô ích và vi phạm nguyên tắc thiết kế. Hãy để việc đó cho id_token.

  • Bãi mìn 2: Tin tưởng mù quáng vào ID Token đẩy từ Frontend xuống Một kịch bản kinh điển: Frontend gọi Google Login, lấy được id_token, rồi ném cái token đó xuống Backend qua một API POST /login/google. Backend thấy token, bóc ra lấy email rồi cho login luôn. SAI HOÀN TOÀN! Hacker có thể tự fake một cái id_token (vì JWT ai cũng decode được). Backend của bạn BẮT BUỘC phải verify chữ ký (Signature) của JWT đó bằng Public Key của Google (JWKS) trước khi tin tưởng các dữ liệu bên trong.

  • Bãi mìn 3: Quên kiểm tra trường aud (Audience) Dù verify chữ ký đúng, bạn vẫn có thể bị tấn công. Hacker có thể lừa người dùng đăng nhập bằng Google trên app của hacker, lấy id_token đó bắn vào API của bạn. Nếu bạn không check trường aud (chắc chắn token này sinh ra dành riêng cho Client ID của dự án bạn), bạn sẽ cấp quyền truy cập nhầm cho hack

4. Tổng kết

Tóm lại, nếu hệ thống của bạn chỉ cần xin quyền truy cập vào Data (như xin quyền đọc Google Drive), hãy dùng thuần OAuth 2.0. Nhưng nếu bạn muốn làm chức năng "Đăng nhập bằng..." (SSO - Single Sign-On), bạn BẮT BUỘC phải dùng OIDC.

Hiểu rõ hai khái niệm này, bạn sẽ tự tin hơn rất nhiều khi thiết kế kiến trúc Backend hay trao đổi, tranh luận với các anh em Security trong dự án.

Hy vọng bài viết này giúp ích cho anh em trên con đường chinh phục Backend. Nếu thấy hay, đừng quên upvote nhé!


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí