---
# System prepended metadata

title: 'Identity Management: OpenID, OAuth and SAML'
tags: [OAuth, OpenID, SAML, Identity]

---

---
title: 'Identity Management: OpenID, OAuth and SAML'
disqus: hackmd
---

Identity Management: OpenID, OAuth and SAML
===

**Tác giả:** 
1. 19120033 - Phan Lộc Sơn
2. 19120082 - Trần Anh Huy
3. 19120376 - Nguyễn Lê Bảo Thi
4. 19120732 - Nguyễn Xuân Vỵ

## Mục lục

[TOC]

## Giới thiệu

Khái niệm định danh đã tồn tại rất lâu trước khi máy tính được phát minh và nhu cầu quản lý trực tuyến xuất hiện, khi đó tên của một người là danh tính ban đầu của họ.

Trong thế giới công nghệ hiện đại ngày nay, định danh của người dùng hầu như không thay đổi nhiều, nó xác định chúng ta là ai và chúng ta được phép làm gì. Đồng thời, các hệ thống được sử dụng để quản lý và thiết lập nó đã có sự phát triển không ngừng về cách thông tin nhận dạng được lưu trữ và sử dụng để cho phép người dùng truy cập các ứng dụng và chức năng được cung cấp. 

Bài viết này giới thiệu tổng quan về ba giao thức quản lý danh tính phổ biến được sử dụng hiện tại: OAuth 2.0, OpenID và SAML 2.0. Mục đích của bài viết nhằm giúp bạn hiểu các giao thức này là gì, mục đích sử dụng và sơ lược cách hoạt động của chúng.

## OAuth 2.0
> Sở hữu quyền lực to lớn phải bao hàm trách nhiệm lớn lao. (The possession of great power necessarily implies great responsibility)[name=William Lamb, Thành viên Quốc hội, Bộ trưởng Nội vụ và Thủ tướng Anh. Từ một bài phát biểu tại Hạ viện năm 1817]

Các ứng dụng hiện đại thường xuyên sử dụng các dịch vụ được cho phép tích hợp vào chúng nhờ API. OAuth 2.0 cung cấp giải pháp tốt hơn để cấp phép cho các ứng dụng gọi các API. Giải pháp này loại bỏ việc người dùng phải chia sẻ thông tin đăng nhập với ứng dụng và cho phép người dùng kiểm soát nhiều hơn những gì ứng dụng có thể truy cập, hạn chế quyền truy cập nó đối với các bên được ủy quyền (Authorized Parties).

### Thuật ngữ
#### API Authorization
Một ứng dụng có thể cần gọi một API thay mặt cho người dùng để truy cập vào nội dung được sở hữu bởi người dùng hoặc thay mặt cho chính họ nếu ứng dụng sở hữu nội dung mong muốn.
Authorization API được định nghĩa là khi thực thể chứng minh có quyền truy cập API nhưng chỉ được phép truy cập trong phạm vi nhất định.
#### Vai trò (Roles)
* *Máy chủ tài nguyên (Resource Server)* - Một dịch vụ (có API) lưu trữ tài nguyên được bảo vệ được có thể được ứng dụng truy cập.
* *Chủ sở hữu tài nguyên (Resource Owner)* - Người dùng hoặc pháp nhân khác sở hữu tài nguyên được bảo vệ tại máy chủ tài nguyên.
* *Ứng dụng khách (Ứng dụng) (Client)* - Một ứng dụng cần truy cập tài nguyên tại máy chủ tài nguyên, thay mặt chủ sở hữu tài nguyên hoặc chính nó.
* *Máy chủ ủy quyền (Authorization Server)* - Một dịch vụ được máy chủ tài nguyên tin cậy để ủy quyền các ứng dụng gọi nó. Nó xác thực ứng dụng hoặc chủ sở hữu tài nguyên và yêu cầu sự đồng ý từ chủ sở hữu tài nguyên nếu ứng dụng thay mặt chủ sở hữu tài nguyên đưa ra yêu cầu. 
#### Hai loại Client: Confidential vs. Public Clients
* *Ứng dụng bảo mật (Confidential Client)* - Ứng dụng chạy trên một máy chủ được bảo vệ và có thể lưu trữ an toàn các bí mật để xác thực chính nó với máy chủ ủy quyền hoặc sử dụng cơ chế xác thực an toàn khác cho mục đích đó.
* *Ứng dụng công khai (Public Client)* - Ứng dụng thực thi chủ yếu trên ứng dụng khách và không thể lưu trữ một cách an toàn bí mật hoặc sử dụng các phương tiện khác để xác thực chính nó với một máy chủ ủy quyền.
#### Các hồ sơ ứng dụng (Client Profiles)
* *Ứng dụng web (Web Application)* - Một ứng dụng bảo mật với mã thực thi đã được bảo vệ, máy chủ back-end. Máy chủ có thể lưu trữ một cách an toàn bất kỳ bí mật cần thiết nào để ứng dụng tự xác thực cũng như nhận bất kỳ token nào từ máy chủ ủy quyền.
* *Ứng dụng dựa vào tác nhân người dùng (User Agent-Based App)* - Được giả định là một ứng dụng công khai với mã thực thi trong trình duyệt của người dùng. 
* *Ứng dụng gốc (Native Application)* - Giả sử là một ứng dụng công khai đã được cài đặt và được thực thi trên thiết bị của người dùng.

Trong thực tế, các định nghĩa này có thể bị trùng lặp.
#### Tokens and Authorization Code: Gồm hai token bảo mật và một mã ủy quyền trung gian
* *Authorization Code* - Một mã trung gian không rõ ràng được trả lại cho một ứng dụng và được sử dụng để lấy access token và tùy chọn refresh token. Mỗi authorization code được sử dụng một lần.
* *Access Token* - Một token được ứng dụng sử dụng để truy cập API. Nó đại diện cho sự ủy quyền của ứng dụng để gọi một API và có thời hạn.
* *Refresh Token* - Một token tùy chọn có thể được sử dụng bởi ứng dụng để yêu cầu một access token mới khi access token trước đó đã hết hạn.

