Skip to main content
Version: 2.8.1

HMAC Authentication

用途說明#

可於服務或路由加上 HMAC 簽署驗證。此插件會確認標頭 Proxy-AuthorizationAuthorization 中的數位簽署是有效的。

欄位配置說明#

變數類型預設值說明必填
hide_credentialsbooleanfalse此欄位決定將請求往後送至服務時是否帶上原本的驗證標頭內容。
設定為 true 時,插件會把驗證內容(i.e. Authorization 標頭)自請求移除。
V
clock_skewnumber300可設定時鐘偏移值(秒)來預防重送攻擊。
填入的值必須大於 0。
anonymousstring可設定 anonymous 使用者在驗證失敗時會使用此身份當作匿名用戶。
若此欄位為空,則當執行請求的身份認證時失敗時,會收到身份驗證失敗 4xx 的回應。
*要注意的是,此欄位需填入的是 consumer 本身之 id,而不是 custom_id 。
validate_request_bodybooleanfalse開啟此項設定,插件會對 body 做驗證。V
enforce_headersarray of string設定在建立 HTTP 簽署時必須帶入之標頭列表。
algorithmsarray of stringhmac-sha1,
hmac-sha256,
hmac-sha384,
hmac-sha512
支援之HMAC摘要演算法列表。允許的內容有 hmac-sha1, hmac-sha256, hmac-sha384hmac-sha512

用法示例#

在全局啟用插件#

  1. 從網站左邊 Menu 中 外掛插件 頁面中,點選右上角的 新增外掛插件

全局啟用畫面

  1. 點選後,選擇 認證 頁籤,並啟用 Hmac Auth,填寫內容參考欄位配置說明,設定成功後,任何請求(不分服務、路由、用戶)皆需經過認證才能通過。

在服務端上啟用插件#

  1. 從網站左邊 Menu 中 服務 > 服務列表 頁面中,選擇要啟用此插件的服務,假設為google,點選對應的編輯按鈕:

服務啟用畫面1

  1. 在編輯畫面中,點選上方的 外掛插件 頁籤,再點選頁籤內容上方的 新增外掛插件 按鈕:

服務啟用畫面2

點選後,選擇 認證 頁籤,並啟用 Hmac Auth,填寫內容參考欄位配置說明,設定成功後,僅有此服務(範例為google)請求需經過認證才能通過。

在路由端上啟用插件#

可以由兩種方式來選擇路由,並啟用插件:

方式一:路由列表#

  1. 從網站左邊 Menu 中 服務 > 路由列表 頁面中,選擇要啟用此插件的路由,假設為google,點選對應的編輯按鈕:

路由啟用畫面1

方式二:服務 > 服務列表 > 路由列表#

  1. 從網站左邊 Menu 中 服務 > 服務列表 頁面中,選擇要啟用此插件的路由 所屬之服務(假設為 google),點選對應的編輯按鈕。

在編輯畫面中,點選上方的 路由 頁籤,選擇要啟用此插件的路由(假設為 google),點選對應的編輯按鈕:

路由啟用畫面2


  1. 承第1步,點擊上述兩種方式之一的編輯按鈕後,在編輯畫面中,點選上方的 外掛插件 頁籤,再點選頁籤內容上方的 新增外掛插件 按鈕:

路由啟用畫面3

點選新增外掛插件 按鈕後,選擇 認證 頁籤,並啟用 Hmac Auth,填寫內容參考欄位配置說明,設定成功後,僅有此路由(範例為google)請求需經過認證才能通過。

建立使用者及憑證#

  1. 從網站左邊 Menu 中 訂閱用戶 > 用戶列表 頁面中選擇右上方 新增 按鈕,新增用戶。

  2. 選擇剛建立的使用者,進入編輯頁面,選擇上方 HMAC Authentication 頁籤,再選擇左上方的 新增 按鈕。

hmac auth

  1. 填入用戶名稱及密鑰,密鑰可填可不填,如留空則會自動生成密鑰。在這裡用 Testtesting 做為範例。

hmac auth2

憑證格式#

驗證簽署結構#

credentials := "hmac" params
params := keyId "," algorithm ", " headers ", " signature
keyId := "username" "=" plain-string
algorithm := "algorithm" "=" DQUOTE (hmac-sha1|hmac-sha256|hmac-sha384|hmac-sha512) DQUOTE
headers := "headers" "=" plain-string
signature := "signature" "=" plain-string
plain-string = DQUOTE *( %x20-21 / %x23-5B / %x5D-7E ) DQUOTE

簽署參數#

參數描述
username憑證的 username
algorithm產生簽署內容的演算法
headersHTTP標頭名,使用空白分開,代表此請求
signature使用 Base64 編碼產生的簽署內容

時鐘偏移(Clock Skew)#

預設為最少延遲 300 秒。伺服器端及客戶端需要與NTP同步並且把有效時間(GMT格式)帶入標頭 X-Date 或是 Date

主體驗證(Body Validation)#

使用者可開啟 validate_request_body 來驗證 body。如開啟此選項,則插件會將 body 用 SHA-256 演算法加密,並且看是否符合標頭 Digest 之內容。標頭 Digest 格式如下:

Digest: SHA-256=base64(sha256(<body>))

如果沒有請求主體,則 Digest 必須設置長度為 0。

強制標頭名(Enforcing Headers)#

enforce_headers 參數可強制標頭必須為簽署內容的一部分。預設上是沒有任何規定標頭必須被使用在生成簽署內容中。建議可以加上 request-linehost 以及 date,如果希望建立一個強力的簽署則可再加上 digest

驗證#

  1. 選擇一路由開啟此插件服務,在此示範全部欄位使用預設值。

  2. 此時在 console 上送出以下指令:

$ curl -H 'x-api-host: google' <GOC API Gateway protocol>://<GOC API Gateway ip>:<GOC API Gateway proxy port>/index -i

會收到以下回應:

HTTP/1.1 401 Unauthorized
Date: Wed, 31 Mar 2021 06:00:01 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
Content-Length: 26
X-Kong-Response-Latency: 2
Server: kong/2.0.4
{"message":"Unauthorized"}%
  1. 建立 signature 來通過驗證

範例中使用 date 以及 request-line 經過 hmac-sha256 來拼湊出以下摘要:

signing_string="date: Wed, 31 Mar 2021 06:24:20 GMT\nGET /index HTTP/1.1"
digest=HMAC-SHA256(<signing_string>, "testing")
base64_digest=base64(<digest>)

最終 Authorization 的內容如下:

Authorization: hmac username="Test", algorithm="hmac-sha256", headers="date request-line", signature=<base64_digest>"

而將上面的 signing_string 經過加密及編碼的內容為 +CHEQ6lBsvAh+I1hrbHsSwvFt1L6ziAPBgw7U/07UnY= ,並將其帶入signature。

試著送出以下指令:

$ curl -H 'x-api-host: google' -H 'date: Wed, 31 Mar 2021 06:24:20 GMT' -H 'Authorization: hmac username="Test", algorithm="hmac-sha256", headers="date request-line", signature="+CHEQ6lBsvAh+I1hrbHsSwvFt1L6ziAPBgw7U/07UnY="' <GOC API Gateway protocol>://<GOC API Gateway ip>:<GOC API Gateway proxy port>/index -i

即可得到正常的回應。