Проверка JWT и авторизация

Что это такое

JSON Web Token — подписанное компактное представление утверждений: кто является субъектом, кто выдал токен, когда он истекает и что он разрешает. Благодаря подписи сервис может проверить его, не спрашивая издателя, и именно это делает токен полезным для API без состояния. Проверка означает сверку подписи, а затем утверждений; авторизация означает превращение проверенных утверждений в решение по конкретному запросу.

Почему это важно

Непроверенный токен — это утверждение, написанное самим вызывающим, а проверенный токен, утверждения которого не сверили, — действительные учётные данные не для той аудитории. Обе ошибки часты, потому что библиотека раскодирует токен и не проверяет его, а разница между декодированием и проверкой — одна опция в одном вызове. Поскольку токен даёт доступ ко всему, что покрывают его области доступа, ошибка здесь оборачивается отказом управления доступом, а не форматированием.

Ключевые идеи

Проверка состоит из нескольких шагов, и важен каждый

Подпись нужно сверить с опубликованными ключами издателя. От алгоритма требуется, чтобы он был ожидаемым, а не тем, который объявил сам токен; издатель и аудитория должны быть теми, кого вы ждёте, а срок действия — в будущем. Библиотека, которая декодирует без проверки, возвращает утверждения неподписанного токена, а их может написать любой вызывающий.

подпись верна -> алгоритм ожидаемый -> издатель ожидаемый -> аудитория ожидаемая -> не истёк

Алгоритм должен выбирать проверяющий, а не токен

Если проверяющий доверяет алгоритму, названному в самом заголовке токена, злоумышленник может назвать более слабый алгоритм или алгоритм «none» и обойти подпись целиком. Однако жёсткого указания ожидаемого алгоритма в вызове проверки достаточно, чтобы убрать эту возможность, и это самая важная строка во всей проверке токена.

Утверждения — вход для решения об авторизации, а не само решение

Действительный токен с идентификатором субъекта ещё не значит, что субъект может читать именно эту запись: для этого нужна проверка владельца записи или роли вызывающего. Смешение действительного токена с авторизацией — так сервис в итоге позволяет любому аутентифицированному пользователю читать данные любого другого, изменив идентификатор в пути.

Аудитория и издатель защищают от путаницы с токенами

Токен, выданный для одного сервиса, не становится автоматически действительным в другом. Проверка аудитории не даёт переиграть здесь токен, выпущенный для другого приложения; проверка издателя отвергает токен недоверенного издателя, даже если подпись выглядит правильной. Каждая из них — одно поле, и обе часто опускают.

Сроку действия нужен допуск и история отзыва

Сравнение времён истечения требует небольшого допуска на расхождение часов, а короткое время жизни ограничивает ущерб от утёкшего токена. Поскольку проверенному токену не нужен вызов к издателю, отзыв не может быть мгновенным, поэтому практичные ответы — список запрещённых токенов для ценных или долгоживущих случаев либо короткие сроки и обновление. Выбор подходящего — решение, а не значение по умолчанию.

Полезную нагрузку может прочитать любой, у кого есть токен, поэтому в ней не должно быть секретов. В ней должно быть только то, что нужно серверу ресурсов: каждое утверждение — ещё одно поле, которое надо синхронизировать, и ещё одно, которое надо учитывать при авторизации. Роли и области доступа попадают в утверждения только если сервер ресурсов должен на них опираться.

Храните токены там, откуда клиент не может их слить

То, где клиент хранит свой токен, определяет, как его могут украсть: постоянное хранилище браузера может прочитать любой скрипт на странице, и тогда межсайтовый скриптинг превращается в захват аккаунта. Серверная сессия или защищённый cookie это ограничивают, а время жизни токена ограничивает ущерб — поэтому эти два решения и принимают вместе.

Практика

Напишите контрольный список проверки

Возьмите функцию проверки токена и выпишите каждую выполняемую ею проверку, затем отметьте, какие из них выполнил бы вызов, только декодирующий токен.

Готово, когда: список называет проверки алгоритма, издателя, аудитории и срока действия, и вы можете сказать, какая единственная опция превращает декодирование в проверку.

Найдите пропущенную проверку авторизации

Возьмите эндпоинт, который читает запись по идентификатору, и добавьте проверку, что проверенному субъекту разрешено читать эту запись.

Готово, когда: смена идентификатора в запросе отклоняется для вызывающего, которому запись не принадлежит, с кодом состояния, не раскрывающим, существует ли запись.

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

  • Декодирование токена без проверки подписи — любой вызывающий может написать любые утверждения; исправить: проверяйте по ключам издателя.
  • Доверие алгоритму из заголовка токена — становятся возможны алгоритм «none» и понижение алгоритма; исправить: жёстко указывайте ожидаемый алгоритм.
  • Пропуск проверок аудитории и издателя — принимается токен, выпущенный для другого приложения; исправить: проверяйте оба.
  • Трактовка действительного токена как авторизации — любой аутентифицированный пользователь читает любую запись; исправить: сверяйте субъекта с ресурсом.
  • Секреты в полезной нагрузке — их прочтёт любой, у кого есть токен; исправить: держите конфиденциальные данные на сервере и ссылайтесь на них по идентификатору.

Что читать дальше