### OAuth 2.0

Khung ủy quyền OAuth 2.0 (OAuth 2.0 Authorization Framework), được xuất bản vào năm 2012, được thiết kế để cho phép một ứng dụng nhận được ủy quyền gọi các API của bên thứ ba hoặc được ủy quyền để gọi API trên danh nghĩa của nó nếu nó sở hữu nội dung được truy cập.

Chủ sở hữu tài nguyên (Resource Owner) là người cho phép ứng dụng truy cập tài nguyên đã được bảo vệ tại máy chủ tài nguyên (Resource server).

**Ví dụ:** 
<figure>
    <img src="https://i.imgur.com/DilajaU.png">
    <figcaption>Hình 2.1. Xác thực API: Luồng User-Based vs. Client-Based</figcaption>
</figure>

Ứng dụng WriteAPaper.com đã gọi hai API thuộc sở hữu của các tổ chức khác nhau. API thứ nhất là famousquotes.com - không thuộc sở hữu của người dùng nào. Vì vậy, ứng dụng chỉ cần là khách hàng đã đăng ký được ủy quyền để gọi API. API thứ hai là documents.com - Có một ứng dụng thứ hai truy cập tới để cung cấp quyền truy cập vào tài liệu từ thiết bị di động của người dùng cho API này. Vì nội dung muốn truy cập thuộc về người dùng và cần quyền truy xuất tài liệu từ người dùng. Vì vậy, nó cần yêu cầu ủy quyền từ người dùng để gọi API này.

<figure>
    <img src="https://i.imgur.com/aNCXUER.png">
    <figcaption>Hình 2.2. Không sử dụng OAuth 2.0</figcaption>
</figure>

Trước khi sử dụng OAuth 2.0, giải pháp thông thường có những rủi ro. Người dùng cần phải cung cấp thông tin đăng nhập cho WriteAPaper dẫn tới ứng dụng này có thể truy cập hay chỉnh sửa bất cứ thứ gì trong tài khoản, có thể chịu rủi ro khi ứng dụng WriteAPaper bị tấn công và không thể thu hồi lại quyền của ứng dụng trừ khi đổi lại mật khẩu.

<figure>
    <img src="https://i.imgur.com/2lOwq5e.png">
    <figcaption>Hình 2.3. Sử dụng OAuth 2.0</figcaption>
</figure>

Khi sử dụng OAuth 2.0, ứng dụng (WriteAPaper) cần gọi một API (documents.com) thay mặt cho người dùng, nó sẽ gửi một yêu cầu ủy quyền tới máy chủ ủy quyền cho API đó đính kèm phạm vi. Máy chủ ủy quyền nhắc người dùng xác thực và được đồng ý, nó sẽ trả về một authorization code. Ứng dụng gửi authorization code đó đến token endpoint của máy chủ ủy quyền và nhận được token (access token có thể thêm refresh token). Ứng dụng sử dụng access token này để gọi API.

OAuth 2.0 access token chỉ nhằm mục đích truy cập API và không truyền tải thông tin về sự kiện xác thực hoặc người dùng. Do đó, việc sử dụng OAuth 2.0 là thích hợp để cấp phép các lệnh gọi API.

### Cách thức hoạt động

#### Authorization Code Grant

Authorization Code Grant sử dụng hai yêu cầu từ ứng dụng đến máy chủ ủy quyền để lấy access token.

*Authorization Code Grant Type + PKCE*

Proof Key for Code Exchange (PKCE) là một cơ chế có thể được sử dụng với yêu cầu ủy quyền và yêu cầu token đảm bảo rằng ứng dụng đã yêu cầu authorization code và ứng dụng sử dụng authorization code để lấy access token là giống nhau. PCKE bảo vệ chống lại một quy trình độc hại, chặn authorization code và sử dụng nó để lấy access token.

Để sử dụng PCKE, ứng dụng tạo một chuỗi mật mã ngẫu nhiên được gọi là code verifier, chuỗi cần đủ dài để cung cấp đủ bảo vệ chống lại việc đoán ra nó. Sau đó ứng dụng tính toán một giá trị dẫn xuất từ code verifier gọi là code challenge.

<figure>
    <img src="https://i.imgur.com/rumsDcI.png">
    <figcaption>Hình 2.4. Authorization Code Grant Type + PCKE</figcaption>
</figure>

*Chi tiết các bước:*
1. Người dùng (Chủ sở hữu tài nguyên) truy cập ứng dụng.
2. Ứng dụng chuyển hướng trình duyệt đến authorization endpoint của máy chủ ủy quyền với một yêu cầu ủy quyền bao gồm challenge code cùng với phương pháp được sử dụng để lấy nó. 
3. Máy chủ ủy quyền nhắc người dùng xác thực và đồng ý. Chuyển hướng trình duyệt cho phép máy chủ ủy quyền tương tác với người dùng.
4. Người dùng xác thực và đồng ý yêu cầu.
5. Máy chủ ủy quyền chuyển hướng trở lại URL callback của ứng dụng với authorization code.
6. Ứng dụng gọi token endpoint của máy chủ ủy quyền với một yêu cầu truy cập bao gồm authorization code và code verifier.
7. Máy chủ ủy quyền phản hồi bằng access token (và tùy chọn gửi refresh token).
8. Ứng dụng gọi máy chủ tài nguyên (API) sử dụng access token.

Sau bước 6, máy chủ ủy quyền chuyển đổi code verifier bằng phương pháp chuyển đổi đã nhận được trong bước 2 và kiểm tra xem kết quả có khớp với challenge code ở bước 2. Điều này cho phép máy chủ ủy quyền phát hiện một ứng dụng độc hại đang cố gắng sử dụng authorization code bị đánh cắp. Chỉ ứng dụng hợp pháp mới biết được code verifier để vượt qua.

