Authentication và Authorization: OpenID vs OAuth2 vs SAML

Bài viết được dịch từ: spin.atomicobject.com

Dự án hiện tại của tôi tại AO đã cung cấp nhiều cơ hội để học về bảo mật web và cái gì sẽ xảy ra khi bạn bấm nút "Đăng nhập với Google/Facebook". Với tư cách là một lập trình viên và người dùng cuối, tôi muốn các ứng dụng được bảo mật, nhưng không quá khó khăn khi sử dụng.

Trong khi tìm kiếm một giải pháp phù hợp với ứng dụng của chúng tôi và các điều khoản bảo mật của khách hàng, chúng tôi đã tìm ra OpenID, OAuth2 SAML.

Authorization & Authentication cơ bản

Dự án của chúng tôi là một single-page application. Chúng tôi muốn giới hạn quyền truy cập cho những người dùng đã đăng ký. Thêm nữa chúng tôi muốn có trải nghiệm phù hợp với mỗi người dùng, và lượng và kiểu dữ liệu họ có thể thấy, ứng với vai trò và quyền hạn truy cập của họ.

Nói cách khác, chúng tôi muốn có khả năng xác thực (authenticate) phân quyền/ủy quyền (authorize) cho mỗi người dùng. Xác thực có nghĩa là xác minh rằng một ai đó thực sự là người mà họ nhận. Phân quyền/Ủy quyền có nghĩa là quyết định những tài nguyên mà một người dùng cụ thể có thể truy cập, họ có thể làm gì với những tài nguyên đó. Thông thường, một ứng dụng sẽ yêu cầu mỗi thứ một chút.

Với những trang web như Facebook hoặc Google, một người dùng có thể đăng nhập tới một ứng dụng với một bộ giấy chứng nhận (credential). Sau đó cùng một bộ giấy chứng nhận này có thể sử dụng để đăng nhập tới các website hoặc ứng dụng liên quan (giống như các website yêu cầu bạn "Đăng ký với tài khoản Facebook hoặc Google").

Tương tự, một doanh nghiệp có thể có một cổng thông tin (portal) nội bộ cho nhân viên với các trang web liên quan như timesheets, bảo hiểm y tế, hoặc các tin tức của công ty. Thay vì yêu cầu nhân viên đăng nhập tại mỗi trang web, một giải pháp tốt hơn là nhân viên đăng nhập tại cổng thông tin, và cổng thông tin sẽ tự động xác thực người dùng với các trang web liên quan khác. Giải pháp này được gọi là single sign-on/SSO (đăng nhập một lần), cho phép một người dùng nhập username và password một lần duy nhất để truy cập tới nhiều ứng dụng.

Điều này rất hữu ích cho người dùng. Họ chỉ cần quản lý duy nhất một usename và password cho các website liên quan. Trải nghiệm người dùng cũng tốt hơn, vì họ không cần phải đăng nhập nhiều lần. Chứng nhận của người dùng (một bộ) sẽ được lưu trữ trong một database, thay vì nhiều chứng nhận được lưu trữ trên nhiều database. Điều này cũng có nghĩa là các lập trình viên của các ứng dụng khác nhau không cần phải lưu trữ password. Thay vào đó, họ có thể chấp nhận bằng chứng nhận dạng hoặc ủy quyền từ một nguồn đáng tin cậy.

Có nhiều giải pháp cho việc triển khai SSO. Ba giao thức bảo mật web phổ biến nhất (tại thời điểm viết bài) là OpenID, OAuth và SAML. Cách triển khai và các thư viện đã có sẵn trong nhiều ngôn ngữ lập trình, và một giao thức đã được chuẩn hóa sẽ tốt hơn một giải pháp tùy chỉnh.

OpenID

OpenID là một chuẩn mở cho xác thực (authentication), được quảng bá bởi tổ chức phi lợi OpenID Foundation. Kể từ tháng 3 năm 2016, đã có hơn một tỷ tài khoản OpenID được sử dụng trên internet, và các công ty như Google, WordPress, Yahoo và Paypal sử dụng OpenID để xác thực người dùng.

