OIDC
,OAuth
OIDC 是一種基於 OAuth 2.0 的身份認證協議,允許使用者端通過 Authorization Server 驗證使用者身份,並以標準的 ID Token
獲取使用者的基本資訊。
OAuth 只討論如何授權(authorization),並沒有明確定義身分驗證(authentication)機制,而 OIDC 協定補足了這部分缺漏。
資源擁有者,基本上就是使用者
想要取得 user 認證及授權的 client 端,必須在 Authorization Server 有註冊。
Attributes | description | 範例 |
---|---|---|
client_id | OIDC Client ID | awesome-service |
audience | 允許接受 ID Token 的 URI | https://awesome.burgess.com |
redirect_uri | 登入後轉導的頁面 | https://awesome.burgess.com/login/callback |
backchannel_logout_uri | 主動發送登出請求給 client 端的 URI | https://awesome.burgess.com/logout/callback |
post_logout_redirect_uris | 登出後轉導的頁面 | https://awesome.burgess.com/logout/backchannel |
註冊後 Authorization Server 會發給 client 端一個 client_secret
,之後換 ID_TOKEN
會用到
路徑 | 說明 |
---|---|
GET /oauth2/auth | 取得 Authorization Code |
POST /oauth2/token | 取得 ID Token |
登入成功後就可以拿 ID Token
去取得 user info
state 由 OIDC Client 隨機生成,之後步驟可與 Authorization Server 回傳的 state 比對,目的是為了確認轉導過程中的使用者都是同一個人,防止 CSRF 攻擊。
scope 為這次 OIDC Client 想取得使用者的 scope,依 ORY Hydra Authentication
,登入驗證並取得 ID Token 的 scope 是填 openid
步驟 (2) 其他所需的參數可在這回傳。
透過 GET 方法發送至 authorize endpoint
GET 參數
parameters | description |
---|---|
client_id | OIDC Client ID,要跟 Authorization Server 註冊的一致 |
nonce | 隨機字串,驗證後會存在 ID Token 內 |
backchannel_logout_uri | 主動發送登出請求給服務的 URI |
redirect_uri | 登入後轉導的頁面,要跟 Authorization Server 註冊的一致 |
response_type | 回應類型,通常固定填 code |
scope | 登入驗證並取得 ID Token 的 scope 為 openid |
state | 為避免 CSRF 攻擊的一個隨機字串 |
Authorization Server 會回傳一個 302 轉址到 redirect_uri 的訊息給 UserAgent,轉址內容含有 Authorization code, state and scope 等參數。
redirect_uri 必須是該 Client ID 在 Authorization Server 註冊的 uri
步驟 (1) OIDC Client 有回傳 state
,這時可驗證從 Authorization Server 轉導回來的 state
是否跟先前發出的一致。
ID Token
透過 POST 方法發送至 token endpoint
Basic access authentication : 通常為註冊的 client_id
與 註冊完 Authorization Server 發的 client_secret
之組合。client_id
:client_secret
的 base64 編碼的 credentials,再放到 header 中,以下為 Basic access authentication 內容範例:
parameters | description |
---|---|
code | 先前拿到的 Authorization Code |
grant_type | 採用到授權方式,授權碼授權方式基本上填 authorization_code |
redirect_uri | Authorization Server 的 callback 網址,必須跟步驟 (2) 一樣 |
驗證成功後 redirect_uri 會拿到 ID Token
& access token
,ID Token
帶有使用者資訊,access token
則是使用者授權使用某些服務或取得某些資訊的權限,換句話說,得到授權的 service 可以透過 access token
呼叫授權方的 API,使用某些服務或取得某些資訊。
token 很重要,要避免外洩,一般只會放在後端能存取的地方,應避免放在 cookie 或 LocalStorage 等等前端 user 可以查看的地方。
ID Token
是 JWT 格式,通常 payload 會紀錄使用者 ID、token 有效期限、發行單位、發行時間、OIDC Client ID、Authorization Server Login Session ID 等等資訊。
拿到 ID Token
之後要檢查一下下列資料:
RS256
exp
)是否有過期iss
)是否為 Authorization Serveraud
)是不是 OIDC Client 自己的 client_idID Token
是有可能被竄改的,因此可以用 Authorization Server 提供的 public key 進行完整性的驗證,才可信任 ID Token
所夾帶的資訊。
路徑 | 說明 |
---|---|
GET /.well-known/jwks.json | 取得 Authorization Server 的 public key |
可以使用開源的 JWT 驗證工具進行驗證
登出有分兩種 flow ,OpenID Connect Front-Channel Logout 1.0 及 OpenID Connect Back-Channel Logout 1.0,可以參考 Hydra user-logout 說明,Front-Channel Logout 主要是 Authorization Server 對 User Agent 發出 302 轉址到 OIDC Client 註冊的 frontchannel_logout_uri
; Back-Channel Logout 主要是 Authorization Server 直接通知 OIDC Client 註冊的 backchannel_logout_uri
,而下面內容為 Back-Channel Logout。
路徑 | 說明 |
---|---|
GET /oauth2/sessions/logout | 登出 |
流程圖步驟 (3) 簡化只畫一條回 OIDC Client,其實還有其他的 OIDC Client 會被呼叫,這些 OIDC Clients 都會執行清除各自 ID token
的流程
state 由 OIDC Client 隨機生成,之後步驟可與 Authorization Server 回傳的 state 比對,目的是為了確認轉導過程中的使用者都是同一個人,並且防止 CSRF 攻擊。
透過 GET 方法發送至 Authorization Server logout endpoint
GET 參數
parameters | description |
---|---|
id_token | 登入過程所拿到的的 ID token |
post_logout_redirect_uri | 必須跟 Authorization Server 註冊的一致 |
state | 為避免 CSRF 攻擊的一個隨機字串 |
Authorization Server 會進行一系列登出流程,並針對所有已登入的 OIDC Clients 發出 POST logout 請求,這些 uri 即為當初各 OIDC Clients 註冊的 backchannel_logout_uri。
Authorization Server 所發出 POST logout 帶有 logout_token
,各個 OIDC Cliens 收到後要先驗證 logout_token
要檢查一下下列資料:
RS256
iss
)是否為 Authorization Server。aud
)是不是 OIDC Client 自己的 client_id。sid
),找出 OIDC Client 中對應的 ID token
( ID token
的 payload 也會有 sid
),該 ID token
就是要被 OIDC Client 清除的。透過 POST 方法發送至 revoke endpoint
body 參數:
parameters | description |
---|---|
token | 要註銷的 Access token |
Authorization Server 會回傳一個 302 轉址到 post_logout_redirect_uri
的訊息給 User Agent,轉址內容含有 state 。
post_logout_redirect_uri
是有在 Authorization Server 註冊的 uri。
OIDC Client 的 post_logout_redirect_uri
執行自身的登出流程,EX: 清 cookie, session 等等,成功後即完成登出手續。
當 OIDC Client 發現持有的 ID token
或過期,請走登出流程,讓使用者重新再登入取新的 ID token
即使近年來 Cross-Origin Resource Sharing (CORS) 被廣泛採用,不論是 OIDC 登入流程或 OAuth 身份授權,不建議由前端發起,前端取得的 ID token
或 access token
會被竊取。
最簡單的安全處理方式是由後端 server 發起 OIDC 登入流程或 OAuth 身份授權,把 ID token
及 access token
儲存在後端(放入 Session or 自行處理儲存方式),登入完成後由後端設定 SameSite
及 HttpOnly
的 Cookie(Session-ID or User-Info) 及 Signed Cookie。
前端每次發起請求,後端就驗證 Cookie & Signed Cookie,並找到相關 token 資料(可由 Session ID 找到 token 值或是自行設定的 Cookie 對應後端儲存資料內容),再帶著 access token
轉發到 Resource Server 或 Auth Server 要資料。
Cookie SameSite
設定可禁止跨網站發送該 Cookie,防止 CSRF 攻擊。
Cookie HttpOnly
設定可禁止 JavaScript 存取該 cookie,防止 XSS 攻擊。
Cookie 也可設定 Secure
屬性,傳輸時會進行加密。