Đặc tả PKCE liệt kê hai phương pháp biến đổi có thể được sử dụng để lấy challenge code từ trình xác minh mã, cụ thể là "plain" và "S256". Với phương pháp "plain", challenge code và code verifier giống hệt nhau, vì vậy không có biện pháp bảo vệ chống lại thử thách mã bị xâm phạm. Các ứng dụng cấp authorization code với PKCE nên sử dụng phương pháp biến đổi S256 sử dụng base64 URL được mã hóa bằng hàm băm SHA256 của code verifier để bảo vệ nó. 

#### Implicit Grant

OAuth 2.0 xác định implicit grant được tối ưu hóa để sử dụng với các public client. Việc sử dụng loại hỗ trợ này trả về một access token cho một ứng dụng trong một yêu cầu. Nó được thiết kế vào thời điểm khi tiêu chuẩn CORS (Cross-Origin Resource Sharing) không được hỗ trợ rộng rãi trong các trình duyệt nên các trang web chỉ có thể gọi về domain.

<figure>
    <img src="https://i.imgur.com/deeQRC5.png">
    <figcaption>Hình 2.5. OAuth 2.0 Implicit Grant Type</figcaption>
</figure>

*Chi tiết các bước:*
1. Người dùng (Chủ sở hữu tài nguyên) truy cập ứng dụng.
2. Ứng dụng chuyển hướng trình duyệt đến authorization endpoint của máy chủ ủy quyền với yêu cầu ủy quyền.
3. Máy chủ ủy quyền nhắc người dùng xác thực và đồng ý.
4. Người dùng xác thực và đồng ý yêu cầu.
5. Máy chủ ủy quyền chuyển hướng trở lại callback URL của ứng dụng có access token.
6. Ứng dụng sử dụng access token để gọi máy chủ tài nguyên (API).

Implicit grant không còn được khuyến khích vì CORS đã hỗ trợ cho hầu hết các trình duyệt, khả năng rò rỉ access token. Để khắc phục các vấn đề trên có thể sử dụng loại cấp mã ủy quyền (với PKCE) hoặc implicit grant với sự thay thế chế độ phản hồi cung cấp các tùy chọn mới cho các ứng dụng.

#### Resource Owner Password Credentials Grant

Resource Owner Password Credentials Grant hỗ trợ các tình huống trong đó ứng dụng được tin cậy để xử lý thông tin đăng nhập của người dùng cuối và không thể sử dụng loại hỗ trợ nào khác.

<figure>
    <img src="https://i.imgur.com/Qp2UBtn.png">
    <figcaption>Hình 2.6. Resource Owner Password Credentials Grant</figcaption>
</figure>

*Chi tiết các bước:*
1. Người dùng (Chủ sở hữu tài nguyên) truy cập ứng dụng.
2. Ứng dụng nhắc người dùng nhập thông tin đăng nhập của họ.
3. Người dùng cung cấp thông tin đăng nhập của họ cho ứng dụng.
4. Ứng dụng gửi yêu cầu mã thông báo đến token endpoint của máy chủ ủy quyền với thông tin đăng nhập của người dùng.
5. Ứng dụng gửi yêu cầu mã thông báo đến token endpoint của máy chủ ủy quyền với thông tin đăng nhập của người dùng.
6. Ứng dụng gọi máy chủ tài nguyên (API), sử dụng access token.

Điều này thường được thực hiện vì các luồng đăng nhập chuyển hướng qua các trình duyệt trên thiết bị di động được coi là cồng kềnh. Nếu sử dụng, người dùng nên loại bỏ thông tin đăng nhập của họ ngay sau khi nó có access token, để giảm khả năng thông tin đăng nhập bị xâm phạm.

Loại hỗ trợ này không được khuyến khích nhất vì nó làm lộ thông tin đăng nhập của người dùng với ứng dụng và ứng dụng có thể sử dụng thông tin đó để truy cập bất kỳ thông tin nào nó muốn và người dùng không có cách nào ngăn chặn sự lạm dụng này.

Bây giờ khuyến khích sử dụng cấp authorization code (với PKCE) cho ứng dụng gốc sử dụng trình duyệt hệ thống.

#### Client Credentials Grant

Client Credentials Grant được sử dụng khi ứng dụng gọi một API để truy cập tài nguyên mà ứng dụng sở hữu. Ứng dụng sủ dụng loại cấp thông tin xác thực ứng  dụng và xác thực cho máy chủ ủy quyền bằng thông tin đăng nhập của chính nó để có được access token.

<figure>
    <img src="https://i.imgur.com/cuIKKmK.png">
    <figcaption>Hình 2.7. Client Credentials Grant</figcaption>
</figure>

*Chi tiết các bước:*
1. Ứng dụng gửi yêu cầu ủy quyền bao gồm thông tin đăng nhập của ứng dụng vào máy chủ ủy quyền.
2. Máy chủ ủy quyền xác thực thông tin đăng nhập và phản hồi bằng một access token.
3. Ứng dụng gọi máy chủ tài nguyên (API) bằng cách sử dụng access token vừa nhận được.
4. 4-6 Các bước lặp lại như trên nếu access token đã hết hạn vào lần tiếp theo ứng dụng gọi API.

Không cần tương tác của người dùng cuối với máy chủ ủy quyền trong luồng này. Các thông tin xác thực ứng dụng đóng vai trò là ủy quyền cho ứng dụng và được sử dụng để yêu cầu access token từ điểm cuối token.

### Tóm tắt

Giao thức OAuth2.0 cho phép ứng dụng có được ủy quyền để gọi một API thay mặt người dùng hoặc trên danh nghĩa của ứng dụng. Điều này giúp loại bỏ yêu cầu đối với người dùng để chia sẻ thông tin đăng nhập của họ với ứng dụng. Nó cũng cung cấp cho người dùng khả năng kiểm soát tốt hơn về những gì ứng dụng có thể làm và giới hạn về thời lượng truy cập API. Người dùng có thể thu hồi quyền truy cập API cho một ứng dụng riêng lẻ mà không ảnh hưởng đến khả năng của ứng dụng để gọi API thay mặt họ.

