7
4

More than 1 year has passed since last update.

OpenID Connect JWKs Endpoint とid_token署名検証方法 メモ

Posted at

JWKsエンドポイント

  • id_tokenの署名を検証するための公開鍵のmodulus(絶対値)とexponent(指数値)を返却するエンドポイント
    • JSON Web Key (JWK):署名鍵を表現するためのJSONデータ構造

リクエスト

  • Keycloak例
GET /auth/realms/master/protocol/openid-connect/certs HTTP/1.1
Host: localhost:8080

レスポンス

  • Keycloak例
{
    "keys": [
        {
            "kid": "QSiaBQwkRZ9vqJgGv2byfTppJyeJT9mkxENgbxttoT8",
            "kty": "RSA",
            "alg": "RS256",
            "use": "sig",
            "n": "jKv0hkM...b9VvYIJ9hG8xN6zOQ",
            "e": "AQAB",
            "x5c": [
                "MIIC.....DyPe2E="
            ],
            "x5t": "9MMflCR5h-VY2D4HZx_kZ_L64XM",
            "x5t#S256": "DOiv2PKlM9QyI97gyUGl_95EULW9kyrv1ocAbxn1Q6M"
        },
        {
            "kid": "oYNqQTimc0dJfz7JFKNCwqgWC5Fp26eidiNcva6Nfn8",
            "kty": "RSA",
            "alg": "RS256",
            "use": "enc",
            "n": "mJNKSuJ...69NGCQ",
            "e": "AQAB",
            "x5c": [
                "MIICmzCCAYMCBgF8.../S2ZUocM="
            ],
            "x5t": "s7q4K84XS_OT4kRhwY-dPBGDeQU",
            "x5t#S256": "NbJVyOEgN_P5tJ0AO8bKX8vK2Loaw1PSQrlSS3YMhc4"
        }
    ]
}

パラメータ

パラメーター名 説明
keys JWK配列
kid 鍵識別子
ID TokenのHeaderに含まれているKey ID。 署名に利用した秘密鍵の対になる公開鍵を判定するために利用。
kty RSAやEC等の暗号アルゴリズムファミリー
use 公開鍵の用途
alg 署名検証アルゴリズム
x5c PKIX証明書からなるJSON 配列
それぞれの証明書文字列は base64 エンコードされた値で表現される※base64url エンコードではない
当該JWK の鍵を含む PKIX 証明書は先頭の証明書である必要がある
x5t DER エンコードされた X.509 証明書の SHA-1 thumbprintの base64url エンコード値
当該証明書に含まれる鍵は当該 JWK の示す公開鍵と一致する
x5t#S256 DER エンコードされた X.509 証明書の SHA-256 thumbprint の base64url エンコード値
当該証明書に含まれる鍵は当該 JWK の示す公開鍵と一致する
n modulus
公開鍵を復元するための公開鍵の絶対値
e exponent
公開鍵を復元するための指数値

id_token署名検証の流れ

  1. id_tokenを取得
  2. id_tokenをパース
  3. id_tokenからalgkidを取得
  4. JWKsエンドポイントへリクエストして公開鍵を取得
  5. 4で取得したkeys配列にあるkidと3で取得したkidが一致するものを取得
  6. kidと対応するneも取得
  7. nealgを利用して公開鍵を作成
  8. 7で作成した鍵を使用してid_tokenを検証
  • PyJWTを用いてid_token検証を行う例
import jwt
from jwt import PyJWKClient
def get_payload_from_id_token(id_token):
    # Keycloak JWKs Endpoint URL
    url = f"{KEYCLOAK_BASE_URL_CONTAINER_NAME}auth/realms/{KEYCLOAK_REALM_NAME}/protocol/openid-connect/certs"
    # JWKs Endpoint Client 
    jwks_client = PyJWKClient(url)
    # Signing Key
    signing_key = jwks_client.get_signing_key_from_jwt(id_token)
    # Decoding id_token by Signing Key
    payload = jwt.decode(id_token, signing_key.key, algorithms=["RS256"],audience=APP_CLIENT_ID)
    return payload

参考情報

7
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
4