Một người dùng phải có một tài khoản OpenID thông qua một nhà cung cấp nhận dạng (OpenID identity provider) chẳng hạn như Google. Sau đó người dùng sử dụng tài khoản này để đăng nhập vào bất kỳ website (bên phụ thuộc - relying party) chấp nhận xác thực bằng OpenID (giống như YouTube hoặc các site khác chấp nhận sử dụng một tài khoản Google để đăng nhập). Chuẩn OpenID cung cấp một khuôn khổ cho việc kết nối giữa các (nhà cung cấp nhận dạng - identity provider) và bên phụ thuộc (relying party).

Sự trao đổi này có thể so sánh với việc đi qua biên giới. Hãy tưởng tượng, Alice là một công dân Canada, cô ấy muốn thăm Mỹ. Tại biên giới, phía Mỹ yêu cầu bằng chứng nhận dạng (hộ chiếu của cô ấy). Bởi vì chính phủ Mỹ tin tưởng chính phủ Canada trong việc cung cấp nhận dạng cho công dân của họ, phía Mỹ chấp nhận hộ chiếu của Alice là bằng chứng đáng tin cậy về danh tính của cô ấy, và vì thế, họ để cho cô ấy vào Mỹ. Trong ví dụ này, Alice là người dùng cuối, phía Mỹ là bên phụ thuộc (relying party), và Canada là nhà cung cấp nhận dạng (identity provider).

Giao dịch này được chấp nhận bởi vì Alice có thể cung cấp bằng chứng nhận dạng cho phía Mỹ, rằng cô ấy đến từ một nơi mà Mỹ tin tưởng. Tương tự như vậy, bên phụ thuộc (relying party) hay chính là website người dùng đang đăng nhập phải tin tưởng vào nhà cung cấp nhận dạng (identity provider) của OpenID về việc xác minh danh tính của người dùng.

Trên một website, nó sẽ như thế này:

Hãy trở lại với Alice, người muốn đăng nhập vào tài khoản MyBlogger của mình (bên phụ thuộc - relying party). Cô ấy điều hướng đến màn hình đăng nhập, và được cung cấp tùy chọn "Đăng nhập với Google". Khi cô ấy click vào nó, MyBlogger khởi tạo liên kết với Google và yêu cầu nhận một xử lý liên quan (handle). Sau đó MyBlogger chuyển Alice tới trang đăng nhập của Google. Cô ấy nhập các thông tin của mình, và Google sẽ xác minh tính hợp lệ của chúng. Sau đó cô ấy sẽ được chuyển hướng trở lại MyBlogger, cùng với một token để thông báo rằng Google tin tưởng cô ấy chính là người mà cô ấy tuyên bố (Alice). MyBlogger tin tưởng token này và tạo một phiên (sesion) cho cô ấy.

Chú ý:

  1. OpenID về mặt kỹ thuật là một URL mà người dùng sở hữu (ví dụ alice2016.openid.com), vì thế một vài website cung cấp tùy chọn nhập OpenID một cách thủ công.
  2. Phiên bản mới nhất của OpenID là OpenID Connect, nó kết hợp xác thực của OpenID (OpenID authentication) và ủy quyền/ phân quyền của OAuth2 (OAuth2 authorization).
  3. Screen Shot 2016-05-16 at 8.29.34 AM

    Facebook trước đây sử dụng OpenID nhưng hiện nay đã chuyển sang Facebook Connect.

OAuth2

OAuth2 là một chuẩn mở để ủy quyền/phân quyền (authorization), OAuth2 cũng là nền tảng của OpenID Connect, nó cung cấp OpenID (xác thực - authentication) ở phía trên của OAuth2 (ủy quyền - authorization) để có một giải pháp bảo mật hoàn chỉnh hơn. OpenID Connect (OIDC) được tạo ra vào đầu năm 2014 và OAuth2 hoàn toàn độc lập, chứ không phải một phần của OIDC.