Giao thức OAuth 2.0 cung cấp giải pháp ủy quyền, không phải giải pháp xác thực. Bước xác thực trong OAuth 2.0 xác thực người dùng có quyền đồng ý để cho phép một yêu cầu truy cập cho một tài nguyên cụ thể. Sau khi bạn có một ứng dụng được ủy quyền gọi một API, bạn sẽ muốn xác thực người dùng với ứng dụng đó, được đề cập trong phần tiếp theo.

## OpenID Connect
> Trong xã hội với sự tồn tại của con người, không có cảm giác đang sống mà không có ý thức về danh tính. (In the social jungle of human existence, there is no feeling of being alive without a sense of identity.)[name=Erik Erikson, nhà tâm lý học và tâm lý học phát triển người Mỹ gốc Đức, người đã đặt ra cụm từ “Khủng hoảng danh tính”, từ Danh tính: Tuổi trẻ và khủng hoảng (1968)]
> 
Giao thức OpenID Connect (OIDC) cung cấp một lớp dịch vụ xác thực ở phía trên OAuth 2.0, được thiết kế để cho phép các máy chủ ủy quyền xác thực người dùng cho ứng dụng và trả về kết quả theo một cách tiêu chuẩn.

### Vấn đề cần giải quyết
Kịch bản của OIDC được thiết kế để giải quyết việc liên quan đến một người dùng cần được xác thực để truy cập một ứng dụng. OIDC cho phép một ứng dụng ủy thác việc xác thực người dùng cho máy chủ ủy quyền OAuth 2.0, và yêu cầu nó trả về cho ứng dụng các tuyên bố về người dùng được xác thực và sự kiện xác thực ở định dạng tiêu chuẩn. Hình 3.1 minh họa về cách thức hoạt động của nó.

<figure>
    <img src="https://i.imgur.com/MXXUtmZ.png">
    <figcaption>Hình 3.1. Xác thực OIDC</figcaption>
</figure>

Khi người dùng truy cập ứng dụng thông qua trình duyệt, trình duyệt được chuyển hướng đến một máy chủ ủy quyền có triển khai OIDC. Ta gọi máy chủ ủy quyền này là nhà cung cấp OpenID (OP – OpenID Provider). OP tương tác với người dùng để xác thực họ (giả sử họ chưa đăng nhập). Sau khi xác thực, trình duyệt người dùng được chuyển hướng về ứng dụng. Ứng dụng có thể yêu cầu các tuyên bố về người dùng được xác thực mà được trả về trong ID Token. Ngoài ra, nó có thể yêu cầu một OAuth 2.0 access token và sử dụng nó để gọi Userinfo endpoint của OP để thu được các tuyên bố. Vì OIDC là một lớp nằm phía trên OAuth 2.0, một ứng dụng có thể sử dụng OP cho cả việc xác thực và ủy quyền người dùng để gọi API của OP.

### Thuật ngữ

#### Vai trò
* *Người dùng cuối (End User)* - Một chủ thể cần được xác thực (ta sử dụng thuật ngữ "người dùng" để đơn giản và nhất quán).
* *Nhà cung cấp OpenID (OP - OpenID Provider)* - Một máy chủ ủy quyền OAuth 2.0 có triển khai OIDC, và có thể xác thực một người dùng và trả về các tuyên về người dùng được xác thực cũng như sự kiện xác thực cho ứng dụng.
* *Bên đáng tin cậy (RP - Relying Party)* - Một ứng dụng mà ủy quyền xác thực người dùng cho một OP và yêu cầu các tuyên bố về người dùng từ OP. Ta sử dụng thuật ngữ "ứng dụng" cho RP để nhất quán, nhưng một RP có thể là một nhà cung cấp xác thực khác trong các trường hợp sử dụng nâng cao hơn.

#### Các loại client
Bao gồm confidential và public client cũng như native application đã xác định ở phần OAuth 2.0.

#### Token và Authorization Code
OIDC sử dụng authorization code, access token, refresh token (như mô tả trong phần OAuth 2.0) và ID token. ID token là một token được sử dụng để truyền tải các tuyên bố về một sự kiện xác thực và một người dùng được xác thực cho ứng dụng.
ID token được encode dạng JSON Web Token (JWT). 

#### UserInfo Endpoint
Một ứng dụng có thể truy xuất các tuyên bố về một người dùng từ UserInfo endpoint của OP. Nó là một OAuth 2.0 API endpoint, và để gọi nó thì cần có một access token được cấp bới OP. Khi yêu cầu access token, ứng dụng sử dụng tham số scope để chỉ ra các tuyên bố mong muốn về người dùng. OP xác thực người dùng và có được sự chấp thuận cho các tuyên bố được yêu cầu, và sau đó cấp access token với phạm vi được ủy quyền cho các tuyên bố đối với ứng dụng. Ứng dụng sau đó sử dụng access token để yêu cầu các tuyên bố từ UserInfo endpoint.

Ứng dụng nên thực hiện xác thực đối với các phản hồi do OP cụ thể đề xuất.

UserInfo endpoint chủ yếu là hữu ích nếu các tuyên bố hồ sơ người dùng mong muốn quá lớn đối với ID token được trả về thông qua URL Fragment.


### Cách thức hoạt động
OIDC xác định 3 luồng khác nhau mà theo đó một ứng dụng có thể tương tác với một OP để thực hiện một yêu cầu xác thực.

#### Luồng OIDC
Luồng OIDC được thiết kế xung quanh các ràng buộc của các loại ứng dụng khác nhau và có một số điểm tương đồng với các loại grant được xác định trong OAuth 2.0. OIDC gốc xác định các luồng sau:
* Luồng Authorization Code
* Luồng Implicit
* Luồng Hybrid

