В задачах аутентификации JWT ключевым моментом становится проверка подписи токена. В большинстве современных систем подпись проверяется с использованием публичных ключей, опубликованных в формате JWKS (JSON Web Key Set). Такие ключи могут храниться локально, но в реальных продуктивных системах почти всегда используются удалённые JWKS endpoints.
В библиотеке jose для JavaScript предусмотрен механизм
динамической загрузки и кеширования удалённых ключей через
createRemoteJWKSet. Это позволяет автоматически получать
актуальные ключи с сервера авторизации и использовать их для проверки
JWT без ручного управления ключами.
JWKS endpoint — это HTTP-ресурс, возвращающий JSON следующего вида:
{
"keys": [
{
"kty": "RSA",
"kid": "abc123",
"use": "sig",
"alg": "RS256",
"n": "...",
"e": "AQAB"
}
]
}
Каждый ключ содержит идентификатор kid, который затем
указывается в JWT заголовке:
{
"alg": "RS256",
"kid": "abc123"
}
При проверке токена библиотека должна:
kid из заголовка JWTcreateRemoteJWKSet автоматизирует весь этот процесс.
createRemoteJWKSetОсновная функция создаёт источник ключей, который динамически подтягивает JWKS по URL.
import { createRemoteJWKSet, jwtVerify } from 'jose'
const JWKS = createRemoteJWKSet(
new URL('https://auth.example.com/.well-known/jwks.json')
)
const { payload, protectedHeader } = await jwtVerify(token, JWKS)
Здесь JWKS становится функцией-резолвером ключей. При
каждой верификации JWT библиотека:
kidОдной из ключевых особенностей является встроенный кеш.
После первого запроса JWKS:
Это критично для производительности, особенно при высокой нагрузке.
В реальных системах ключи могут ротироваться. Например:
kidcreateRemoteJWKSet автоматически учитывает такие
изменения:
kid не найден в кешеЭто обеспечивает устойчивость к ротации ключей без остановки сервиса.
createRemoteJWKSet принимает второй аргумент — параметры
запроса:
const JWKS = createRemoteJWKSet(
new URL('https://auth.example.com/.well-known/jwks.json'),
{
timeoutDuration: 5000,
cooldownDuration: 30000
}
)
Ограничивает время ожидания ответа от JWKS endpoint. Если сервер авторизации недоступен или отвечает слишком долго, запрос прерывается.
Определяет период, в течение которого повторные неудачные запросы к JWKS будут ограничены. Это защищает систему от перегрузки при сбоях внешнего провайдера.
Сценарии ошибок могут быть следующими:
Если endpoint не отвечает:
kidЕсли токен содержит kid, которого нет в JWKS:
Если сервер возвращает невалидный JSON или структуру без
keys:
JWKS может содержать несколько активных ключей:
{
"keys": [
{ "kid": "key1", "kty": "RSA", "n": "...", "e": "AQAB" },
{ "kid": "key2", "kty": "RSA", "n": "...", "e": "AQAB" }
]
}
При этом логика выбора:
kid из JWTЕсли kid отсутствует, поведение зависит от конфигурации
токена и обычно считается ошибкой, так как невозможно однозначно выбрать
ключ.
jwtVerifycreateRemoteJWKSet чаще всего используется вместе с
jwtVerify:
import { jwtVerify, createRemoteJWKSet } from 'jose'
const JWKS = createRemoteJWKSet(
new URL('https://issuer.example.com/.well-known/jwks.json')
)
const result = await jwtVerify(token, JWKS, {
issuer: 'https://issuer.example.com',
audience: 'api-client'
})
Здесь происходит не только проверка подписи, но и валидация:
iss (issuer)aud (audience)JWKS отвечает только за криптографическую часть.
В распределённых системах JWKS endpoint становится центральной точкой доверия. Поэтому важно учитывать:
При тысячах запросов в секунду:
JWKS endpoint часто размещают за CDN:
createRemoteJWKSet работает с этим прозрачно, так как
использует обычный HTTP(S) запрос.
Несмотря на удобство, существуют важные ограничения:
Если JWKS провайдер недоступен:
kidОшибки в kid делают токены непроверяемыми. Это требует
дисциплины при выпуске JWT.
Хотя библиотека обновляет ключи автоматически, при неправильной конфигурации возможна задержка обновления.
Все они предоставляют JWKS endpoints, совместимые с
createRemoteJWKSet.
Каждый сервис:
В архитектурах с нулевым доверием:
joseВ serverless-средах:
В многопроцессных системах:
| Подход | Преимущества | Недостатки |
|---|---|---|
| Remote JWKS | автоматическая ротация, централизованное управление | зависимость от сети |
| Local keys | независимость от сети | сложная ротация |
Использование createRemoteJWKSet становится стандартом
для систем, где безопасность и динамическое управление ключами важнее
полной автономности проверки токенов.