Вы правы, зашифровать claims можно, либо весть payload целиком, например с помощью JWE
В статье я упоминал, что чувствительную информацию в токене следует шифровать, а не просто подписывать, но основной акцент был на том, что JWT в стандартном виде не предусматривает шифрование, и на практике этот аспект часто опускают
Чтобы избежать недопонимания, внесу небольшие уточнения в текст)
Ваш подход имеет смысл, если вам действительно нужен JWT Если рассматривать как часто используют JWT (далеко не всегда, от проекта к проекту реализацию отличаются), то это выглядит так:
В БД (лучше Redis для быстрого доступа и возможность удобно использовать TTL) оптимально хранить не сам RT(небезопасно), а его идентификатор JTI (JWT ID), это дает возможность отзывать RT, делая их невалидными без хранения полных токенов. Отзыв RT токена подразумевает под собой невозможность обновить AT.
Сценарий: Злоумышленник крадет RT+AT пользователя Злоумышленник может использовать эти токены пока валидны (в т.ч обновлять AT) Простой повторный вход не решит проблему, потому что выписывается просто новая пара RT+AT (если повторный вход автоматически обнуляет все RT пользователя, это создает другую проблему - пользователь не сможет использовать систему с нескольких устройств одновременно)
простое решение, без использования сложных механизмов: Пользователь должен иметь возможность "завершить все активные сеансы" и\или конкретный сеанс, НО AT злоумышленника все равно будет валидным в течение срока действия, НО злоумышленник уже не сможешь выписать новый AT по RT, потому что JTI от RT украденный находится к примеру в revocation lists + после обновления AT выдается новая пара RT+AT с новым JTI, а старый JTI аннулируется. Это снижает риск повторного использования RT в случае его утечки. *тут также много споров при таком подходе использовать ли allow list для валидных JTI или revocation lists для отозванных JTI, но тут на самом деле зависит от приложения, времени жизни RT\AT итп итд. + allow list позволяет к примеру контролировать "лимит" количества активных сессий на аккаунт
Также я бы рекомендовать сократить срок жизни АТ хотя бы до часа (но в практике моей обычно до 30 минут это бывает). При таком подходи АТ у злоумышленника продолжить "быть", если мы не собираемся при каждом запросе чекать JTI из AT на "забаненость", что я бы не делал, НО можно, к примеру на чувствительные эндпоинты чекать AT (если в нем хранится тот же JTI что и в RT)
Вообщем вариантов много с JWT, от простых до прилично сложных, все зависит от необходимого уровня безопасности приложения\архитектуры\самого приложения, но также не стоит забывать про старые добрые сессии
JWT это безусловно хорошая и полезная технология, которая может решать множество задач. В своей статье я не ставил целью подвергнуть её критике, а лишь хотел обратить внимание на те аспекты, о которых некоторые разработчики не всегда задумываются
Существует множество механизмов, позволяющих нивелировать "ограничения" JWT для той же аутентификации , например Proof-of-Possession для JWT (RFC 7800) и еще найдется с десяток и больше вариантов решения вышеописанных проблем
Но даже с этими механизмами нет универсального "инструмента", который одинаково хорошо подойдёт для любой архитектуры и любого сценария. Выбор технологии зависит от бизнес требований, а понимание плюсов и минусов инструмента позволяет принимать правильные решения, по этому я полностью согласен с Вами, что и сессии также не панацея)
Зная о потенциальных проблемах, мы можем заранее предусмотреть как их обойти или минимизировать риски или посмотреть в сторону других технологий
Спасибо за ваш комментарий!
Вы правы, зашифровать claims можно, либо весть payload целиком, например с помощью JWE
В статье я упоминал, что чувствительную информацию в токене следует шифровать, а не просто подписывать, но основной акцент был на том, что JWT в стандартном виде не предусматривает шифрование, и на практике этот аспект часто опускают
Чтобы избежать недопонимания, внесу небольшие уточнения в текст)
Ваш подход имеет смысл, если вам действительно нужен JWT
Если рассматривать как часто используют JWT (далеко не всегда, от проекта к проекту реализацию отличаются), то это выглядит так:
В БД (лучше Redis для быстрого доступа и возможность удобно использовать TTL) оптимально хранить не сам RT(небезопасно), а его идентификатор JTI (JWT ID), это дает возможность отзывать RT, делая их невалидными без хранения полных токенов. Отзыв RT токена подразумевает под собой невозможность обновить AT.
Сценарий:
Злоумышленник крадет RT+AT пользователя
Злоумышленник может использовать эти токены пока валидны (в т.ч обновлять AT)
Простой повторный вход не решит проблему, потому что выписывается просто новая пара RT+AT (если повторный вход автоматически обнуляет все RT пользователя, это создает другую проблему - пользователь не сможет использовать систему с нескольких устройств одновременно)
простое решение, без использования сложных механизмов:
Пользователь должен иметь возможность "завершить все активные сеансы" и\или конкретный сеанс, НО AT злоумышленника все равно будет валидным в течение срока действия, НО злоумышленник уже не сможешь выписать новый AT по RT, потому что JTI от RT украденный находится к примеру в revocation lists
+ после обновления AT выдается новая пара RT+AT с новым JTI, а старый JTI аннулируется. Это снижает риск повторного использования RT в случае его утечки. *тут также много споров при таком подходе использовать ли allow list для валидных JTI или revocation lists для отозванных JTI, но тут на самом деле зависит от приложения, времени жизни RT\AT итп итд. + allow list позволяет к примеру контролировать "лимит" количества активных сессий на аккаунт
Также я бы рекомендовать сократить срок жизни АТ хотя бы до часа (но в практике моей обычно до 30 минут это бывает). При таком подходи АТ у злоумышленника продолжить "быть", если мы не собираемся при каждом запросе чекать JTI из AT на "забаненость", что я бы не делал, НО можно, к примеру на чувствительные эндпоинты чекать AT (если в нем хранится тот же JTI что и в RT)
Вообщем вариантов много с JWT, от простых до прилично сложных, все зависит от необходимого уровня безопасности приложения\архитектуры\самого приложения, но также не стоит забывать про старые добрые сессии
Спасибо за ваш комментарий!
JWT это безусловно хорошая и полезная технология, которая может решать множество задач. В своей статье я не ставил целью подвергнуть её критике, а лишь хотел обратить внимание на те аспекты, о которых некоторые разработчики не всегда задумываются
Существует множество механизмов, позволяющих нивелировать "ограничения" JWT для той же аутентификации , например Proof-of-Possession для JWT (RFC 7800) и еще найдется с десяток и больше вариантов решения вышеописанных проблем
Но даже с этими механизмами нет универсального "инструмента", который одинаково хорошо подойдёт для любой архитектуры и любого сценария. Выбор технологии зависит от бизнес требований, а понимание плюсов и минусов инструмента позволяет принимать правильные решения, по этому я полностью согласен с Вами, что и сессии также не панацея)
Зная о потенциальных проблемах, мы можем заранее предусмотреть как их обойти или минимизировать риски или посмотреть в сторону других технологий