iT邦幫忙

2025 iThome 鐵人賽

DAY 27
0

新的故事

就在團隊完成了HMAC認證實作,以符合金融公司的高安全性要求後,又一間金融公司希望使用這個新的API,但這次卻出了另一個認證的難題給工程團隊。因此,團隊又聚在一起討論,該如何完成這次的任務。

Lala:這次安全性要求更高了,為確保資訊安全,所提供之服務須經安全性連線,認證授權機制之機敏資訊除可供定期輪替,金鑰亦需採用非對稱加密,並確保逾時後授權失效之機制....

Ariel:非對稱加密,這樣HMAC好像又不符合要求了....

Sam:沒錯,雖說HMAC採用的是每一次發送請求時,都會變更認證內容,但是的確是使用對稱金鑰的形式進行的。

Ariel:我記得我閱讀過文件,主流是不是要使用OIDC(Open ID Connection)協議,那是不是就是非對稱金鑰?

Sam:對,那是最經典而且最主流的認證授權方式,而且OIDC又有多種認證流程可以使用,的確是符合需求....但,那個plugin....要企業版才有。

Lala:那這個客戶的需求,是不是就沒辦法承接了?

Sam:這倒也不是,其實OIDC底層是透過JWT(JSON Web Token)實作而成的,而JWTplugin是不用錢的,應該也是可以符合這次客戶的需求。而且也剛好藉這次接觸JWT的機會,讓我們一起了解OIDC的其中一種 flow。

Ariel:聽起來頗有趣的,那就開始吧。

JWT

JWT
圖 27-1 JWT

JWT(JSON Web Token)是一種 基於 JSON 格式的權杖(token),常用來在不同系統或服務間攜帶身份認證或授權資訊。
它由三個部分組成(以 . 分隔):

 header.payload.signature

  • Header:說明演算法與 token 類型,例如 { "alg": "HS256", "typ": "JWT" }。
  • Payload:使用者相關資訊與權限聲明(claims),例如 sub, exp, role, iss等。
  • Signature:根據 header 與 payload 經過金鑰簽章,確保內容未被竄改。

補充:
token.dev
圖27-2 token.dev
為了讓讀者更能了解JWT的組成,推薦 token.dev這個網站,可以快速的產生一個範例的 token讓讀者可以學習,並且會將 token的各個組成解碼後以 JSON的形式觀看,是個學習與實驗的好網站。

網路上如果去翻找程式碼範例,其實也不乏各網站自己實作JWT的發行與管理,大多都透過 API endpoint 進行。然後在 API 請求時,帶在 http header 的 authorization欄位,以 bearer header.payload.signature 形式被帶入。

這種做法最大的優點就是,token 的 payload中就有足夠資訊能夠識別登入者以及相對應的權限,不需查詢資料庫。這種被稱之為無狀態 (stateless)的身分認證與授權方式,可以讓伺服器不用維護 session。

這也是前面在談到與撰寫網頁系統最大的認證授權的不同之處,但也因為無狀態(stateless)的特性,代表可以在多個服務之間跳轉,服務依舊可以繼續提供。相較過往使用 session的方式,當如果伺服器有多台時,通常會需要跟網管去協調網路設備的Session Persistence,不然只要跳台就會需要使用者重新登入,體感就會變得很不好。

另外,進入了微服務的架構下,除非在所有微服務的南北向入口統一管理session,不然要個別處理session幾乎是不可能的任務。因為微服務的容器設計是需要具備自我修復的能力,這表示容器隨時都有可能重新啟動。如果個別管理session卻又隨時會被 kill,那應該會是一場大災難。

對稱金鑰與非對稱金鑰

