Ответ
Основной и рекомендуемый способ — использование JWKS (JSON Web Key Set). Это стандартный механизм, который позволяет клиентам динамически получать публичные ключи для проверки подписи JWT.
1. JWKS (JSON Web Key Set) — Стандартный подход
Это публичный эндпоинт (например, /.well-known/jwks.json), который возвращает JSON-объект с набором ключей. Такой подход позволяет серверу аутентификации ротировать ключи без необходимости вносить изменения в клиентские приложения.
Пример ответа JWKS:
{
"keys": [
{
"kty": "RSA",
"use": "sig",
"kid": "unique-key-id-1",
"alg": "RS256",
"n": "...base64url-encoded-modulus...",
"e": "AQAB"
}
]
}
kty: Тип ключа (например,RSA).use: Назначение ключа (sig— для подписи).kid: Уникальный идентификатор ключа. JWT в своем заголовке содержитkid, чтобы клиент знал, какой именно ключ из набора использовать для верификации.
2. Другие способы (менее гибкие)
- Встраивание в конфигурацию клиента: Публичный ключ жестко прописывается в конфигурации клиентского приложения. Главный минус — при смене ключа на сервере требуется обновление всех клиентов.
- Передача в заголовке JWT (
jwk): Публичный ключ встраивается непосредственно в заголовок токена. Используется редко, так как значительно увеличивает размер токена.
Пример получения ключа из JWKS на Python:
import jwt
import requests
# URL эндпоинта с ключами
jwks_url = "https://auth.example.com/.well-known/jwks.json"
# Получаем JWT, который нужно проверить
token = "eyJhbGciOiJSUzI1NiIsImtpZCI6InVuaXF1ZS1rZXktaWQtMSJ9..."
# 1. Получаем kid из заголовка токена
header = jwt.get_unverified_header(token)
kid = header['kid']
# 2. Загружаем ключи с JWKS-эндпоинта
jwks_client = jwt.PyJWKClient(jwks_url)
signing_key = jwks_client.get_signing_key_from_jwt(token)
# 3. Верифицируем токен с помощью найденного ключа
data = jwt.decode(
token,
signing_key.key,
algorithms=["RS256"],
options={"verify_aud": False}
)
print(data)