---
# System prepended metadata

title: OpenID Connect (OIDC)
tags: [authentication, oidc]

---

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

- 角色定義:
![](https://i.imgur.com/Y68ed48.png)
- 通常使用流程:

![](https://i.imgur.com/pVZ6h8m.png)


## 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解出來的內容會類似這樣
![](https://i.imgur.com/5VNon2l.png)

[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)
![](https://i.imgur.com/YGVLJe4.png)
- 適用情境
![](https://i.imgur.com/PDR8nJb.png)

#### ***CODE + PKCE***
![](https://i.imgur.com/DP9nMpT.png)
先解釋兩個參數:

- 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
![](https://i.imgur.com/Yy8I5ez.png)
![](https://i.imgur.com/MnlIQuU.png)
![](https://i.imgur.com/9LGr0lZ.png)



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

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` 
