# OpenID Connect (OIDC)
OpenID Connect (OIDC) 是一種在 OAuth 2.0 框架之上運行的開放式身份驗證協議。OIDC 針對消費者,允許個人使用單點登錄 (SSO)訪問使用 OpenID 提供商 (OP)(例如電子郵件提供商或社交網絡)的依賴方站點,以驗證其身份。它為應用程序或服務提供有關用戶的信息、身份驗證的上下文以及對其配置文件信息的訪問權限。
- 角色定義:

- 通常使用流程:

## what is different with OPENID?
OpenID是由非營利組織 OpenID Foundation推動的一種開放標準和去中心化的 認證 協議。它允許用戶通過使用第三方身份提供程序 (IDP) 服務的合作站點(稱為依賴方,或 RP)進行身份驗證,從而無需網站管理員提供他們自己的臨時登錄系統,並允許用戶登錄多個不相關的網站,而不必為每個網站設置單獨的身份和密碼。
OpenID Connect 執行許多與 [OpenID 2.0](https://openid.net/specs/openid-authentication-2_0.html) 相同的任務,但以 API 友好的方式執行,並且可供本機和移動應用程序使用。OpenID Connect 定義了用於可靠簽名和加密的可選機制。OAuth 1.0a 和 OpenID 2.0 的集成需要擴展,而在 OpenID Connect 中,OAuth 2.0 功能與協議本身集成在一起。[more info](https://security.stackexchange.com/questions/44797/when-do-you-use-openid-vs-openid-connect)
## Specifications
### Core
#### ***ID Token***
ID Token是由JWT所組成透過JWS(簽證)進形實作組要構成有三個部分
part|description
---|---
header|包含簽章使用的演算法,一般常見最簡單的是 HS256,也就是只有一組金鑰做雜湊來產生簽章,要驗證簽章就一定要這組金鑰;另外一種常見的也是今天主題的重點:RS256,RS256 採用非對稱加密的方式,也就是分別會有公私鑰兩組金鑰,通常會在 server 端使用私鑰來簽章,而 client 端則使用公鑰來驗證簽章是否正確。
payload|裡面包含整個 token 的主要資訊。
signature|每個 JWT token 之所以不容易被竄改,都是靠這個簽章運作的,簽章是針對 header 和 payload 所產生的唯一資訊,因此只要有一個地方被竄改,簽章就會不一樣,我們就會視為這是個不合法的 JWT token。
```
BASE64URL(UTF8(JWS Protected Header)) || '.' ||
BASE64URL(JWS Payload) || '.' ||
BASE64URL(JWS Signature)
```
透過JWT解出來的內容會類似這樣

[ID token實際上需要透過server提供的公鑰(JWK)進行驗證後,就能知道id token的合法性。](https://fullstackladder.dev/blog/2023/01/28/openid-validate-token-with-rs256-and-jwks/)
[這邊提供js sample code](https://viewsonic-ssi.visualstudio.com/myviewboard.com/_git/mvb-auth0?path=/docs/example/jwt/example.js&version=GBdev&anchor=support-flow)
ID token的payload必須符合下面定義規範包含所屬參數,各參數的定義如下
parameter|description
---|---
iss|發布者的URL
sub|subject identifier。通常用來代表特定End-user的識別碼
aud|token逾傳送的對象。通常會是client ID的形式
exp|id token 到期時間
iat|發布 (issue)的時間
nonce|用來防止replay attack。回傳RP在發出認證請求 (authentication request)時,所攜帶的隨機數 (如果RP有傳送它的話就應該被回傳)
c_hash|authorization code的雜湊值。用來驗證其完整性
at_hash|access token的雜湊值。用來驗證其完整性
#### ***Authentication Request***
使用發現端點查找授權端點的URL。
parameter|description
---|---
response_type |應始終為code。
client_id |註冊在server上的client id
redirect_uri |授權完成時響應將發送到的 URI。必須來自此客戶端的預註冊 URI 列表。
scope |客戶端請求授權的範圍的空格分隔列表。所有請求都必須包含openid 。要接收刷新令牌,請包含offline_access。還應包括確定同意類型的特定範圍。
nonce| 用於將客戶端會話與 ID 令牌相關聯並減輕replay attack的字符串值。每個客戶的每個請求必須是唯一的.
prompt| 登錄非 offline_access 範圍,同意offline_access 範圍。
state| 用於維護請求和回調之間狀態的不透明值。
ui_locales| BCP47 語言標籤的空格分隔列表。
發起範例
```
HTTP/1.1 302 Found
Location: https://server.example.com/authorize?
response_type=code
&scope=openid%20profile%20email
&client_id=s6BhdRkqt3
&state=af0ifjsldkj
&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
```
#### ***Token Request***
使用發現端點查找令牌端點的 URL。
parameter|description
---|---
grant_type |authorization_code或refresh_token,具體取決於代碼的類型。
code |從授權端點返回的授權代碼,或從令牌端點返回的刷新令牌。必須匹配指定的grant_type。
redirect_uri |與請求授權端點相同。
### Discover
必須在先前指定的路徑上使用 HTTP GET 請求查詢 OpenID 提供者配置文件
```
GET /.well-known/openid-configuration HTTP/1.1
Host: example.com
```
欄位| 必要| 說明
---|---|---|
issuer| REQUIRED| 在拿到 ID token 時,iss 會與此欄位的值一樣
authorization_endpoint| REQUIRED| OpenID Connect 啟動身分驗證的入口
token_endpoint| REQUIRED / OPTIONAL| OpenID Connect 讓 Client 取得 token 的端口。如果只支援 Implicit Flow 則不需要
userinfo_endpoint| RECOMMENDED| 透過 token 取得使用者個資的端口
jwks_uri| REQUIRED| 這裡會放 JWK Set 的內容,可以使用此內容來作為 JWK 處理,通常這裡放的是公鑰
registration_endpoint| RECOMMENDED| 動態註冊的端口
scopes_supported| RECOMMENDED| 支援哪些 Scope
response_types_supported| REQUIRED| 指 response_type 有哪些可以用
response_modes_supported| OPTIONAL| 指 response_mode 有哪些可以用
grant_types_supported| OPTIONAL| 如 authorization_code、implicit 等
- [google discover](https://accounts.google.com/.well-known/openid-configuration)
- [azure discover](https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration)
### Authorization Flow
- [流程類型](https://viewsonic-ssi.visualstudio.com/myviewboard.com/_git/mvb-auth0?path=/README.md&version=GBdev&_a=preview&anchor=support-flow)

- 適用情境

#### ***CODE + PKCE***

先解釋兩個參數:
- Code Verifier: 一個特殊字串,長度限制為 43 ~ 128 之間。
- Code Chanllenge: 透過 SHA 256 將 Code Verifier 轉換過的字串。
接下來要解釋一下,這兩個字串如何能夠讓 OAuth2 的流程中安全性增加。由於 SHA256 是不可逆且較安全的加密模式,並且在資料的傳輸上先提供 Code Chanllenge 再來是 Code Verifier 可以確保著交握的兩端都是同一個人,因為必須要同時都有兩個才能正確地確認。 這樣就算原本的 code 被竊取到了,也會因為無法產生正確的 Code Verifier 讓惡意程式無法竊取到資料。
講簡單就是送出Authentication Request帶入code_chanllenge,當取得code後轉發出Token Request的時候帶入code_verifier,server side透過SHA256比對code_chanllenge是不是由code_verifier產生。如果是就核發access_token。
### Logout Flow



## Development
開發oidc相關驗證功能我認為不要自己開發,除非對文件是非常熟捻,不然正常情況下基本上石做一定會漏東漏西,因為有太多小細節。建議是使用oidc官方認證過的一些opensource進行轉開發,大概80%基本的功能與流程都根據RFC規範已經實作完畢,通常有遺漏實作的都是2019年以後推出新規範,像是open banking所定義的FAPI(Financial-grade API Security Profile)。

https://openid.net/developers/certified/
https://openid.net/certification/#OPs
## Learning Resource
[IT幫幫忙](https://ithelp.ithome.com.tw/users/20102562/ironman/2923?page=3)
[Auth0](https://auth0.com/docs/authenticate/login/oidc-conformant-authentication)
[azure oidc doc](https://learn.microsoft.com/zh-tw/azure/active-directory/develop/v2-oauth2-auth-code-flow)
###### tags: `oidc` `authentication`