1. 引言
在本教程中,我們將首先快速回顧 OAuth 2.0、OpenID 和 Keycloak。然后,我們將了解 Keycloak REST API 以及如何在 Postman 中調用它們。
2. OAuth 2.0
OAuth 2.0 是一個授權框架,它允許經過身份驗證的用戶通過令牌向第三方授予訪問權限。令牌通常僅限于某些生命周期有限的范圍。因此,它是用戶憑證的安全替代方案。
OAuth 2.0 帶有四個主要組件:
-
Resource Owner(資源所有者) – 擁有受保護資源或數據的最終用戶或系統
-
Resource Server(資源服務器) – 該服務通常通過基于 HTTP 的 API 公開受保護的資源
-
Client(客戶端) – 代表資源所有者調用受保護的資源
-
Authorization Server(授權服務器) – 頒發 OAuth 2.0 令牌,并在對資源所有者進行身份驗證后將其交付給客戶端
OAuth 2.0 是一種具有一些標準流的協議,我們在此重點設計一下授權服務器組件。
3. OpenID 連接
OpenID Connect 1.0 (OIDC) 構建在 OAuth 2.0 之上,用于向協議添加身份管理層。因此,它允許客戶端通過標準 OAuth 2.0 流程驗證最終用戶的身份并訪問基本配置文件信息。OIDC 向 OAuth 2.0 引入了一些標準范圍,例如 openid、profile 和 email。
4. Keycloak 作為授權服務器
**JBoss 開發了 Keycloak 作為基于 Java 的開源身份和訪問管理解決方案。 **除了支持 OAuth 2.0 和 OIDC 之外,它還提供身份代理、用戶聯合和 SSO 等功能。
我們可以將 Keycloak 用作帶有管理控制臺的獨立服務器,或將其嵌入到 Spring 應用程序中。一旦我們以這兩種方式中的任何一種運行了 Keycloak,我們就可以嘗試訪問其端點。
5. Keycloak 端點
Keycloak 為 OAuth 2.0 流程提供了各種 REST 端點。要在 Postman 中使用這些端點,我們首先要創建一個名為 “Keycloak” 的環境。然后,添加一些鍵值對,用于設置 Keycloak 授權服務器的 URL、領域、OAuth 2.0 客戶端 ID 和客戶端密碼:
5.1. OpenID 配置端點
配置終端節點類似于根目錄。它返回所有其他可用終端節點、支持的范圍和聲明以及簽名算法。
讓我們在 Postman 中創建一個請求:{{server}}/realms/{{realm}}/.well-known/openid-configuration。Postman 在運行時從所選環境中設置 {{server}} 和 {{realm}} 的值:
然后我們將執行請求,如果一切順利,我們將得到一個響應:
如前所述,我們可以在響應中看到所有可用的終端節點,例如 “authorization_endpoint”、“token_endpoint” 等。
此外,響應中還有其他有用的屬性。例如,我們可以從 “grant_types_supported” 中找出所有支持的授權類型,或者從 “scopes_supported” 中找出所有支持的作用域。
5.2. 授權端點
讓我們繼續了解負責 OAuth 2.0 授權代碼流程的授權端點。它在 OpenID 配置響應中以 *“authorization_endpoint” *的形式提供。
授權端點:{{server}}/realms/{{realm}}/protocol/openid-connect/auth?response_type=code&client_id={{clientId}}
此外,此端點接受 scope 和 redirect_uri 作為可選參數。
我們不會在 Postman 中使用此端點,通常通過瀏覽器發起授權碼流程。如果沒有有效的登錄 cookie,Keycloak 會將用戶重定向到登錄頁面。最后,授權碼會被發送到重定向 URL。接下來,我們將了解如何獲取訪問令牌。
5.3. 令牌端點
令牌終端節點允許我們檢索訪問令牌、刷新令牌或 id 令牌。OAuth 2.0 支持不同的授權類型,例如 authorization_code、refresh_token 或 password。
令牌端點:{{server}}/realms/{{realm}}/protocol/openid-connect/token
但是,每種授權類型都需要一些專用的表單參數。
5.3.1. 授權碼流程
我們將首先測試令牌端點,以獲取code(授權碼)對應的訪問令牌。請求正文中傳遞這些表單參數:client_id、client_secret、grant_type、code 和 redirect_uri。令牌終端節點還接受 scope 作為可選參數:
模擬獲得code
-
瀏覽器訪問:
http://192.168.1.212:8080/realms/cemx/protocol/openid-connect/auth?response_type=code&client_id=cemc-client&redirect_uri=http://192.168.1.128:8081/login/oauth2/code/keycloak
-
在登錄界面里面輸入用戶名和密碼
-
查看瀏覽器網絡訪問
通過code獲得Token
5.3.2. 用戶名密碼流程
如果我們想繞過授權碼流程,可以選擇 password 授權類型。這里我們需要用戶憑證,因此當我們的網站或應用程序中有內置登錄頁面時,可以使用此流程。讓我們創建一個 Postman 請求,并在正文中傳遞表單參數 client_id、client_secret、grant_type、username 和 password:
在執行此請求之前,我們必須將 username 和 password 變量添加到 Postman 的環境鍵/值對中。
另一種有用的授權類型是* refresh_token*。當我們擁有來自上一次對 token 終端節點的有效刷新令牌時,我們可以使用它。刷新令牌流需要參數 client_id、client_secret、grant_type 和 refresh_token。
我們需要響應access_token來測試其他終端節點。為了加快使用 Postman 的測試速度,我們可以在令牌終端節點請求的 Scripts 部分編寫一個腳本:
如果出現錯誤”keycloak Client not allowed for direct access grants“,說明這里需要Direct access grants的開啟
5.4. 用戶信息端點
當我們擁有有效的訪問令牌時,我們可以從用戶信息終端節點檢索用戶配置文件數據。
用戶信息端點:{{server}}/realms/{{realm}}/protocol/openid-connect/userinfo
現在,我們將為其創建一個 Postman 請求,并在 Authorization 標頭中傳遞訪問令牌:
這里的access_token就是上一步獲得寫入環境中的Access Token,考慮到需要獲得用戶信息,采用scope 為openid,所以,上一步我紅色標準的參數別忘記了。
不然,該請求的響應頭中有報錯信息,如 error=“insufficient_scope”, error_description=“Missing openid scope”
原因:當前使用的 access_token 丟失了 openid 這個作用范圍。說明這個 access_token 不支持 openid 的方式請求 userinfo。解決這個問題,需要在請求 token 時,顯式的增加 scope=openid 的參數。
5.5. Token Introspect 端點
如果資源服務器需要驗證訪問令牌是否有效,或者想要獲取更多關于它的元數據(特別是對于 opaque access tokens[不透明的訪問令牌]),那么令牌內省端點就能滿足需求。在這種情況下,資源服務器將 introspect 過程與安全配置集成在一起。
introspect 端點:{{server}}/realms/{{realm}}/protocol/openid-connect/token/introspect
然后,我們將在 Postman 中創建一個 introspect 請求,并將 client_id、client_secret 和 token 作為表單參數傳遞:
如果 access_token 有效,我們將得到如下響應:
但是,如果我們使用無效的訪問令牌,則響應將是:
6. 總結
在本文中,使用正在運行的 Keycloak Server,我們為授權、令牌、用戶信息和內省端點創建了 Postman 請求。
7. 關于
關于使用postman的具體操作,請參考《使用 Spring Boot 和 Keycloak 的 OAuth2 快速指南》,該下載區有源碼。