Как защитить токен обновления в системе JWT, когда он отправляется в виде HttpOnly cookie
В моем проекте React + Django в настоящее время я отправляю токен обновления в виде файла cookie HttpOnly. Проблема с файлами cookie HttpOnly заключается в том, что они автоматически отправляются браузером, что делает их уязвимыми для атак CSRF. Чтобы решить эту проблему, я решил добавить токен CSRF для запроса на обновление. Однако проблема, с которой я сталкиваюсь, заключается в том, что я не могу прочитать токен CSRF с помощью JavaScript. Я думаю, это связано с тем, что мой интерфейс и серверная часть находятся в разных доменах. Когда я поискал в Интернете, то обнаружил, что межсайтовые файлы cookie не могут быть прочитаны с помощью JavaScript. Если это так, то каковы возможные способы защиты запроса токена обновления?
Вам не нужно считывать файл cookie обновления с помощью JS (и не следует). Вместо этого подключите его к отдельному механизму токенов CSRF (шаблон двойной отправки файлов cookie) или используйте файлы cookie на том же сайте. Django уже поддерживает этот рабочий процесс "из коробки".
В домене, который выдает cookie, задайте заголовок ответа CORS, подобный этому, с вашим именем заголовка, чтобы JS мог прочитать заголовок csrf:
Access-Control-Expose-Headers: csrf
АЛЬТЕРНАТИВНЫЙ ВАРИАНТ
Токены CSRF, однако, немного неудобны, например, вам может потребоваться сохранить их в локальном хранилище для надежной работы с несколькими вкладками, что не очень удобно.
Вместо этого вы можете использовать SameSite и CORS для реализации защиты CSRF без необходимости в заголовке CSRF:
- Используйте SameSite=strict, чтобы запретить другим сайтам отправлять обновленный файл cookie.
- Используйте CORS для ограничения доступа к другим источникам на том же сайте, что и приложение React.
- Конечным точкам сервера, использующим токен обновления, может потребоваться пользовательский заголовок типа
version=1
, чтобы предотвратить простые запросы из других источников в обход ограничений CORS.
Вы можете прочитать больше об этом шаблоне в документе OAuth для браузерных приложений.