Skip to main content
Version: 2.8.1

JWT

用途說明#

使用包含 HS256 或是 RS256 簽署的 JSON Web Tokens (參考RFC 7519)對請求做驗證。每一個用戶都會擁有 JWT 憑證(公開或祕密金鑰)可以用來簽署 JWTs 。 權杖可透過下列方式傳送:

  • 查詢字串(query string)
  • Cookie
  • HTTP 請求標頭

欄位配置說明#

變數類型預設值說明必填
uri_param_namesarray of stringjwt查詢字串的列表,GOC API Gateway 會審查並從中取得 JWTs。
cookie_namesarray of stringcookie 的列表,GOC API Gateway 會審查並從中取得 JWTs。
header_namesarray of stringauthorizationHTTP 標頭的列表,GOC API Gateway 會審查並從中取得 JWTs。
claims_to_verifyarray of string標準聲明內容列表使 GOC API Gateway 可以識別。
可接受的項目有 exp 以及 nbf
key_claim_namestringiss代表憑證中 key 的聲明名稱。插件會嘗試從 JWT payload 或是 header 以此順序讀取此聲明。
secret_is_base64booleanfalse開啟此項目,則插件會將憑證之祕鑰以 base64 做編碼。可以建立一個編碼過的祕鑰給用戶,用原本的祕鑰簽署 JWT。V
anonymousstring可設定 anonymous 使用者在驗證失敗時會使用此身份當作匿名用戶。
若此欄位為空,則當執行請求的身份認證時失敗時,會收到身份驗證失敗 4xx 的回應。
*要注意的是,此欄位需填入的是 consumer 本身之 id,而不是 custom_id 。
run_on_preflightbooleantrue開啟此項設定 (設為 true) 會在 OPTIONS 預檢請求上運行(並嘗試進行身份驗證);關閉此項設定 (設為 false) 則會讓所有 OPTIONS 預檢請求通過。V
maximum_expirationnumber0可接受輸入的範圍是 0 至 31536000 (365 天) 做為 JWT 的存活時間(單為為秒)。0 代表無限期。
超過範圍的數字會收到拒絕訊息(HTTP狀態碼403)。
如果設定此欄位,則在 claims_to_verify 中也必須填入 exp 的內容。

用法示例#

在全局啟用插件#

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

全局啟用畫面

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

在服務端上啟用插件#

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

服務啟用畫面1

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

服務啟用畫面2

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

在路由端上啟用插件#

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

方式一:路由列表#

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

路由啟用畫面1

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

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

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

路由啟用畫面2


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

路由啟用畫面3

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

建立使用者及憑證#

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

  2. 選擇剛建立的使用者,進入編輯頁面,選擇上方 憑證 頁籤,然後選擇左邊 JWT 頁籤,再選擇列表左上方的 新增 按鈕。

jwt

  1. 演算法部分可填入 HS256HS384HS512RS256ES256 。其它像金鑰欄位可以填入自己的金鑰或是留空自動生成,而 RSA 公開金鑰在演算法選擇 RS256 或是 ES256 時,必須填入公開金鑰(PEM格式)用來驗證權杖的簽署。

如果演算法選擇 HS256 或是 ES256 則使用祕鑰簽署 JWTs 憑證,但祕鑰欄位如果留空會自動生成新的祕鑰。

選擇演算法 HS256#

jwt2 jwt3

選擇演算法 RS256#

jwt4 jwt5

驗證#

  1. 選擇一路由開啟此插件服務,並建立好使用者及憑證 (範例為將路由之域名設定為 google,路徑設定為 /index,並開啟 拆分路徑)。

  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: Thu, 25 Mar 2021 07:56:13 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
WWW-Authenticate: Basic realm="kong"
Content-Length: 26
X-Kong-Response-Latency: 1
Server: kong/2.0.4
{"message":"Unauthorized"}

代表插件正常運作,並阻擋未通過驗證之請求。

使用祕鑰建立 JWT(HS256)#

  1. JWT 分為三個部分:header、payload、secret。

    1. header 設定為
    {
    "typ": "JWT",
    "alg": "HS256"
    }
    1. payload 的部分,需要包含 key_claim_name 的值,預設為 iss 。 將其值設定為剛建立的憑證產生的金鑰。
    {
    "iss": "x70Cz68T3HmtPJ3IytJpN96s8a10Np3X"
    }
    1. secret 即為剛剛建立的憑證產生的祕鑰,並將以上三個部分使用JWT官網生成 JWT 權杖
    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ4NzBDejY4VDNIbXRQSjNJeXRKcE45NnM4YTEwTnAzWCJ9.ayu7BkjmWLxWHV6iW_lxHx2OyqKQh0v4c_HvjGGHicw
  2. 之後送出請求時帶入 JWT 權杖於 Authorization 標頭內:

$ curl -H 'x-api-host: google' -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ4NzBDejY4VDNIbXRQSjNJeXRKcE45NnM4YTEwTnAzWCJ9.ayu7BkjmWLxWHV6iW_lxHx2OyqKQh0v4c_HvjGGHicw' <GOC API Gateway protocol>://<GOC API Gateway ip>:<GOC API Gateway proxy port>/index -i

即可得到正常的回應。

如果有設定 uri_param_names 也可用下列方式送出請求:

