Utilo

Как работает JWT и как безопасно расшифровать токен

Понять структуру JSON Web Tokens, как создаются и проверяются подписи, распространенные претензии, проблемы безопасности и как расшифровать JWT.

· 5 мин чтения

JSON Web Tokens (JWTs) повсюду: OAuth и OpenID Connect логины, API шлюзы, однократный вход между микросервисами и сеансы мобильных приложений. Они также широко не поняты. Разработчики расшифровывают токен, видят читаемый JSON и задаются вопросом, является ли это проблемой безопасности; другие хранят конфиденциальные данные в токенах, предполагая, что они зашифрованы. В этой статье точно объясняется, что такое JWT, как он проверяется и как его проверить без риска.

Три составляющие ТПП

JWT выглядит как три случайных строки, соединенные точками:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0MiIsImV4cCI6MTkwMDAwMDAwMH0.Kx8...

Каждая часть кодирована с помощью Base64URL:

  1. Header JSON, описывающий тип токена и алгоритм подписи, например {"alg":"HS256","typ":"JWT"}.
  2. Payload JSON, содержащий заявления: заявления о пользователе и токене, например {"sub":"42","exp":1900000000}.
  3. Подпись байты, вычисленные из заголовка и полезной нагрузки с секретным или частным ключом.

Base64URL - это вариант [Base64] ((/blog/base64-explained), который использует - и _ вместо + и / и упускает подкладку, поэтому токены могут быть размещены в URL-адресах и заголовках без побега.

Главное, что заголовок и полезная нагрузка только зашифрованы, а не шифрованы. Любой, кто держит этот жетон, может их прочитать. Вставьте токен в [JWT-декодер] ((/tools/jwt-decoder) и полезная нагрузка отображается мгновенно это по дизайну.

Как работает подпись

Подпись делает JWT надежным. Эмитент берет зашифрованный заголовок и полезную нагрузку, соединяет их точкой и подписывает эту строку.

При HS256 (HMAC с SHA-256), эмитент и проверяющий используют один секретный ключ:

signature = HMAC-SHA256(secret, base64url(header) + "." + base64url(payload))

С RS256 или ES256 эмитент подписывается с помощью частного ключа, и любой может проверить с помощью соответствующего общедоступного ключа, часто опубликованного в конечной точке JWKS, такой как https://login.example.com/.well-known/jwks.json. Асимметричные алгоритмы предпочтительнее, когда многие сервисы должны проверять токены, но только один должен выдавать их.

Когда сервер получает токен, он пересчитывает или проверяет подпись. Если хотя бы один символ полезной нагрузки изменился, скажем, злоумышленник отредактировал "role":"user" на "role":"admin", подпись больше не совпадает, и токен отклоняется.

Зарегистрированные претензии, которые вы должны знать

Спецификация JWT (RFC 7519) определяет стандартные названия претензий:

  • iss (эмитент): кто создал токен, например https://login.example.com.
  • sub (субъект): о ком жетон, обычно идентификатор пользователя.
  • aud (аудитория): для кого предназначен токен, например, api.example.com.
  • exp (срок действия): время, после которого токен должен быть отклонен, в [Unix seconds] ((/blog/unix-timestamp-explained).
  • nbf (не ранее): время, до которого токен не действует.
  • iat (выпущен в): когда был создан токен.
  • jti (JWT ID): уникальный идентификатор, полезный для списков отмены.

Заявки добавляют свои собственные требования: scope, roles, tenant_id, email. Держите их в количестве небольшом; каждое требование сопровождается каждым просьбой.

Правильное подтверждение токена

Сервер должен проверить все следующее в этом порядке:

  1. Альгоритм такой, как вы ожидаете. Настройте список разрешений, например ["RS256"]. Никогда не позволяйте заголовку токена решать свободно; исторические уязвимости позволяют злоумышленникам переключаться на none или обманывать серверы в использовании общедоступного ключа в качестве секрета HMAC.
  2. Подпись действительна при правильном ключе, выбранном kid из вашего доверенного набора ключей.
  3. ** exp находится в будущем, а nbf - в прошлом**, что позволяет небольшое смещение часов на 3060 секунд.
  4. iss точно совпадает с вашим поставщиком.
  5. **aud содержит ** идентификатор вашей службы, поэтому токен, выпущенный для другого API, не может быть воспроизведен против вашего.

Используйте поддерживаемую библиотеку jose для JavaScript, PyJWT для Python, golang-jwt для Go вместо того, чтобы писать проверку сами.

Декодирование против проверки

Декодирование означает Base64URL-декодирование первых двух частей и анализа JSON. Он не требует ключа и не доказывает подлинности. Он полезен для:

  • Исправление ошибок, почему API возвращает 401: правильно ли aud? Токен истек?
  • Проверка того, какие сферы или роли фактически предоставлены потоком входа.
  • Подтверждаю, что обновление токенов создало новый exp.

Проверка означает проверку подписи и претензий, как описано выше. Только серверы должны принимать решения об разрешении и только после проверки.

Фронт-энд-код может декодировать токен, чтобы показать имя пользователя или запланировать обновление до exp, но он никогда не должен полагаться на декодированные требования безопасности, потому что пользователь может изменять все, что работает в его браузере.

Где хранить токены в браузере

Нет идеального ответа, только компромиссы:

  • ** httpOnly, Secure, SameSite cookies ** не могут быть прочитаны JavaScript, который защищает от кражи токенов с помощью кросс-сайтовых скриптов. Они требуют защиты CSRF, хотя SameSite=Lax или Strict охватывает большинство случаев.
  • ** Память** (переменная JavaScript) защищена от постоянства, но теряется при перезагрузке; объедините ее с токеном обновления в файле cookie HttpOnly.
  • localStorage удобный, но читаемый любым скриптом на странице, поэтому одна уязвимость XSS утекает каждый токен.

Для большинства веб-приложений, краткосрочные токены доступа в памяти плюс токен обновления в файле cookie HttpOnly являются хорошим балансом.

Срок действия и отзыв

JWT не имеют статуса: сервер может подтвердить их без поиска в базе данных. Обратная сторона заключается в том, что действительный токен не может быть легко отозван до истечения срока его действия. Уменьшение последствий:

  • Сохранить токены доступа недолго 5 - 15 минут обычно.
  • Используйте токены обновления, сохраненные безопасно и проверенные в базе данных, для выпуска новых токенов доступа.
  • Для действий с высоким риском проверьте список отмены значений jti или временную метку "токены, действительные после" на пользователя.

Частые ошибки

  • Вкладывание секретов в полезную нагрузку. Пароли, ключи API и личные данные читаются любым, кто имеет токен. Если вам нужна конфиденциальность, используйте JWE (шифрованные токены) или храните данные на стороне сервера.
  • Очень долговечные токены. Украденный токен, действительный в течение года, является нарушением в течение года.
  • Опущение проверки аудитории. Без проверки aud токен для службы с низкими привилегиями может быть использован против службы с высокими привилегиями.
  • ** Слабые секреты HMAC.** Секреты HS256 должны быть длинными и случайными не менее 256 бит. Короткие секреты могут быть взломаны в автономном режиме с помощью одного токена.
  • Записывание токенов. Журналы доступа и отслеживатели ошибок часто захватывают заголовки Authorization. Редактируйте их.

Безопасное осмотр токена

При отладке используйте декодер, который работает локально в вашем браузере, чтобы токен никогда не отправлялся третьей стороне. Предпочтительно использовать просроченные токены или токены тестовой среды при обмене скриншотами или вклеивании в билеты. Проверка:

  • alg и kid в заголовке соответствуют конфигурации вашего провайдера.
  • iss и aud соответствуют ожиданиям вашего API.
  • exp, iat и nbf имеют смысл относительно текущего времени.
  • Области действия и роли содержат то, что требуется для операции.

Итоги

JWT - это подписанный, не зашифрованный пакет JSON-заявлений. Его безопасность полностью зависит от проверки подписи и подтверждения претензий на сервере. Декодирование безвредно и полезно для отладки; доверие к декодированным данным без проверки является реальным риском. Сохраняйте токены недолговечными, держите полезные нагрузки небольшими и без секретов, проверяйте алгоритм, подпись, срок годности, эмитента и аудиторию каждый раз, и проверяйте токены с помощью инструментов, которые хранят их на вашей машине.

Эта страница переведена с английского автоматически. Если вы заметили ошибку, сообщите нам.

Похожие руководства