JWS 和 JWT 政策總覽

您目前查看的是 Apigee Edge 說明文件。
前往 Apigee X 說明文件
info

本主題提供 JWT (JSON Web Token) 和 JWS (JSON Web Signature) 的一般資訊,以及 Apigee 代理程式開發人員可能感興趣的 Apigee JWS/JWT 政策。

簡介

JWS 和 JWT 常用於在已連線的應用程式之間共用聲明或判斷。透過 JWS/JWT 政策,Edge API Proxy 可以執行下列操作:

  • 產生簽署的 JWTJWS
  • 驗證已簽署的 JWTJWS,以及 JWS/JWT 中的憑證附加資訊。
  • 解碼已簽署的 JWTJWS,但不驗證簽章。

在後兩種情況下,政策也會設定變數,讓其他政策或後端服務本身檢查已驗證的聲明,並根據這些聲明做出決策。

使用「驗證 JWS/JWT」政策時,系統會拒絕無效的 JWS/JWT,並導致錯誤情況。同樣地,使用「解碼 JWS/JWT」政策時,如果 JWS/JWT 格式錯誤,就會導致錯誤情況。

影片

觀看短片,快速瞭解 JWT。雖然這部影片專門介紹如何產生 JWT,但許多概念也適用於 JWS。

觀看這段短片,進一步瞭解 JWT 結構。

用途

您可以使用 JWS/JWT 政策執行下列操作:

  • 在 Edge Proxy 的 Proxy 或目標端點端產生新的 JWS/JWT。舉例來說,您可以建立 Proxy 要求流程,產生 JWS/JWT 並傳回給用戶端。或者,您也可以設計 Proxy,在目標要求流程中產生 JWS/JWT,並附加至傳送給目標的要求。這些聲明隨後會啟用,讓後端服務套用進一步的安全處理程序。
  • 驗證並擷取從用戶端傳入要求、目標服務回應、服務呼叫政策回應或其他來源取得的 JWS/JWT 中的聲明。無論 JWS/JWT 是由第三方或 Edge 本身產生,Edge 都會使用 RSA 或 HMAC 演算法驗證 JWS/JWT 的簽章。
  • 解碼 JWS/JWT。與「驗證 JWS/JWT」政策搭配使用時,解碼功能最實用,因為在驗證 JWS/JWT 之前,必須先瞭解 JWS/JWT 內憑證 (JWT) 或標頭 (JWS/JWT) 的值。

JWS/JWT 的組成部分

簽署的 JWS/JWT 會將資訊編碼為三個部分,並以英文句點分隔:標頭、酬載和簽章:

header.payload.signature
  • 產生 JWS/JWT 政策會建立所有三個部分。
  • 「驗證 JWS/JWT」政策會檢查所有三個部分。
  • Decode JWS/JWT 政策只會檢查標頭和酬載。

JWS 也支援「分離」格式,可從 JWS 省略酬載:

header..signature

使用分離式 JWS 時,酬載會與 JWS 分開傳送。您可以使用「驗證 JWS」政策的 <DetachedContent> 元素,指定未編碼的原始 JWS 酬載。接著,Verify JWS 政策會使用 JWS 中的標頭和簽名,以及 <DetachedContent> 元素指定的酬載,驗證 JWS。

如要進一步瞭解權杖,以及權杖的編碼和簽署方式,請參閱:

JWS 和 JWT 的差異

您可以使用 JWT 或 JWS,在已連結的應用程式之間分享聲明或判斷結果。 兩者之間的主要差異在於酬載的表示方式:

  • JWT
    • 酬載一律為 JSON 物件
    • 酬載一律會附加至 JWT
    • 憑證的 typ 標頭一律會設為 JWT
  • JWS
    • 酬載可採用任何格式,例如 JSON 物件、位元組串流、八位元串流等
    • 酬載不必附加至 JWS

由於 JWT 格式一律會使用 JSON 物件代表酬載,因此 Edge 的「產生 JWT」和「驗證 JWT」政策內建支援處理常見的已註冊聲明名稱,例如 audisssub 等。也就是說,您可以使用「產生 JWT」政策的元素,在酬載中設定這些憑證附加資訊,並使用「驗證 JWT」政策的元素驗證這些值。詳情請參閱 JWT 規格的「已註冊的宣告名稱」一節。

除了支援特定註冊聲明名稱,產生 JWT 政策也直接支援將任意名稱的聲明新增至 JWT。每項聲明都是簡單的名稱/值配對,值可以是數字、布林值、字串、對應或陣列類型。

