[Из песочницы] О хранении JWT токенов в браузерах

a6ozutnu2esctapau7wo8-htm78.jpeg


Открытый стандарт JWT официально появился в 2015 (rfc7519) обещая интересные особенности и широкие перспективы. Правильное хранение Access токена является жизненно важным вопросов при построении системы авторизации и аутентификации в современном Web, где становятся все популярнее сайты, построенные по технологии SPA.

Неправильное хранение токенов ведет к их краже и переиспользованию злоумышленниками.

Так и где хранить?


Рассмотрим основные варианты хранения JWT Access токена в браузере:

  1. Local Storage/Session Storage – метод не безопасный и подвержен атакам типа XSS, особенно если Вы подключаете скрипты из сторонних CDN (добавление integrity атрибута не может гарантировать 100% безопасность), либо не уверены что подключаемые Вами скрипты не имеют возможности «слить» данные из хранилищ на сторону. Более того если Local Storage доступен между табами то Session Storage доступен только в одной вкладке и открытие сайта в новой вкладке лишь вызовет новый раунд авторизации/рефреша Access токена.
  2. Хранение токена в локальной переменной внутри замыкания тоже не обеспечивает должной безопасности потому что атакующий может, например, проксировать функцию fetch и отправить токен на левый сайт. Так же это не решает проблему двух вкладок – нет безопасного способа передать токен из одной вкладки в другую.
  3. Cookies. Вот мы вернулись к старым «печенькам» которые использовались для хранения cookie sessions. Простое хранения Access токена в cookie чревато атакой CSRF. Более того оно не защищает от XSS атак. Для защиты от CSRF нужно ставить параметр Cookie SameSite в режим Strict– этим можно добиться того что все запросы, которые идут с других сайтов, не будут содержать Ваши credentials, что автоматически лишит атакующего возможности произвести CSRF атаку.
    В отличии от первых двух вариантов здесь есть и плюс – Access токен невозможно получить через JS если использовать флаг httpOnly, добавление Secure так же усилит защиту от сниффинга.

    Важным моментом является установка Cookie только для api домена/пути, чтобы запросы к публичной статике не содержали оверхед в header.


Что в итоге?


Cookies при правильном использовании являются адекватным и наиболее безопасным на данный момент решением для хранения JWT Access токена и должны следовать следующим правилам:

  1. Быть установленными для API домена/пути чтобы избежать оверхеда при запросах к статичным файлам (публичным картинкам/стилям/js файлам).
  2. Иметь флаг Secure (для передачи только по https).
  3. Иметь флаг httpOnly (для невозможности получения доступа из JavaScript).
  4. Атрибут SameSite должен быть Strict для защиты от CSRF аттак, запретит передачу Cookie файлов если переход к вашему API был не с установленого в Cookie домена.


На стороне сервера так же должно быть настроено:

  1. Content-Security-Policy – ограничение доверенных доменов для предотвращения возможных XSS атак
  2. Заголовок X-Frame-Options для защиты от атак типа clickjacking.
  3. X-XSS-Protection – принудительно включить встроенный механизм защиты браузера от XSS атак.
  4. X-Content-Type-Options – для защиты от подмены MIME типов.


Соблюдение этих мер в купе с частой ротацией Access/Refresh токенов должно помочь обеспечить высокий уровень безопасности на сайте.

Ограничения


Не смотря на то что атрибут SameSite поддерживается во многих популярных браузерах , существуют так же браузеры которые не поддерживают его или поддерживают частично (привет IE и Safari для мака). Для этих случаев нужен fallback к CSRF токенам. В этом случае вместе с запросами к API надо передавать и CSRF токен. Правильный CSRF токен должен генерироваться сервером с учетом Fingerprint’a пользователя да бы минимизировать вероятность его подмены.

© Habrahabr.ru