Мы рассмотрели как работает OAuth 2.0 в последнем посте, в котором рассказывалось, как генерировать токены доступа и обновлять токены. Что дальше: как вы их надежно храните во внешнем интерфейсе?

Резюме о токене доступа и токене обновления

Токены доступа обычно представляют собой недолговечные токены JWT, подписанные вашим сервером и включаемые в каждый HTTP-запрос к вашему серверу для авторизации запроса.

Маркеры обновления обычно представляют собой долговечные непрозрачные строки, хранящиеся в вашей базе данных и используемые для получения нового маркера доступа по истечении срока его действия.

Где мне хранить свои токены во внешнем интерфейсе?

Есть 2 распространенных способа хранения ваших токенов: localStorage или файлы cookie. Существует много споров о том, какой из них лучше, и большинство людей склоняются к файлам cookie, чтобы они были более безопасными.

Давайте рассмотрим сравнение localStorage и файлов cookie, в основном на основе этого сообщения Пожалуйста, прекратите использование локального хранилища и комментариев к этому сообщению.

Локальное хранилище

Плюсы: удобно.

  • Это чистый JavaScript и удобный. Если у вас нет серверной части и вы полагаетесь на сторонний API, вы не всегда можете попросить их установить определенный файл cookie для вашего сайта.
  • Работает с API, которые требуют, чтобы вы поместили свой токен доступа в заголовок, как это Authorization Bearer ${access_token}.

Минусы: уязвим для XSS-атак.

Атака XSS происходит, когда злоумышленник может запустить JavaScript на вашем веб-сайте. Это означает, что злоумышленник может просто взять токен доступа, который вы сохранили в своем localStorage.

Атака XSS может произойти из-за стороннего кода JavaScript, включенного в ваш сайт, такого как React, Vue, jQuery, Google Analytics и т. Д. Практически невозможно не включить на свой сайт какие-либо сторонние библиотеки.

Печенье

Плюсы: файл cookie недоступен через JavaScript, следовательно, он не так уязвим для XSS-атак, как localStorage.

  • Если вы используете файлы cookie httpOnly и secure, это означает, что к ним нельзя получить доступ с помощью 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 по-прежнему имеют некоторые уязвимости, лучше, чем localStorage, когда это возможно. Почему?

  • И localStorage, и файлы cookie уязвимы для XSS-атак, но злоумышленнику сложнее провести атаку, когда вы используете httpOnly файлы cookie.
  • Файлы cookie уязвимы для атак CSRF, но их можно уменьшить с помощью флага sameSite и токенов против CSRF.
  • Вы все равно можете заставить его работать, даже если вам нужно использовать заголовок Authorization: Bearer или ваш JWT больше 4 КБ.

Это также согласуется с рекомендацией сообщества OWASP:

Не храните идентификаторы сеанса в локальном хранилище, поскольку данные всегда доступны для JavaScript. Файлы cookie могут снизить этот риск с помощью флага httpOnly.
- OWASP: HTML5 Security Cheat Sheet

Итак, как мне использовать файлы cookie для сохранения моих токенов OAuth 2.0?

Напомним, вот различные способы хранения токенов:

  • Вариант 1. Храните свой токен доступа в localStorage: подвержен XSS-атакам.
  • Вариант 2. Сохраните свой токен доступа в httpOnly cookie: подвержен CSRF, но может быть смягчен, немного лучше для XSS.
  • Вариант 3. Сохраните токен обновления в httpOnly cookie: безопасно от CSRF, немного лучше для XSS.

Мы рассмотрим, как работает вариант 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 КБ, и вы также можете поместить его в заголовок авторизации.

Это оно!

Это должно охватывать основы и помочь вам защитить свой сайт. Этот пост написан командой Cotter - мы создаем легкое, быстрое и беспарольное решение для входа в систему для веб-сайтов и мобильных приложений.

Если вы создаете процесс входа в систему для своего веб-сайта или мобильного приложения, эти статьи могут помочь:

использованная литература

Мы ссылались на множество статей по этой теме, особенно из этих статей:

Вопросы и отзывы

Если вам нужна помощь или у вас есть отзывы, напишите нам на Cotter’s Slack Channel! Мы здесь, чтобы помочь.

Готовы использовать Cotter?

Если вам понравился этот пост и вы хотите интегрировать Cotter в свой веб-сайт или приложение, вы можете создать бесплатную учетную запись и ознакомиться с нашей документацией.

Первоначально опубликовано на https://blog.cotter.app 21 июля 2020 г.