#### Luồng OIDC Authorization Code
Luồng này tương tự với OAuth 2.0 authorization code grant khi dựa vào hai yêu cầu và mã ủy quyền trung gian. Hình 3.3 mô tả luồng này, ta giả định rằng ứng dụng yêu cầu cả 3 token và người dùng không tồn tại phiên đăng nhập hiện có. Sơ đồ trong hình có sử dụng PKCE.

<figure>
    <img src="https://i.imgur.com/3RE9fot.png">
    <figcaption>Hình 3.3. Luồng OIDC Authorization Code</figcaption>
</figure>

*Chi tiết các bước:*
1. Người dùng truy cập vào ứng dụng.
2. Trình duyệt người dùng được chuyển hướng đến OP với một yêu cầu xác thực.
3. OP tương tác với người dùng để xác thực và để có được sự đồng ý cho phạm vi yêu cầu truy cập thông tin người dùng.
4. Người dùng xác thực và chấp thuận, và OP tạo hoặc cập nhật phiên xác thực cho người dùng.
5. Trình duyệt người dùng được chuyển hướng trở lại về ứng dụng kèm với authorization code.
6. Ứng dụng gửi yêu cầu token đến OP với authorization code.
7. OP phản hồi lại với ID token, access token, và refresh token (tùy chọn).
8. Ứng dụng có thể sử dụng access token để truy cập vào UserInfo endpoint của OP.

Các ứng dụng thuộc loại public client mà không thể duy trì một cách an toàn một bí mật cho xác thực như vậy có thể sử dụng PKCE. Việc sử dụng PKCE được thiết kế để giảm thiểu rủi ro của authorization code bị chặn bởi một bên trái phép.

#### Luồng OIDC Implicit
Luồng này tương tự với loại OAuth 2.0 grant cùng tên. Hình 3.4 biểu diễn luồng này với ứng dụng chỉ nhận ID token.

<figure>
    <img src="https://i.imgur.com/46S8ety.png">
    <figcaption>Hình 3.4. Luồng OIDC Implicit</figcaption>
</figure>

*Chi tiết các bước:*
1.	Người dùng truy cập vào ứng dụng.
2.	Trình duyệt người dùng được chuyển hướng đến OP với yêu cầu xác thực.
3.	OP tương tác với người dùng để xác thực và có được sự đồng ý cho phạm vi yêu cầu truy cập thông tin người dùng.
4.	Người dùng cung cấp các chứng thực đăng nhập và sự chấp thuận, và OP tạo hoặc cập nhật một phiên xác thực cho người dùng.
5.	Trình duyệt người dùng được chuyển hướng trở về ứng dụng cùng với một ID token.
6.	Ứng dụng có được các tuyên bố về người dùng từ ID token và hiển thị các nội dung ứng dụng phù hợp cho người dùng.

Ngoài việc OP phản hồi lại với ID token, ta cũng có thể yêu cầu OP cung cấp thêm access token, nhưng việc này là không nên vì nó dễ bị lộ. Ta chỉ nên sử dụng luồng Implicit để chỉ trả về ID token, với giả định rằng ID token không chứa dữ liệu nhạy cảm.
Các public client mà cần một access token và/hoặc ID token với các thành phần nhạy cảm nên xem xét sử dụng luồng Authorization Code với PKCE để thay thế.

#### Luồng OIDC Hybrid
Luồng này bao gồm các thành phần của cả 2 luồng Authorization Code và Implicit. Nó được thiết kế cho các ứng dụng có cả back-end bảo mật, và front-end với JavaScript phía client thực thi trong trình duyệt. Luồng này cho phép các mô hình như trả về ID token và authorization code trong phản hồi front-channel cho front-end của ứng dụng, trả về access token (có thể thêm refresh token) cho back-end của ứng dụng bằng authorization code. Luồng này được mô tả như hình 3.5.

<figure>
    <img src="https://i.imgur.com/l8sTLsA.png">
    <figcaption>Hình 3.5. Luồng OIDC Hybrid</figcaption>
</figure>

*Chi tiết các bước:*
1.	Người dùng truy cập ứng dụng.
2.	Trình duyệt người dùng được chuyển hướng đến OP với yêu cầu xác thực.
3.	OP tương tác với người dùng để xác thực và có được sự đồng ý cho phạm vi yêu cầu truy cập thông tin người dùng.
4.	Người dùng xác thực và cung cấp sự chấp thuận, và OP tạo hoặc cập nhật một phiên xác thực cho người dùng.
5.	Trình duyệt người dùng được chuyển hướng trở về front-end ứng dụng với authorization code và ID token.
6.	Ứng dụng xác minh ID token, nếu hợp lệ, back-end gọi token endpoint với authorization code để có thêm các token.
7.	OP trả về các token được yêu cầu.
8.	Ứng dụng có thể gọi UserInfo endpoint của OP với access token.

Ngoài trả về authorization code và ID token từ Authorization endpoint, ta có thể yêu cầu trả về authorization code và access token, hoặc authorization code, ID token và access token, nhưng 2 chế độ phản hồi này không được khuyến khích sử dụng.

Trong thực tế, luồng Hybrid không được sử dụng rộng rãi. Sử dụng luồng này yêu cầu một triển khai phức tạp. Các ứng dụng nên xem xét sử dụng luồng Authorization Code với PKCE, trừ khi chúng có những use-case đặc biệt mà yêu cầu luồng Hybrid.

### Tóm tắt
Giao thức OIDC cung cấp một lớp xác thực phía trên OAuth 2.0 mà có hỗ trợ xác thực người dùng cho ứng dụng. Sử dụng OIDC cho phép ứng dụng ủy thác xác thực người dùng cho một nhà cung cấp OpenID. Kết hợp OIDC và OAuth 2.0 có thể giải quyết cả xác thực và ủy quyền API.