在密碼學中,除了各式各樣不同的演算法外,主要還是分成了對稱金鑰非對稱金鑰兩種大類型。用簡單的比喻敘述,並稍微闡明各自有缺點:

  • 對稱金鑰:雙方就像共用一把鎖鑰匙,都必須知道同一把鑰匙。例如前面示範的apikey就是一種經典類型,或是hamc-auth同樣也是,這都是雙方共同知道同一把金鑰,進行溝通的加解密與驗證。
    這種優點就是實作簡單以及速度快。不過要注意的就是,金鑰必須要安全共享,如果外洩,攻擊者就可以偽造token來進行存取。
  • 非對稱金鑰:比較像去銀行領款時,取款人用印章蓋了取款單上面的章,而銀行櫃台則是用曾經被留存的印鑑單核對,核對正確就能確定印章沒被偽造。但銀行人員卻無法偽造取款的印章後,跑去銀行領錢。
    這種優點當然就是安全性較高,在伺服器端只須保存公鑰即可驗證,不怕外洩。缺點則是效能比較低,畢竟運算與實作相較對稱金鑰稍微複雜。

非對稱與對稱金鑰認證差異
圖27-3 非對稱與對稱金鑰認證差異

Kong 的JWT 實作

route 的設定

kong的認證方式中,JWT同時支援了對稱與非對稱的認證方式,與其他認證方式的設定方式類似,都可以彈性的在routeservice實作認證的要求,另外在Consumer(使用者/應用程式)綁定,藉由 Consumersecretpublic key 進行驗證。

- name: case_ELK_JPG_AuthZN_weather
  url: http://case_ELK_JPG_AuthZN_weather:8080
  routes:
  - name: case_ELK_JPG_AuthZN_weather
    paths:
    - /case_ELK_JPG_AuthZN_weather/
    plugins:
    - name: key-auth
      ...內容省略...
    - name: acl
      ...內容省略...
  - name: TestCase_HMAC
    paths:
    - /FinancalHMAC/
    plugins:
    - config:
      name: hmac-auth
      ...內容省略...
    - name: acl
      ...內容省略...
  - name: TestCase_JWT
    paths:
    - /FinancalJWT/
    plugins:
    - config:
        anonymous: null
        claims_to_verify:
        - exp
        cookie_names: []
        header_names:
        - authorization
        key_claim_name: name
        maximum_expiration: 4800
        run_on_preflight: true
        secret_is_base64: false
        uri_param_names:
        - jwt
      enabled: true
      name: jwt
      protocols:
      - grpc
      - grpcs
      - http
      - https
    - name: acl
      config:
        allow:
        - FinancalJWT
    ...acl 內容省略...

這次以ironman2025\case_ELK_JPG_Route_JWT\ 這的資料夾做為示範的範例標的。

前面的故事說到,是共用同一個service,繼續建立route但是使用不同的認證授權方式。所以請讀者注意到上方的kong.yml設定內容(ironman2025\case_ELK_JPG_Route_JWT\1.Kong_declarative\declarative\kong.yml),可以注意到同樣是基於 case_ELK_JPG_AuthZN_weather 這個 service下,又建立了一個名為 TestCase_JWT的 route,而且在其之下建立了兩個 plugin,分別是JWTacl

簡單說明一些值得注意的設定項目:

  • claims_to_verify: - exp
    • 指定要檢查哪些 claim。這裡是 exp(過期時間),表示 Kong 會驗證 token 是否過期。
    • 其他可用的還有 nbf(not before)。
  • header_names: - authorization
    • JWT token 可以從 HTTP Header 的 Authorization 讀取。
    • 格式通常是 Authorization: Bearer <jwt_token>
  • key_claim_name: name
    • 這是 JWT payload 裡用來對應 Kong Consumer 的欄位。
    • 例如:如果 payload 有 "name": "HS256_Sam_Key",Kong 就會拿 HS256_Sam_Key 去對應到 consumer在jwt_secrets所設定的key,以此來辨識是哪一位consumer
  • maximum_expiration: 4800
    • Token 最長有效時間(秒數)。
    • 如果 JWT 的 exp - iat 超過 4800 秒,Kong 會拒絕,避免有人簽發「超長效期 token」。
  • ACLgroupFinancalJWT

consumer 的設定

如同其他的認證設定方式一樣,在 route被設定好認證方式之後,接著就是在 consumer部分要進行設定,同樣來看kong.yml