OAuth2 cung cấp quyền truy cập đã được ủy quyền an toàn (secure delegated access), điều đó có nghĩa là một ứng dụng hay một client có thể thao tác hoặc truy cập các tài nguyên trên một server thay mặt cho một người dùng, mà không cần người sử dụng phải chia sẻ thông tin tài khoản của họ với ứng dụng. OAuth2 làm điều này bằng các token được tạo ra bởi một nhà cung cấp nhận dạng (indentity provider) cho các ứng dụng bên thứ ba, với sự chấp thuận của người dùng.

Tuy nhiên tài liệu hướng dẫn OAuth của Twitter nói rằng OAuth2 là một chuẩn xác thực (authentication standard). Vậy nó có nghĩa là gì? Thực tế, ủy quyền có thể được sử dụng như một hình thức xác thực (pseudo-authentication).

Ủy quyền sử dụng trong trường hợp của OAuth2 có thể hình dung như thế này: Alice sẽ rời khỏi thị trấn và cô ấy muốn Bob bạn của mình trông nhà giúp. Alice đưa cho Bob chìa khóa nhà, và bây giờ anh ấy có thể vào trong ngôi nhà. Chìa khóa cho phép anh ấy vào nhà, cũng giống như cho phép một người dùng có thể truy cập tới các tài nguyên, và cái họ có thể làm với các tài nguyên đó. Trong ví dụ này, chủ nhà là người dùng, Bob là client, khóa cửa là nhà cung cấp nhận dạng (identity provider), và ngôi nhà là máy chủ lưu trữ tài nguyên.

Thực tế, một trường hợp sử dụng OAuth2 có thể như thế này: Alice đăng ký một tài khoản mới tại NewApp và được cung cấp tùy chọn để xem ai trong số bạn bè của cô ấy đã sử dụng NewApp, sau đó cô ấy có thể kết nối  với họ. Có một nút với nhãn "nhập danh bạ từ Facebook". Alice bấm nút đó, và cô ấy được điều hướng tới Facebook để đăng nhập. Sau khi đăng nhập thành công cô ấy sẽ được hỏi có muốn chia sẻ danh sách bạn bè Facebook với NewApp không. Cô ấy chọn có, và được điều hướng trở lại NewApp với một token. NewApp giờ đã có quyền (với token) truy cập tới danh sách bạn bè của Alice mà không cần cô ấy chia sẻ thông tin cá nhân trực tiếp với NewApp. Điều này loại bỏ nguy cơ NewApp đăng nhập vào Facebook với thông tin tài khoản của Alice và làm một số thứ cô ấy không mong muốn (đăng status, thay đổi mật khẩu, ...).

SAML

SAML là chuẩn lâu đời nhất, được phát triển từ năm 2001, và lần cập nhật gần đây nhất vào năm 2005. SAML là viết tắt của Security Assertion Markup Language. Nó là một chuẩn mở cung cấp cả xác thực (authentication) và phân quyền/ủy quyền (authorization).

Về mặt kỹ thuật nó tương tự với hai chuẩn còn lại, SAML định nghĩa một principal, là người dùng cuối đang cố gắng truy cập tới một tài nguyên. Có một nhà cung cấp dịch vụ (service provider), chính là máy chủ web mà principal đang cố truy cập. Và có một nhà cung cấp nhận dạng (identity provider), sẽ lưu trữ nhận dạng và thông tin của principal.

Ví dụ về Mỹ và Canada có thể sử dụng để minh họa. Alice muốn vào Mỹ từ Canada. Mỹ muốn xác minh danh tính hoặc các thông tin khác về cô ấy (nếu cô ấy có một giấy phép lái xe hợp lệ, nó sẽ cho phép cô ấy được lái xe ở Mỹ) - họ tạo một yêu cầu tới Canada để xác thực và/hoặc ủy quyền thông tin về Alice. Canada trả lời bằng cách gửi thông tin được yêu cầu cho phía Mỹ, cùng với một vài bằng chứng rằng Canada thực sự là người gửi tin nhắn. Bằng chứng này có thể là một hộ chiếu như trước đây, hoặc các giấy tờ được cấp bởi chính phủ hoặc thị thực (visa). Và như trước đây, hệ thống này dựa vào sự tin tưởng của Mỹ với Canada về việc cấp giấy phép lái xe, thị thực, ...