## SAML 2.0
> Việc được tin cậy là lời khen ngợi quý giá hơn cả việc được yêu quý. (To be trusted is a greater compliment than to be loved.) [name=George MacDonald, từ The Marquis of Lossie (1877)]

Ngôn ngữ đánh dấu xác nhận bảo mật (Security Assertion Markup Language - SAML) 2.0 được biết đến với việc cung cấp hai tính năng quan trọng: đăng nhập một lần giữa nhiều tên miền (cross-domain single sign-on - SSO) và liên kết danh tính (identity federation).

### Thuật ngữ
* *Chủ thể (Subject)* - Một thực thể về thông tin bảo mật sẽ được trao đổi. Chủ thể thường đề cập đến một người, nhưng có thể là bất kỳ thực thể nào có khả năng xác thực, bao gồm cả một chương trình phần mềm. Trong bài này, chủ thể thường là người dùng ứng dụng.
* *Xác nhận SAML (SAML Assertion)* - Một thông điệp dựa trên XML có chứa thông tin bảo mật về một chủ thể.
* *Hồ sơ mô tả SAML (SAML Profile)* - Một đặc tả định nghĩa cách sử dụng thông điệp SAML cho một trường hợp sử dụng, ví dụ như đăng nhập một lần giữa nhiều tên miền.
* *Nhà cung cấp danh tính (Identity Provider)* - Một vai trò được định nghĩa trong hồ sơ mô tả đăng nhập một lần giữa nhiều tên miền. Nhà cung cấp danh tính là một máy chủ cung cấp các xác nhận SAML về một chủ thể được xác thực, trong bối cảnh đăng nhập một lần giữa nhiều tên miền.
* *Nhà cung cấp dịch vụ (Service Provider)* - Một vai trò khác được định nghĩa trong hồ sơ mô tả đăng nhập một lần giữa nhiều tên miền. Nhà cung cấp dịch vụ ủy quyền xác thực cho nhà cung cấp danh tính và dựa vào thông tin về chủ thể được xác thực trong xác nhận SAML do nhà cung cấp danh tính cung cấp trong bối cảnh đăng nhập một lần giữa nhiều tên miền.
* *Mối quan hệ tin cậy (Trust Relationship)* - Thỏa thuận giữa nhà cung cấp dịch vụ SAML và nhà cung cấp danh tính SAML, theo đó nhà cung cấp dịch vụ tin cậy các xác nhận do nhà cung cấp danh tính cung cấp.
* *Liên kết giao thức SAML (SAML Protocol Binding)* - Mô tả cách các phần tử trong thông điệp SAML được ánh xạ vào các giao thức truyền thông tiêu chuẩn, chẳng hạn như HTTP, để truyền giữa nhà cung cấp dịch vụ và nhà cung cấp danh tính. Trong thực tế, các thông điệp phản hồi và yêu cầu SAML (SAML request and response messages) thường được gửi qua HTTPS bằng cách sử dụng HTTP-Redirect hoặc HTTP-POST, sử dụng các liên kết HTTP-Redirect và HTTP-POST tương ứng.

### Đăng nhập một lần (Single Sign-On)
#### Vấn đề cần giải quyết
Giả sử trường hợp có một người dùng cần truy cập đến nhiều ứng dụng với các tên miền khác nhau, ví dụ như application1.com và application2.com. Nếu không có đăng nhập một lần, người dùng có thể phải tạo tài khoản và đăng nhập riêng lẻ với từng ứng dụng, điều này có nghĩa là người dùng cần phải nhớ nhiều tên đăng nhập và mật khẩu khác nhau.
#### Định nghĩa
Đăng nhập một lần (SSO) là khả năng mà SAML cho phép các ứng dụng ủy quyền xác thực người dùng cho nhà cung cấp danh tính (Identity Provider). Nhà cung cấp danh tính xác thực người dùng và trả về ứng dụng một xác nhận với thông tin về người dùng được xác thực và sự kiện xác thực đó. Nếu người dùng truy cập vào ứng dụng thứ hai có ủy quyền xác thực cho cùng một nhà cung cấp danh tính với ứng dụng thứ nhất, người dùng sẽ có thể truy cập vào ứng dụng thứ hai mà không cần đăng nhập lại.
#### Đăng nhập một lần do Nhà cung cấp dịch vụ khởi tạo (SP-Initiated SSO)
Hình thức đăng nhập một lần giữa nhiều tên miền đơn giản nhất được minh họa trong sơ đồ dưới đây. Trong ví dụ này, người dùng bắt đầu tại nhà cung cấp dịch vụ (service provider - SP) (ứng dụng). Sơ đồ giả định rằng người dùng hiện không có phiên xác thực tại nhà cung cấp danh tính và do đó phải xác thực danh tính.

<figure>
    <img src="https://i.imgur.com/grER9va.png">
    <figcaption>Hình 4.1. Đăng nhập một lần do Nhà cung cấp dịch vụ khởi tạo</figcaption>
</figure>

*Chi tiết các bước:*
1. Người dùng truy cập vào nhà cung cấp dịch vụ (ứng dụng).
2. Nhà cung cấp dịch vụ chuyển hướng trình duyệt của người dùng đến nhà cung cấp danh tính bằng yêu cầu xác thực SAML (SAML authentication request).
3. Nhà cung cấp danh tính tương tác với người dùng để xác thực.
4. Người dùng xác thực. Nhà cung cấp danh tính xác thực thông tin đăng nhập.
5. Nhà cung cấp danh tính chuyển hướng trình duyệt của người dùng trở lại nhà cung cấp dịch vụ với phản hồi SAML (SAML response) chứa xác nhận xác thực SAML (SAML authentication assertion). Phản hồi này được gửi đến URL dịch vụ xác nhận người dùng (Assertion Consumer Service - ACS) của nhà cung cấp dịch vụ.
6. Nhà cung cấp dịch vụ sử dụng và kiểm tra tính hợp lệ của phản hồi SAML và phản hồi lại yêu cầu ban đầu của người dùng (giả sử người dùng đã được xác thực thành công và có đủ quyền cho yêu cầu đó).