由於 JWS 可使用任何資料表示法做為酬載,因此您無法將聲明新增至酬載。 Generate JWS 政策支援將任意名稱的聲明新增至 JWS 的標頭。 此外,JWS 政策支援分離式酬載,也就是 JWS 省略酬載。 分離式酬載可讓您分別傳送 JWS 和酬載,且是多項安全標準的必要條件。

使用 JWS 和 JWT 時避免範本注入

為防止未經授權揭露資料,請在使用 GenerateJWT 或 GenerateJWS 政策時,遵循下列指引:

  • 避免直接參照使用者輸入內容:請勿在支援範本的 ref 屬性中,直接使用不受信任的輸入內容 (例如 request.queryparam.*request.header.*)。
  • 清除輸入內容:如果必須在 JWT/JWS 宣告中使用外部資料,請先使用 AssignMessage 政策,從輸入內容中移除所有大括號 ({ }) 或其他範本字元,再參照該內容。
  • 針對字串使用明確的聲明:如果是簡單的字串聲明,請避免使用 type="map"。使用預設的 type="string" 可避免參照值隱含範本化。
  • 請注意驗證和產生政策之間的行為不一致:JWS 和 JWT 產生政策在範本方面,與驗證政策的行為不同。

簽章演算法簡介

JWS/JWT 驗證和 JWS/JWT 產生政策支援 RSA、RSASSA-PSS、ECDSA 和 HMAC 演算法,並使用位元強度為 256、384 或 512 的 SHA2 總和檢查碼。無論簽署 JWS/JWT 時使用的演算法為何,JWS/JWT 解碼政策都能正常運作。

HMAC 演算法

HMAC 演算法會使用共用密鑰 (又稱密鑰) 建立簽名 (也稱為簽署 JWS/JWT),並驗證簽名。

私密金鑰的長度下限取決於演算法的位元強度:

  • HS256:金鑰長度下限為 32 個位元組
  • HS386:金鑰長度下限為 48 個位元組
  • HS512:金鑰長度下限為 64 個位元組

RSA 演算法

RSA 演算法會使用公開/私密金鑰組進行加密簽章。使用 RSA 簽章時,簽署方會使用 RSA 私密金鑰簽署 JWS/JWT,驗證方則會使用相符的 RSA 公開金鑰驗證 JWS/JWT 上的簽章。金鑰大小沒有規定。

RSASSA-PSS 演算法

RSASSA-PSS 演算法是 RSA 演算法的更新版本,與 RSS 類似,RSASSA-PSS 也使用 RSA 公開/私密金鑰組進行加密簽章。金鑰格式與 RSS 相同。 簽署方會使用私密金鑰簽署 JWS/JWT,驗證方則會使用相符的公開金鑰驗證 JWS/JWT 上的簽章。金鑰大小沒有規定。

ECDSA 演算法

橢圓曲線數位簽章演算法 (ECDSA) 是一種橢圓曲線密碼編譯演算法,具有 P-256、P-384 和 P-521 曲線。使用 ECDSA 演算法時,演算法會決定您必須指定的公開和私密金鑰類型:

演算法 曲線 重要規定
ES256 P-256 從 P-256 曲線產生的金鑰 (又稱 secp256r1 或 prime256v1)
ES384 P-384 從 P-384 曲線 (也稱為 secp384r1) 產生的金鑰
ES512 P-521 從 P-521 曲線 (也稱為 secp521r1) 產生的金鑰

金鑰加密演算法

JWS/JWT 政策支援 OpenSSL 支援的所有金鑰加密演算法。

使用 JSON Web Key Set (JWKS) 驗證 JWS/JWT

驗證已簽署的 JWS/JWT 時,您需要提供與用於簽署權杖的私密金鑰相關聯的公開金鑰。您有兩種方式可將公開金鑰提供給驗證 JWS/JWT 政策:

  • 使用實際的公開金鑰值 (通常在流程變數中提供),或
  • 使用以 JWKS 包裝的公開金鑰。

關於 JWKS

JWKS 是代表一組 JSON Web Key (JWK) 的 JSON 結構。JWK 是代表加密編譯金鑰的 JSON 資料結構。JWK 和 JWKS 的說明請參閱 RFC7517。請參閱附錄 A 的 JKWS 範例。JSON Web Key Sets 範例

JWKS 結構

RFC7517 說明各金鑰類型 (例如「RSA」或「EC」) 的 JWKS 金鑰元素。舉例來說,視金鑰類型而定,這些參數可能包括:

  • kty:金鑰類型,例如「RSA」或「EC」。
  • kid (金鑰 ID) - 可以是任意值 (金鑰集內不得重複)。如果傳入的 JWT 含有 JWKS 集合中的金鑰 ID,政策就會使用正確的公開金鑰驗證 JWS/JWT 簽章。

