Токены JWT - это круто, но как их безопасно хранить в вашем интерфейсе? Мы рассмотрим плюсы и минусы localStorage и файлов cookie.
В моем последнем посте мы рассмотрели, как работает OAuth 2.0, и изучили, как генерировать токены доступа и обновлять токены. Теперь мы рассмотрим, как хранить токены в вашем интерфейсе.
Токены доступа обычно представляют собой недолговечные токены JWT, которые подписываются вашим сервером и включаются в каждый HTTP-запрос к вашему серверу для его авторизации. Токены обновления обычно представляют собой долговечные непрозрачные строки, которые хранятся в вашей базе данных и используются для получения нового токена доступа по истечении срока его действия.
Где мне хранить свои токены во внешнем интерфейсе?
Есть два распространенных способа хранения ваших токенов. Первый находится в localStorage
, а второй - в файлах cookie. Существует много споров о том, какой из них лучше, и большинство людей склоняются к файлам cookie, поскольку они более безопасны.
Давайте рассмотрим сравнение localStorage
и файлов cookie. Эта статья в основном основана на этой статье и комментариях к этому посту.
Локальное хранилище
Плюсы: удобно.
- Это чистый JavaScript, и это удобно. Если у вас нет серверной части и вы полагаетесь на сторонний API, вы не всегда можете попросить сторонний API установить определенный файл cookie для вашего сайта.
- Работает с API, которые требуют, чтобы вы поместили свой токен доступа в заголовок, например:
Authorization Bearer ${access_token}
.
Минусы: уязвим для XSS-атак.
Атака XSS происходит, когда злоумышленник может запустить JavaScript на вашем веб-сайте. Это означает, что злоумышленник может забрать токен доступа, который вы сохранили в своем localStorage
. XSS-атака может произойти из-за стороннего кода JavaScript, включенного в ваш сайт, такого как React, Vue, jQuery, Google Analytics и т. Д. Практически невозможно не включить на свой сайт какие-либо сторонние библиотеки.
Печенье
Плюсы: файл cookie недоступен через JavaScript; следовательно, он не так уязвим для XSS-атак, как localStorage
.
- Если вы используете
httpOnly
иsecure
файлы cookie, это означает, что к вашим файлам cookie нельзя получить доступ с помощью JavaScript, поэтому, даже если злоумышленник может запустить JS на вашем сайте, он не сможет прочитать ваш токен доступа из файла cookie. - Он автоматически отправляется в каждом HTTP-запросе на ваш сервер.
Минусы: в зависимости от варианта использования вы не сможете хранить свои токены в файлах cookie.
- Максимальный размер файлов cookie составляет 4 КБ. Поэтому, если вы используете большой токен JWT, сохранение в файле cookie не вариант.
- Существуют сценарии, когда вы не можете поделиться файлами cookie со своим сервером API или API требует, чтобы вы поместили токен доступа в заголовок авторизации. В этом случае вы не сможете использовать файлы cookie для хранения своих токенов.
О XSS-атаке
Локальное хранилище уязвимо, потому что оно легко доступно с помощью JavaScript, и злоумышленник может получить ваш токен доступа и использовать его позже. Однако, хотя httpOnly
файлы cookie недоступны с помощью JavaScript, это не означает, что с помощью файлов cookie вы защищены от XSS-атак с использованием вашего токена доступа.
Если злоумышленник может запустить JavaScript в вашем приложении, он может просто отправить HTTP-запрос на ваш сервер, который автоматически включит ваши файлы cookie; Это просто менее удобно для злоумышленников, потому что они не могут прочитать содержимое токена, хотя им редко приходится. Для злоумышленника также может быть более выгодно атаковать с помощью браузера жертвы (просто отправив этот HTTP-запрос), а не с помощью машины злоумышленника.
Файлы cookie и CSRF-атака
Атака CSRF - это атака, вынуждающая пользователя выполнить непреднамеренный запрос. Например, если веб-сайт принимает запрос на изменение адреса электронной почты через:
POST /email/change HTTP/1.1 Host: site.com Content-Type: application/x-www-form-urlencoded Content-Length: 50 Cookie: session=abcdefghijklmnopqrstu email=myemail.example.com
тогда злоумышленник может легко создать form
на вредоносном веб-сайте, который отправляет запрос POST на https://site.com/email/change
со скрытым полем электронной почты, и автоматически включается session
cookie. Однако это можно легко уменьшить, используя флаг sameSite
в вашем файле cookie и добавив токен анти-CSRF.
Итак, как мне использовать файлы cookie для сохранения моих токенов OAuth 2.0?
Подведем итоги: вот различные способы хранения токенов:
- Вариант 1. Храните токен доступа в
localStorage
: подвержен XSS-атакам. - Вариант 2. Сохраните свой токен доступа в
httpOnly
cookie: подвержен CSRF, но может быть смягчен, немного лучше с точки зрения воздействия XSS. - Вариант 3. Сохраните токен обновления в
httpOnly
cookie: в безопасности от CSRF, немного лучше с точки зрения воздействия XSS.
Мы рассмотрим, как работает вариант 3, поскольку он лучший из трех.
Вариант 3. Сохраните токен доступа в памяти и сохраните токен обновления в файле cookie.
Почему это безопасно от CSRF? Хотя форма, отправленная на /refresh_token
, будет работать и будет возвращен новый токен доступа, злоумышленник не сможет прочитать ответ, если он использует форму HTML. Чтобы злоумышленник не смог успешно выполнить fetch
или AJAX
запрос и прочитать ответ, необходимо правильно настроить политику CORS сервера авторизации для предотвращения запросов с неавторизованных веб-сайтов.
Итак, как это работает?
Шаг 1. Верните токен доступа и обновите токен, когда пользователь аутентифицирован.
После аутентификации пользователя сервер авторизации вернет access_token
и refresh_token
. access_token
будет включен в тело ответа, а refresh_token
будет включен в файл cookie.
Обновить настройки cookie токена:
- Используйте флаг
httpOnly
, чтобы JavaScript не читал его. - Используйте флаг
secure=true
, чтобы его можно было отправлять только по HTTPS. - По возможности используйте флаг
SameSite=strict
, чтобы предотвратить CSRF. Это можно использовать только в том случае, если сервер авторизации имеет тот же сайт, что и ваш интерфейс. Если это не так, то ваш сервер авторизации должен установить заголовки CORS в серверной части или использовать другие методы, чтобы гарантировать, что запрос токена обновления может выполняться только авторизованными веб-сайтами.
Шаг 2. Сохраните токен доступа в памяти
Хранение токена в памяти означает, что вы помещаете этот токен доступа в переменную на своем интерфейсном сайте. Да, это означает, что токен доступа исчезнет, если пользователь переключится на другую вкладку или обновит сайт. Вот почему у нас есть токен обновления.
Шаг 3. Продлите токен доступа с помощью токена обновления
Когда токен доступа исчез или истек, нажмите конечную точку /refresh_token
, и токен обновления, который был сохранен в файле cookie на шаге 1, будет включен в запрос. Затем вы получите новый токен доступа, который сможете использовать для своих запросов API. Это означает, что ваш токен JWT может быть больше 4 КБ, и вы также можете поместить его в заголовок авторизации.
Заключение
Хотя файлы cookie все еще имеют некоторые уязвимости, этот метод предпочтительнее, чем localStorage
, когда это возможно. Это связано с тем, что и localStorage
, и файлы cookie уязвимы для XSS-атак, но злоумышленнику труднее атаковать, когда вы используете httpOnly
файлы cookie. Кроме того, файлы cookie уязвимы для атак CSRF, но эту угрозу можно уменьшить с помощью флага sameSite
и токенов анти-CSRF. Наконец, вы все равно можете заставить его работать, даже если вам нужно использовать заголовок Authorization: Bearer
или если ваш JWT больше 4 КБ.
Это также соответствует рекомендации сообщества OWASP:
Не храните идентификаторы сеансов в локальном хранилище, поскольку данные всегда доступны для JavaScript. Файлы cookie могут снизить этот риск с помощью флага
httpOnly
.
Это оно!
Это должно охватывать основы и помочь вам защитить свой сайт.
Ресурсы
При написании этого блога мы ссылались на несколько статей, особенно из этих статей:
- Пожалуйста, прекратите использовать локальное хранилище
- Полное руководство по работе с JWT на интерфейсных клиентах (GraphQL)
- Cookies vs Localstorage для сессий - все, что вам нужно знать
Вопросы и отзывы
Если вам нужна помощь или у вас есть отзывы, пожалуйста, оставьте комментарий здесь!
Этот пост написан командой Cotter - беспарольный вход на ваш сайт или в приложение.