#### Đăng nhập một lần do Nhà cung cấp danh tính khởi tạo (IdP-Initiated SSO)
SAML cũng định nghĩa 1 luồng đăng nhập một lần khác, được gọi là “do nhà cung cấp danh tính khởi tạo”, trong đó người dùng bắt đầu tại nhà cung cấp danh tính. Trong trường hợp này, nhà cung cấp danh tính chuyển hướng trình duyệt của người dùng đến nhà cung cấp dịch vụ bằng phản hồi SAML mà nhà cung cấp dịch vụ không phải gửi bất kỳ yêu cầu xác thực nào. Luồng này được tìm thấy trong một số môi trường doanh nghiệp nơi người dùng truy cập các ứng dụng qua một cổng thông tin công ty.
Luồng đăng nhập một lần do nhà cung cấp khởi tạo được thể hiện trong sơ đồ dưới đây (sơ đồ giả định rằng người dùng hiện không có phiên xác thực).

<figure>
    <img src="https://i.imgur.com/w0L27kC.png">
    <figcaption>Hình 4.2. Đăng nhập một lần do Nhà cung cấp danh tính khởi tạo</figcaption>
</figure>

*Chi tiết các bước:*
1. Người dùng truy cập vào cổng thông tin công ty.
2. Cổng thông tin chuyển hướng trình duyệt của người dùng đến nhà cung cấp danh tính bằng yêu cầu xác thực SAML.
3. Nhà cung cấp danh tính tương tác với người dùng để xác thực.
4. Người dùng xác thực. Nhà cung cấp danh tính xác thực thông tin đăng nhập.
5. Nhà cung cấp danh tính chuyển hướng trình duyệt của người dùng trở lại cổng thông tin với phản hồi SAML cho cổng (phản hồi số 1) có chứa xác nhận xác thực. Người dùng được đăng nhập vào cổng thông tin có hiển thị nội dung cho người dùng, trong đó bao gồm danh sách các ứng dụng.
6. Người dùng nhấp vào một liên kết trong cổng thông tin để mở một ứng dụng. Liên kết chuyển hướng trình duyệt của người dùng đến nhà cung cấp danh tính với một tham số cho biết ứng dụng của nhà cung cấp dịch vụ mong muốn. Nhà cung cấp danh tính kiểm tra phiên xác thực của người dùng. Sơ đồ này giả định phiên của người dùng vẫn còn hợp lệ.
7. Nhà cung cấp danh tính chuyển hướng trình duyệt của người dùng đến URL dịch vụ xác nhận người dùng (Assertion Consumer Service - ACS) của nhà cung cấp dịch vụ, với phản hồi SAML mới (phản hồi số 2) cho nhà cung cấp dịch vụ đó (ứng dụng).
8. Nhà cung cấp dịch vụ sử dụng phản hồi SAML và xác nhận xác thực, sau đó hiển thị một trang thích hợp cho người dùng (giả sử người dùng có đủ danh tính và quyền cho yêu cầu đó).

### Liên kết Danh tính (Identity Federation)
#### Định nghĩa
Liên kết danh tính (identity federation) là cơ chế SAML cung cấp cho ứng dụng và nhà cung cấp danh tính (identity provider) sử dụng một định danh của người dùng được chia sẻ chung nhằm trao đổi thông tin về người dùng đó. Điều này cho phép nhà cung cấp dịch vụ ủy quyền xác thực người dùng cho nhà cung cấp danh tính và nhận lại xác nhận xác thực.

Với SAML, liên kết danh tính thiết lập một thỏa thuận nhận dạng được sử dụng giữa nhà cung cấp dịch vụ (ứng dụng) và nhà cung cấp danh tính để tham chiếu đến một chủ thể (người dùng). Điều này cho phép nhà cung cấp dịch vụ ủy quyền xác thực người dùng cho nhà cung cấp danh tính và nhận lại xác nhận xác thực với các yêu cầu nhận dạng bao gồm nhận dạng cho chủ thể được xác thực - chủ thể sẽ nhận dạng được bởi nhà cung cấp dịch vụ.
#### Ví dụ
Một người dùng tên là Ann Smith có một tài khoản ở hai ứng dụng, application1 tại app1.com và application2 tại app2.com. Trong application1, định danh tài khoản của cô ấy là ann@corp.com và trong application2, định danh tài khoản của cô ấy là “ann”. Ann cũng có một tài khoản tại một nhà cung cấp danh tính doanh nghiệp, nơi nhận dạng tài khoản của cô ấy là ann@corp.com.
Quản trị viên của application1 và nhà cung cấp danh tính trao đổi siêu dữ liệu (metadata) về môi trường của họ và sử dụng nó để thiết lập thông tin liên kết giữa application1 và nhà cung cấp danh tính. Điều tương tự cũng được thực hiện bởi các quản trị viên của application2 và nhà cung cấp danh tính. Trên thực tế, quản trị viên của nhà cung cấp danh tính định cấu hình nó để gửi các xác nhận đến từng nhà cung cấp dịch vụ có chứa các nhận dạng và thuộc tính thích hợp cho nhà cung cấp dịch vụ (ứng dụng).

<figure>
    <img src="https://i.imgur.com/jN6x37K.png">
    <figcaption>Hình 4.3. Liên kết danh tính</figcaption>
</figure>

