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
署名検証の流れ
-
id_token
を取得 -
id_token
をパース -
id_token
からalg
、kid
を取得 - JWKsエンドポイントへリクエストして公開鍵を取得
- 4で取得したkeys配列にある
kid
と3で取得したkid
が一致するものを取得 -
kid
と対応するn
とe
も取得 -
n
とe
、alg
を利用して公開鍵を作成 - 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