Trong ví dụ của chúng ta, Alice là principal, Mỹ là nhà cung cấp dịch vụ (service provider), và Canada lại một lần nữa là nhà cung cấp nhận dạng. Yêu cầu gửi tới Canada bởi Mỹ tương tự một thông điệp XML nêu rõ thông tin gì được yêu cầu, ai đang yêu cầu, và người nhận câu trả lời. Trả lời của Canada sẽ được gọi là một assertion, trong thuật ngữ của SAML (tương tự token của OpenID hoặc OAuth2). Assertion này có thể chứa các thông tin về xác thực, ủy quyền và/hoặc các thuộc tính (các thông tin cụ thể về người dùng, chẳng hạn như email hoặc số điện thoại).

SAML 2.0 định nghĩa các assertion, các protocol, cái gì là các yêu cầu và trả lời assertion, các binding, hoặc cách các yêu cầu và trả lời xảy ra giữa các nhà cung cấp dịch vụ (service provider) và nhà cung cấp nhận dạng (identity provider), sử dụng các phương thức kết nối chuẩn (ví dụ HTTP POST); và profiles, cái kết hợp của các assertion, protocol và binding để sử dụng cho trường hợp khác nhau, chẳng hạn như SSO.

Một trường hợp SSO giống như thế này: Alice là quản lý tại Acme Corp. Cô ấy truy cập cổng thông tin của Acme Corp, nơi cô ấy đăng nhập với thông tin cá nhân của mình. Sau khi đăng nhập, cô ấy có thể bấm vào một số liên kết mà cô ấy thích (lương thưởng, tin tức của công ty, Saleforce, ...). Cô ấy bấm vào liên kết Salesforce, nó chứa một SAML assertion về Alice. Cô ấy sẽ được chuyển tới Salesfoce, nó nhận được SAML assertion. Salesforce tin tưởng Acme Corp, và vì thế tin tưởng assertion. Sử dụng thông tin trong assertion, Alice tự động đăng nhập, và các dữ liệu thích hợp được hiển thị dựa trên các thuộc tính trong assertion.

Tổng kết

Cả ba giải pháp được tổng hợp lại trong bảng bên dưới. Ứng dụng của chúng tôi triển khai IdentityServer, một .NET framework triển khai cả OAuth2 và OpenID Connect.

 
OAuth2
OpenId
SAML
Token (or assertion) format
JSON or SAML2
JSON
XML
Authorization?
Yes
No
Yes
Authentication?
Pseudo-authentication
Yes
Yes
Year created
2005
2006
2001
Current version
OAuth2
OpenID Connect
SAML 2.0
Transport
HTTP
HTTP GET and HTTP POST
HTTP Redirect (GET) binding, SAML SOAP binding, HTTP POST binding, and others
Security Risks
Phishing
 
OAuth 2.0 does not support signature, encryption, channel binding, or client verification.  Instead, it relies completely on TLS for confidentiality.
Phishing
 
Identity providers have a log of OpenID logins, making a compromised account a bigger privacy breach
XML Signature Wrapping to impersonate any user
Best suited for
API authorization
Single sign-on for consumer apps
Single sign-on for enterprise
Note:  not well suited for mobile

 

Tham khảo thêm

PHP vs Node.js - Cuộc chiến giữa hai công nghệ lập trình web PHP vs Node.js - Cuộc chiến giữa hai công nghệ lập trình web Hồ Sỹ Hùng Blog Home Một lập trình viên nên biết 6 công nghệ cần học trong 2013 Một lập trình viên nên biết 6 công nghệ cần học trong 2013 Techmaster team
Vũ Kim Thành

Front-end Web Developer at FPT software. I have a passion with front-end technologies. When I have free time, I often read, study and share my knowledge for everyone.