- acls:
  - group: FinancalJWT
  username: sam@samnchiuhotmail.onmicrosoft.com
  custom_id: sam
  jwt_secrets:
  - algorithm: RS256
    key: RS256_Sam_Key
    rsa_public_key: |-
      -----BEGIN PUBLIC KEY-----
      MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6S7asUuzq5Q/3U9rbs+P
      kDVIdjgmtgWreG5qWPsC9xXZKiMV1AiV9LXyqQsAYpCqEDM3XbfmZqGb48yLhb/X
      qZaKgSYaC/h2DjM7lgrIQAp9902Rr8fUmLN2ivr5tnLxUUOnMOc2SQtr9dgzTONY
      W5Zu3PwyvAWk5D6ueIUhLtYzpcB+etoNdL3Ir2746KIy/VUsDwAM7dhrqSK8U2xF
      CGlau4ikOTtvzDownAMHMrfE7q1B6WZQDAQlBmxRQsyKln5DIsKv6xauNsHRgBAK
      ctUxZG8M4QJIx3S6Aughd3RZC4Ca5Ae9fd8L8mlNYBCrQhOZ7dS0f4at4arlLcaj
      twIDAQAB
      -----END PUBLIC KEY-----
    secret: xxx
  - algorithm: HS256
    key: HS256_Sam_Key
    secret: HS256_Sam_Secret_HS256_Key_minimum_size_of_256
  • acls
    • group: FinancalJWT
    • 把這個 Consumer 加入到 FinancalJWT 這個 ACL 群組。方便在 Kong 裡面用 ACL Plugin 控制哪些群組可以存取 API。
  • username
    • 這是 Consumer 的「顯示名稱」,這裡是sam@samnchiuhotmail.onmicrosoft.com
    • 至於為何這裡會有 onmicrosoft.com的帳號,容筆者先賣個關子。
  • custom_id
    • 自訂 ID,可以用來跟外部系統(例如 AD、IdP、CRM)對應。
    • 這裡是 sam,代表這個 consumer 在外部系統的唯一識別。
  • jwt_secrets
    • 這邊定義了兩種 JWT 金鑰驗證方式,讓同一個 Consumer 支援 RS256HS256
    • RS256
      • algorithm: RS256這裡指定使用 RSA 非對稱演算法驗證。
      • key : RS256_Sam_Key這是 Kong 用來識別這組金鑰的名稱。
      • rsa_public_key : RSA 公鑰。
        • 當 token 是 RS256 簽署時,Kong 會用這個公鑰來驗證。
      • secret: xxx → 雖然有 secret 欄位,但在 RS256 模式下實際上不會用到(主要還是依賴公鑰,而且這欄位不保留格式檢查器會一直提示錯誤)。
    • HS256
      • algorithm: HS256 指定 HMAC-SHA256 對稱演算法。
      • key: HS256_Sam_Secret_HS256_Key_minimum_size_of_256 Kong 用來識別這組金鑰的名稱(建議最小長度要超過256 bit)。
      • secret: HS256_Sam_Secret 簽署與驗證都會使用這組密鑰。

非對稱金鑰示範檔案:
ironman2025\case_ELK_JPG_Route_JWT\1.Kong_declarative\declarative\example_JWT.yml

這個範例筆者準備了非對稱金鑰,放在示範專案上面的路徑中,供讀者參閱。但切記,如果讀者自己要在公司中使用,請針對每一位consumer建立不同的金鑰,可別使用筆者的示範金鑰,然後廣發到廣大使用者中。這樣不僅無法識別真正的使用者,同時風險也極高。

至於產生非對稱金鑰的方式,讀者可以去找找網路上有一些實作範例,或是自行撰寫程式產生也可以。

小結

今天筆者用了一些篇幅來說明關於JWT設定中,對稱與非對稱金鑰的特點。同樣的也將這兩種類型在Kong上面的設定都說明。接下來明天將進入實作的階段,來確認JWT驗證方式在Kongconsumer中的實作方式。

讓我們明天見~


上一篇
Day 26 : Kong 的 Routes 共用與 HMAC Auth 實踐 - 2
下一篇
Day 28 : Kong 的 JWT 實踐 - 認證實作及探索OIDC的流程
系列文
解鎖API超能力:我的30天Kong可觀測性與管理實戰之旅29
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言