以下是選用元素及其值的範例:

  • alg - 金鑰演算法。必須與 JWS/JWT 中的簽署演算法相符。
  • use - 如果存在,則必須為 sig。

下列 JWKS 包含必要元素和值,在 Edge 上會有效 (來自 https://www.googleapis.com/oauth2/v3/certs):

{
   "keys":[
      {
         "kty":"RSA",
         "alg":"RS256",
         "use":"sig",
         "kid":"ca04df587b5a7cead80abee9ea8dcf7586a78e01",
         "n":"iXn-WmrwLLBa-QDiToBozpu4Y4ThKdwORWFXQa9I75pKOvPUjUjE2Bk05TUSt7-V7KDjCq0_Nkd-X9rMRV5LKgCa0_F8YgI30QS3bUm9orFryrdOc65PUIVFVxIwMZuGDY1hj6HEJVWIr0CZdcgNIll06BasclckkUK4O-Eh7MaQrqb646ghFlG3zlgk9b2duHbDOq3s39ICPinRQWC6NqTYfqg7E8GN_NLY9srUCc_MswuUfMJ2cKT6edrhLuIwIj_74YGkpOwilr2VswKsvJ7dcoiJxheKYvKDKtZFkbKrWETTJSGX2Xeh0DFB0lqbKLVvqkM2lFU2Qx1OgtTnrw",
         "e":"AQAB"
      },
      {
          "kty":"EC",
          "alg":"ES256",
          "use":"enc",
          "kid":"k05TUSt7-V7KDjCq0_N"
          "crv":"P-256",
          "x":"Xej56MungXuFZwmk_xccvsMpCtXmqhvEEMCmHyAmKF0",
          "y":"Bozpu4Y4ThKdwORWFXQa9I75pKOvPUjUjE2Bk05TUSt",
      }
   ]
}

設計使用 JWKS 的 Proxy

從核發者取得 JWS/JWT 時,核發者通常會在 JWS/JWT 標頭中插入金鑰 ID (或 kid)。金鑰會告知 JWS/JWT 的接收者如何尋找驗證簽署 JWS/JWT 簽名所需的公開或私密金鑰。

舉例來說,假設核發者使用私密金鑰簽署 JWT。「金鑰 ID」會識別要用來驗證 JWT 的相符公開金鑰。公開金鑰清單通常位於某個知名端點,例如:https://www.googleapis.com/oauth2/v3/certs

這是 Edge (或任何可與 JWKS 搭配使用的平台) 必須執行的基本序列,才能使用含有 JWKS 的 JWS/JWT:

  1. 檢查 JWS/JWT 標頭,找出金鑰 ID (kid)。
  2. 檢查 JWS/JWT 標頭,找出簽署演算法 (alg),例如 RS256。
  3. 從指定核發機構的知名端點 JWKS 擷取金鑰和 ID 清單。
  4. 從金鑰清單中擷取公開金鑰,並使用 JWS/JWT 標頭中註明的金鑰 ID,以及相符的演算法 (如果 JWKS 金鑰指定演算法)。
  5. 使用該公開金鑰驗證 JWS/JWT 的簽名。

身為 Edge API Proxy 開發人員,您需要執行下列操作來進行 JWS/JWT 驗證:

  1. 從指定發卡機構的知名端點擷取金鑰和 ID 清單。您可以在這個步驟中使用服務呼叫政策。
  2. 在「驗證 JWS/JWT」政策中,於 <Source> 元素中指定 JWS/JWT 的位置,並在 <PublicKey/JWKS> 元素中指定 JWKS 酬載。舉例來說,如果是 VerifyJWT 政策:
    <VerifyJWT name="JWT-Verify-RS256">
        <Algorithm>RS256</Algorithm>
        <Source>json.jwt</Source>
        <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
        <PublicKey>
            <JWKS ref="public.jwks"/>
        </PublicKey>
        <Subject>apigee-seattle-hatrack-montage</Subject>
        <Issuer>urn://apigee-edge-JWT-policy-test</Issuer>
        <Audience>urn://c60511c0-12a2-473c-80fd-42528eb65a6a</Audience>
        <AdditionalClaims>
            <Claim name="show">And now for something completely different.</Claim>
        </AdditionalClaims>
    </VerifyJWT>

「驗證 JWT」政策會完成其他所有步驟:

  • 如果 JWKS 中沒有與 JWT 中斷言的金鑰 ID (kid) 相符的金鑰,驗證 JWT 政策就會擲回錯誤,且不會驗證 JWT。
  • 如果傳入的 JWT 標頭沒有金鑰 ID (kid),就無法進行金鑰 ID 對驗證金鑰的對應。

身為 Proxy 設計人員,您有責任決定要使用的金鑰;在某些情況下,這可能是固定的硬式編碼金鑰。