$ curl -H 'x-api-host: google' 'http://localhost:8000/index?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ4NzBDejY4VDNIbXRQSjNJeXRKcE45NnM4YTEwTnAzWCJ9.ayu7BkjmWLxWHV6iW_lxHx2OyqKQh0v4c_HvjGGHicw' -i

使用公開/祕密金鑰建立 JWT(RS256/ES256)#

  1. JWT 分為三個部分:header、payload、secret。

    1. header 設定為
    {
    "typ": "JWT",
    "alg": "RS256"
    }
    1. payload 的部分,需要包含 key_claim_name 的值,預設為 iss 。 將其值設定為剛建立的憑證產生的金鑰。
    {
    "iss": "J5fXgnWycvlwZsZdp4d5FZj04IZZu6AC"
    }
    1. 使用 JWT官網 帶入以上兩個資訊,再加上公開及祕密金鑰內容後生成 JWT 權杖
    eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJKNWZYZ25XeWN2bHdac1pkcDRkNUZaajA0SVpadTZBQyJ9.FAvPN4MQsL9_PDYut6_oOte07hdfyomdw7HSAO49wMG2QgAqEB0YofQHtesX7QpP2zvdiCo_uQC9uYvviiqnTTJO5oP0XBWSXBEFaXuQ3ey3Sh8Jp5wbB0F6q8kuCbQn7-elM8Rp0RAwIYnTwprUShCtZ4gtw2SjrFib3mvsOg7y5t4ChUOuCh0NbGhvyqJPItdPT9-HYMsp8ILjdrDtkH7afXCXsTBTfbIozpWSj1PLDKS8RlbKdguBSebM51FQlYueMf5JLm6GUYVRcDBHi-zwRNqASh-qC_eUcPcbnjssNWMoePCtPJuuPg-qGwlP8ExznrUA_-BXDGbITV-zVw
  2. 之後送出請求時帶入 JWT 權杖於 Authorization 標頭內:

$ curl -H 'x-api-host: google' -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJKNWZYZ25XeWN2bHdac1pkcDRkNUZaajA0SVpadTZBQyJ9.FAvPN4MQsL9_PDYut6_oOte07hdfyomdw7HSAO49wMG2QgAqEB0YofQHtesX7QpP2zvdiCo_uQC9uYvviiqnTTJO5oP0XBWSXBEFaXuQ3ey3Sh8Jp5wbB0F6q8kuCbQn7-elM8Rp0RAwIYnTwprUShCtZ4gtw2SjrFib3mvsOg7y5t4ChUOuCh0NbGhvyqJPItdPT9-HYMsp8ILjdrDtkH7afXCXsTBTfbIozpWSj1PLDKS8RlbKdguBSebM51FQlYueMf5JLm6GUYVRcDBHi-zwRNqASh-qC_eUcPcbnjssNWMoePCtPJuuPg-qGwlP8ExznrUA_-BXDGbITV-zVw' <GOC API Gateway protocol>://<GOC API Gateway ip>:<GOC API Gateway proxy port>/index -i

即可得到正常的回應。

如果有設定 uri_param_names 也可用下列方式送出請求:

curl -H 'x-api-host: google' '<GOC API Gateway protocol>://<GOC API Gateway ip>:<GOC API Gateway proxy port>/index?jwt=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJKNWZYZ25XeWN2bHdac1pkcDRkNUZaajA0SVpadTZBQyJ9.FAvPN4MQsL9_PDYut6_oOte07hdfyomdw7HSAO49wMG2QgAqEB0YofQHtesX7QpP2zvdiCo_uQC9uYvviiqnTTJO5oP0XBWSXBEFaXuQ3ey3Sh8Jp5wbB0F6q8kuCbQn7-elM8Rp0RAwIYnTwprUShCtZ4gtw2SjrFib3mvsOg7y5t4ChUOuCh0NbGhvyqJPItdPT9-HYMsp8ILjdrDtkH7afXCXsTBTfbIozpWSj1PLDKS8RlbKdguBSebM51FQlYueMf5JLm6GUYVRcDBHi-zwRNqASh-qC_eUcPcbnjssNWMoePCtPJuuPg-qGwlP8ExznrUA_-BXDGbITV-zVw' -i

相關解釋#

聲明#

claims_to_verify 可支援 exp 以及 nbf 兩個選項,想要同時加入時可填入 exp,nbf

聲明名稱驗證內容
expJWT 的過期時間,過期時間必須大於簽發 JWT 時間
nbf擬發放 JWT 之後,在某段時間點前該 JWT 仍舊是不可用的

Base64編碼祕鑰#

如果祕鑰中含有 binary 資料,可以將它們以 base64 做編碼。這時候要將 secret_is_base64 打開。在用戶底下建立憑證的時候必須將已編碼過的祕鑰帶入祕鑰的欄位。而在建立 JWT 時則要使用原始的祕鑰。

生成公開/祕密金鑰#

想生成全新的公開及祕密金鑰,可使用下列指令:

$ openssl genrsa -out private.pem 2048

生成祕密金鑰後,再生成相應的公開金鑰:

$ openssl rsa -in private.pem -outform PEM -pubout -out public.pem

之後就會生成兩把金鑰分別是 public.pemprivate.pem