Проверка JWT и авторизация
Что это такое
JSON Web Token — подписанное компактное представление утверждений: кто является субъектом, кто выдал токен, когда он истекает и что он разрешает. Благодаря подписи сервис может проверить его, не спрашивая издателя, и именно это делает токен полезным для API без состояния. Проверка означает сверку подписи, а затем утверждений; авторизация означает превращение проверенных утверждений в решение по конкретному запросу.
Почему это важно
Непроверенный токен — это утверждение, написанное самим вызывающим, а проверенный токен, утверждения которого не сверили, — действительные учётные данные не для той аудитории. Обе ошибки часты, потому что библиотека раскодирует токен и не проверяет его, а разница между декодированием и проверкой — одна опция в одном вызове. Поскольку токен даёт доступ ко всему, что покрывают его области доступа, ошибка здесь оборачивается отказом управления доступом, а не форматированием.
Ключевые идеи
Проверка состоит из нескольких шагов, и важен каждый
Подпись нужно сверить с опубликованными ключами издателя. От алгоритма требуется, чтобы он был ожидаемым, а не тем, который объявил сам токен; издатель и аудитория должны быть теми, кого вы ждёте, а срок действия — в будущем. Библиотека, которая декодирует без проверки, возвращает утверждения неподписанного токена, а их может написать любой вызывающий.
подпись верна -> алгоритм ожидаемый -> издатель ожидаемый -> аудитория ожидаемая -> не истёк
Алгоритм должен выбирать проверяющий, а не токен
Если проверяющий доверяет алгоритму, названному в самом заголовке токена, злоумышленник может назвать более слабый алгоритм или алгоритм «none» и обойти подпись целиком. Однако жёсткого указания ожидаемого алгоритма в вызове проверки достаточно, чтобы убрать эту возможность, и это самая важная строка во всей проверке токена.
Утверждения — вход для решения об авторизации, а не само решение
Действительный токен с идентификатором субъекта ещё не значит, что субъект может читать именно эту запись: для этого нужна проверка владельца записи или роли вызывающего. Смешение действительного токена с авторизацией — так сервис в итоге позволяет любому аутентифицированному пользователю читать данные любого другого, изменив идентификатор в пути.
Аудитория и издатель защищают от путаницы с токенами
Токен, выданный для одного сервиса, не становится автоматически действительным в другом. Проверка аудитории не даёт переиграть здесь токен, выпущенный для другого приложения; проверка издателя отвергает токен недоверенного издателя, даже если подпись выглядит правильной. Каждая из них — одно поле, и обе часто опускают.
Сроку действия нужен допуск и история отзыва
Сравнение времён истечения требует небольшого допуска на расхождение часов, а короткое время жизни ограничивает ущерб от утёкшего токена. Поскольку проверенному токену не нужен вызов к издателю, отзыв не может быть мгновенным, поэтому практичные ответы — список запрещённых токенов для ценных или долгоживущих случаев либо короткие сроки и обновление. Выбор подходящего — решение, а не значение по умолчанию.
Полезную нагрузку может прочитать любой, у кого есть токен, поэтому в ней не должно быть секретов. В ней должно быть только то, что нужно серверу ресурсов: каждое утверждение — ещё одно поле, которое надо синхронизировать, и ещё одно, которое надо учитывать при авторизации. Роли и области доступа попадают в утверждения только если сервер ресурсов должен на них опираться.
Храните токены там, откуда клиент не может их слить
То, где клиент хранит свой токен, определяет, как его могут украсть: постоянное хранилище браузера может прочитать любой скрипт на странице, и тогда межсайтовый скриптинг превращается в захват аккаунта. Серверная сессия или защищённый cookie это ограничивают, а время жизни токена ограничивает ущерб — поэтому эти два решения и принимают вместе.
Практика
Напишите контрольный список проверки
Возьмите функцию проверки токена и выпишите каждую выполняемую ею проверку, затем отметьте, какие из них выполнил бы вызов, только декодирующий токен.
Готово, когда: список называет проверки алгоритма, издателя, аудитории и срока действия, и вы можете сказать, какая единственная опция превращает декодирование в проверку.
Найдите пропущенную проверку авторизации
Возьмите эндпоинт, который читает запись по идентификатору, и добавьте проверку, что проверенному субъекту разрешено читать эту запись.
Готово, когда: смена идентификатора в запросе отклоняется для вызывающего, которому запись не принадлежит, с кодом состояния, не раскрывающим, существует ли запись.
Частые ошибки
- Декодирование токена без проверки подписи — любой вызывающий может написать любые утверждения; исправить: проверяйте по ключам издателя.
- Доверие алгоритму из заголовка токена — становятся возможны алгоритм «none» и понижение алгоритма; исправить: жёстко указывайте ожидаемый алгоритм.
- Пропуск проверок аудитории и издателя — принимается токен, выпущенный для другого приложения; исправить: проверяйте оба.
- Трактовка действительного токена как авторизации — любой аутентифицированный пользователь читает любую запись; исправить: сверяйте субъекта с ресурсом.
- Секреты в полезной нагрузке — их прочтёт любой, у кого есть токен; исправить: держите конфиденциальные данные на сервере и ссылайтесь на них по идентификатору.
Что читать дальше
- Аутентификация и потоки OAuth2 (05-backend-data/10-authentication-authorization-oauth2-jwt/01-authentication-and-oauth2-flows) — откуда пришёл этот токен.
- Аутентификация и авторизация (OAuth2 / JWT) (05-backend-data/10-authentication-authorization-oauth2-jwt) — пара задач, которую завершает этот дочерний урок.
- Веб-безопасность (OWASP Top 10) (07-security/01-web-security-owasp-top-10) — нарушенный контроль доступа, классическим случаем которого является пропущенная проверка авторизации.