Khi Ann truy cập application1, ứng dụng này sẽ chuyển hướng trình duyệt của cô ấy đến nhà cung cấp danh tính tại “corp.com”. Nhà cung cấp danh tính xác thực Ann và chuyển hướng trình duyệt của cô ấy trở lại application1 với xác nhận xác thực có chứa thuộc tính xác định cô ấy là ann@corp.com. Application1 sử dụng cùng một định danh cho Ann, vì vậy ứng dụng này nhận ra cô ấy dựa trên danh tính đó.
Khi Ann truy cập application2, ứng dụng sẽ chuyển hướng trình duyệt của cô ấy đến nhà cung cấp danh tính mà đã nhận dạng rằng cô ấy đã có một phiên làm việc. Tuy nhiên, nếu nhà cung cấp danh tính trả về một xác nhận xác thực xác định cô ấy là ann@corp.com, application2 sẽ không công nhận cô ấy là người dùng hợp lệ bằng tên đó. Nhà cung cấp dịch vụ nhận dạng cần trả lại một nhận dạng thích hợp cho từng nhà cung cấp dịch vụ. Trong trường hợp này, khi nhà cung cấp danh tính gửi xác nhận xác thực đến application2, nhà cung cấp danh tính cần xác định chủ thể của xác nhận bằng cách sử dụng “ann”. Cách tiếp cận được dùng là thiết lập khi hai bên trao đổi siêu dữ liệu và định cấu hình cơ sở để thiết lập mối quan hệ (liên kết) giữa nhà cung cấp dịch vụ và nhà cung cấp danh tính.

### Xác thực trung gian (Authentication Brokers)
Các ứng dụng có thể sử dụng xác thực trung gian để dễ dàng hỗ trợ nhiều giao thức và cơ chế xác thực khác nhau. Xác thực trung gian cho phép ứng dụng triển khai một giao thức nhận dạng mới hơn như OIDC và dựa vào xác thực trung gian để giao tiếp qua các giao thức khác nhau với nhiều nhà cung cấp danh tính khác nhau.
Hình dưới đây mô tả một ứng dụng được triển khai để sử dụng OIDC và OAuth 2.0 với một xác thực trung gian giao tiếp lần lượt với một số nhà cung cấp danh tính, mỗi nhà cung cấp sử dụng một giao thức khác nhau. Việc sử dụng xác thực trung gian cho phép nhóm phát triển ứng dụng triển khai các giao thức nhận dạng mới hơn trong ứng dụng của họ và tập trung vào các tính năng cốt lõi của ứng dụng thay vì tốn thời gian để trực tiếp triển khai và hỗ trợ các giao thức nhận dạng cũ hơn do khách hàng yêu cầu.

<figure>
    <img src="https://i.imgur.com/UytWWAt.png">
    <figcaption>Hình 4.4. Lợi ích của xác thực trung gian</figcaption>
</figure>

### Tóm tắt
SAML 2.0 cung cấp giải pháp tiêu chuẩn công nghiệp cho đăng nhập một lần trên web và liên kết danh tính. Các tính năng chính này cho phép doanh nghiệp sử dụng các ứng dụng đám mây mà vẫn duy trì quyền kiểm soát tập trung đối với danh tính. Việc sử dụng SAML giúp loại bỏ khả năng hiển thị thông tin đăng nhập mật khẩu tĩnh đối với các ứng dụng và cung cấp cho người dùng sự tiện lợi khi đăng nhập một lần. Nhiều doanh nghiệp đã triển khai các nhà cung cấp danh tính SAML và mong muốn các nhà cung cấp phần mềm dưới dạng dịch vụ (SaaS application) hỗ trợ nó.

## Tổng kết

OAuth 2.0, OIDC và SAML 2.0 được tạo ra cho các mục đích khác nhau, vì thế chúng cũng có những điểm khác biệt (như đã trình bày ở trên), sau đây là tóm tắt đơn giản cho bạn đọc:

| | OAuth 2.0 | Open ID Connect | SAML 2.0 |
|---|---|---|---|
| Mục đích | Liên quan đế sự ủy quyền truy cập vào 1 tài nguyên mà người dùng sở hữu | Liên quan đến việc xác thực ngươi dùng | SAML cũng dùng để xác thực người dùng nhưng nó thường thấy nhiều hơn ở trong các tập đoàn/công ty  | 
| Điểm mạnh | Cung cấp nền tảng ủy quyền người dùng, người dùng không còn phải đăng nhập mỗi khi cần lấy thông tin của mình trên Resource Server | Cung cấp dịch vụ xác thực cho người dùng không trong môi trường doanh nghiệp, OIDC dễ cấu hình hơn so với SAML và đôi khi cũng có use case OIDC dùng để ủy quyền thay vì OAuth 2.0 | Ra đời sớm, cung cấp nhiều tính năng nổi bật và là công cụ mạnh mẽ hỗ trợ xác thực người dùng trong doanh nghiệp |
| Hạn chế | Chỉ hỗ trợ ủy quyền  | Là giao thức mới hơn và đang phát triển, vì thế chưa hỗ trợ nhiều tính năng (như Single Sign-on trong SAML 2) | Chỉ hỗ trợ xác thực người dùng, không hỗ trợ ủy quyền, cài đặt phức tạp|
| Ngữ cảnh sử dụng | Người dùng muốn ủy quyền cho example.com có thể đọc được cái bài đăng trên twitter.com của mình mà không cần phải cung cấp mật khẩu cho example.com | Người dùng muốn đăng nhập vào example.com bằng tài khoản twitter thay vì phải tạo 1 tài khoản/mật khẩu khác gắn với example.com, tạo 1 tài khoản, dùng nhiều chỗ | Nhân viên có thể đăng nhập vào các bộ phận của công ty, các application hay các trang nội bộ mà không phải đăng nhập lại ở mỗi lần truy cập, nhờ có SAML, người nhân viên chỉ cần đăng nhập 1 lần cho tất cả các lần xác thực khi truy cập vào các ứng dụng của công ty. |

### Tài liệu tham khảo
[Solving Identity Management Applications | Yvonne Wilson & Abhishek Hingnikar](https://www.amazon.com/Solving-Identity-Access-Management-Applications/dp/148425094X)

### Appendix and FAQ

:::info
**Find this document incomplete?** Leave a comment!
:::

###### tags: `Identity` `OAuth` `OpenID` `SAML`
