OAuth2外掛程式實現了基於JWT(JSON Web Tokens)進行OAuth2 Access Token簽發的能力, 遵循RFC9068規範。本文介紹如何配置OAuth2外掛程式。
外掛程式類型
認證鑒權。
外掛程式配置說明
配置欄位
認證配置
名稱 | 資料類型 | 填寫要求 | 預設值 | 描述 |
consumers | array of object | 必填 | - | 佈建服務的調用者,用於對請求進行認證。 |
issuer | string | 選填 | Higress-Gateway | 用於填充JWT中的issuer。 |
auth_path | string | 選填 | /oauth2/token | 指定路徑尾碼用於簽發Token,路由級配置時,要確保能首先匹配對應的路由。在使用 API 管理時,需要建立相同路徑的介面。 |
global_credentials | bool | 選填 | true | 在通過 consumer 認證的前提下,允許任意路由簽發的憑證訪問。 |
auth_header_name | string | 選填 | Authorization | 用於指定從哪個要求標頭擷取JWT。 |
token_ttl | number | 選填 | 7200 | Token從簽發後多久內有效,單位為秒。 |
clock_skew_seconds | number | 選填 | 60 | 校正JWT的exp和iat欄位時允許的時鐘位移量,單位為秒。 |
keep_token | bool | 選填 | true | 轉寄給後端時是否保留JWT。 |
global_auth | array of string | 選填(僅執行個體層級配置) | - | 只能在執行個體層級配置,若配置為true,則全域生效認證機制; 若配置為false,則只對做了配置的網域名稱和路由生效認證機制,若不配置則僅當沒有網域名稱和路由配置時全域生效(相容老使用者使用習慣)。 |
子項consumers中每一項的配置欄位說明如下。
名稱 | 資料類型 | 填寫要求 | 預設值 | 描述 |
name | string | 必填 | - | 配置該consumer的名稱。 |
client_id | string | 必填 | - | OAuth2 client id。 |
client_secret | string | 必填 | - | OAuth2 client secret。 |
對於開啟該配置的路由,如果路徑尾碼和
auth_path匹配,則該路由不會被轉寄到原目標服務,而是用於產生Token。如果關閉
global_credentials,請確保啟用此外掛程式的路由不是精確匹配路由,此時若存在另一條首碼匹配路由,則可能導致預期外行為。對於通過認證鑒權的請求,請求的header會被添加一個
X-Mse-Consumer欄位,用以標識調用者的名稱。
鑒權配置(非必需)
名稱 | 資料類型 | 填寫要求 | 預設值 | 描述 |
allow | array of string | 選填(非執行個體層級配置) | - | 只能在路由或網域名稱等細粒度規則上配置,對於符合匹配條件的請求,配置允許訪問的 consumer,從而實現細粒度的許可權控制。 |
在一個規則裡,鑒權配置和認證配置不可同時存在。
配置樣本
路由粒度配置認證
在route-a和route-b兩個路由做如下外掛程式配置:
consumers:
- name: consumer1
client_id: 12345678-xxxx-xxxx-xxxx-xxxxxxxxxxxx
client_secret: abcdefgh-xxxx-xxxx-xxxx-xxxxxxxxxxxx此時雖然使用同一份配置,但route-a 下籤發的憑證無法用於訪問 route-b,反之亦然。
如果希望同一份配置共用憑證存取權限,可以做如下配置:
global_credentials: true
consumers:
- name: consumer1
client_id: 12345678-xxxx-xxxx-xxxx-xxxxxxxxxxxx
client_secret: abcdefgh-xxxx-xxxx-xxxx-xxxxxxxxxxxx全域配置認證和路由粒度進行鑒權
以下配置將對網關特定路由或網域名稱開啟 Jwt Auth 認證和鑒權,注意如果一個JWT能匹配多個jwks,則按照配置順序命中第一個匹配的consumer。
在執行個體層級做如下外掛程式配置:
global_auth: false
consumers:
- name: consumer1
client_id: 12345678-xxxx-xxxx-xxxx-xxxxxxxxxxxx
client_secret: abcdefgh-xxxx-xxxx-xxxx-xxxxxxxxxxxx
- name: consumer2
client_id: 87654321-xxxx-xxxx-xxxx-xxxxxxxxxxxx
client_secret: hgfedcba-xxxx-xxxx-xxxx-xxxxxxxxxxxx在route-a和route-b兩個路由做如下外掛程式配置:
allow:
- consumer1在*.example.com和test.com兩個網域名稱做如下外掛程式配置:
allow:
- consumer2此例指定的
route-a和route-b即在建立網關路由時填寫的路由名稱,當匹配到這兩個路由時,將允許name為consumer1的調用者訪問,其他調用者不允許訪問。此例指定的
*.example.com和test.com用於匹配請求的網域名稱,當發現網域名稱匹配時,將允許name為consumer2的調用者訪問,其他調用者不允許訪問。
網關執行個體層級開啟
以下配置將對網關執行個體層級開啟 OAuth2 認證,所有請求均需要經過認證後才能訪問。
global_auth: true
consumers:
- name: consumer1
client_id: 12345678-xxxx-xxxx-xxxx-xxxxxxxxxxxx
client_secret: abcdefgh-xxxx-xxxx-xxxx-xxxxxxxxxxxx
- name: consumer2
client_id: 87654321-xxxx-xxxx-xxxx-xxxxxxxxxxxx
client_secret: hgfedcba-xxxx-xxxx-xxxx-xxxxxxxxxxxx請求樣本
使用 Client Credential 授權模式
擷取 AccessToken
# 通過 GET 方法擷取(推薦)
curl 'http://test.com/oauth2/token?grant_type=client_credentials&client_id=12345678-xxxx-xxxx-xxxx-xxxxxxxxxxxx&client_secret=abcdefgh-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
# 通過 POST 方法擷取(需要先匹配到有真實目標服務的路由,否則網關不會讀取請求 Body)
curl 'http://test.com/oauth2/token' -H 'content-type: application/x-www-form-urlencoded' -d 'grant_type=client_credentials&client_id=12345678-xxxx-xxxx-xxxx-xxxxxxxxxxxx&client_secret=abcdefgh-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
# 擷取響應中的 access_token 欄位即可:
{
"token_type": "bearer",
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6ImFwcGxpY2F0aW9uXC9hdCtqd3QifQ.eyJhdWQiOiJkZWZhdWx0IiwiY2xpZW50X2lkIjoiMTIzNDU2NzgteHh4eC14eHh4LXh4eHgteHh4eHh4eHh4eHh4IiwiZXhwIjoxNjg3OTUxNDYzLCJpYXQiOjE2ODc5NDQyNjMsImlzcyI6IkhpZ3Jlc3MtR2F0ZXdheSIsImp0aSI6IjEwOTU5ZDFiLThkNjEtNGRlYy1iZWE3LTk0ODEwMzc1YjYzYyIsInN1YiI6ImNvbnN1bWVyMSJ9.NkT_rG3DcV9543vBQgneVqoGfIhVeOuUBwLJJ4Wycb0",
"expires_in": 7200
}使用 AccessToken 請求
curl 'http://test.com' -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6ImFwcGxpY2F0aW9uXC9hdCtqd3QifQ.eyJhdWQiOiJkZWZhdWx0IiwiY2xpZW50X2lkIjoiMTIzNDU2NzgteHh4eC14eHh4LXh4eHgteHh4eHh4eHh4eHh4IiwiZXhwIjoxNjg3OTUxNDYzLCJpYXQiOjE2ODc5NDQyNjMsImlzcyI6IkhpZ3Jlc3MtR2F0ZXdheSIsImp0aSI6IjEwOTU5ZDFiLThkNjEtNGRlYy1iZWE3LTk0ODEwMzc1YjYzYyIsInN1YiI6ImNvbnN1bWVyMSJ9.NkT_rG3DcV9543vBQgneVqoGfIhVeOuUBwLJJ4Wycb0'相關錯誤碼
HTTP狀態代碼 | 出錯資訊 | 原因說明 |
401 | Invalid Jwt token. | 要求標頭未提供JWT、JWT格式錯誤或到期等原因。 |
403 | Access Denied. | 無許可權訪問當前路由。 |