全部產品
Search
文件中心

API Gateway:oauth外掛程式

更新時間:Jan 08, 2025

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-aroute-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-aroute-b兩個路由做如下外掛程式配置:

allow:
- consumer1

*.example.comtest.com兩個網域名稱做如下外掛程式配置:

allow:
- consumer2
說明
  • 此例指定的route-aroute-b即在建立網關路由時填寫的路由名稱,當匹配到這兩個路由時,將允許nameconsumer1的調用者訪問,其他調用者不允許訪問。

  • 此例指定的*.example.comtest.com用於匹配請求的網域名稱,當發現網域名稱匹配時,將允許nameconsumer2的調用者訪問,其他調用者不允許訪問。

網關執行個體層級開啟

以下配置將對網關執行個體層級開啟 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.

無許可權訪問當前路由。