Браузер не сохраняет файлы cookie HttpOnly React/Django

У меня есть интерфейс netlify app.mydomain.com и REST API django ninja api.mydomain.com. Когда я отправляю запрос на свою конечную точку входа, API успешно возвращается с ключом доступа (который я храню в состоянии приложения) и токеном обновления в виде безопасного файла cookie только для http. Я вижу, что этот файл cookie возвращается, просматривая заголовки ответов в инструментах разработки. Однако файл cookie вообще не сохраняется в браузере. Я ответил на множество других вопросов/ответов и считаю, что реализовал все необходимое, но он все еще не работает.

Мой вызов API входа из внешнего интерфейса:

await fetch(
  AUTH_URL_OBTAIN,
  {
    method: RequestMethod.POST,
    headers: {"Content-Type": "application/json"},
    body: JSON.stringify({username: formData.email, password: formData.password}),
    credentials: "include",
  },
);

На серверной стороне файл cookie устанавливается следующим образом:

response.set_cookie(
    key = "refresh",
    value=refresh_token,
    expires=datetime.fromtimestamp(refresh_token_payload["exp"], timezone.utc),
    httponly=True,
    samesite = "none",
    secure=True,
    path = "/api/auth/web/token-refresh",
    domain = ".mydomain.com",
)

У меня также установлены следующие настройки (замена значений переменных среды):

CSRF_TRUSTED_ORIGINS = ["https://app.mydomain.com"]
CORS_ALLOWED_ORIGINS = ["https://app.mydomain.com"]
CORS_ORIGIN_WHITELIST = ["https://app.mydomain.com"]
CORS_ALLOW_CREDENTIALS = True

Ответ на вход в систему предоставляет токен доступа (который работает, как и ожидалось — я могу прекрасно выполнять вызовы API, используя это, и иметь credentials: include на всех fetch запросах), а заголовки ответов приведены ниже:

Access-Control-Allow-Credentials: true

Access-Control-Allow-Origin: https://app.mydomain.com

Content-Length: 661

Content-Type: application/json; charset=utf-8

Cross-Origin-Opener-Policy: same-origin

Date: Thu, 06 Jun 2024 14:06:22 GMT

Referrer-Policy: same-origin

Server: daphne

Set-Cookie: refresh=ey...3uQ; Domain=.mydomain.com; expires=Sat, 06 Jul 2024 14:06:22 GMT; HttpOnly; Max-Age=2592000; Path=/api/auth/web/token-refresh; SameSite=none; Secure

Vary: origin

X-Content-Type-Options: nosniff

X-Frame-Options: DENY

Я сейчас в некоторой растерянности - буду очень признателен за любые советы, спасибо!

просто любопытно, что произойдет, если вы не включите HttpOnly (просто установите обычный файл cookie), это сработает? Я предполагаю, что это может быть вызвано не HttpOnly

Damzaky 09.06.2024 02:49

Пробовали ли вы добавить maxAge в ответ cookie, а также SameSite: «lax» и проверить

Tarun Kantiwal 09.06.2024 18:22

Привет, спасибо за ваши комментарии. @Damzaky да, ты прав, другие файлы cookie настраиваются нормально. Кажется, установлен файл cookie sessionid, который предназначен только для http. Также устанавливается файл cookie csrftoken, который не является только http. Файл cookie обновления по-прежнему не установлен. @TarunKantiwal установлен максимальный возраст, и я попробовал все варианты для samesite.

RHSmith159 10.06.2024 14:46

хм, странно, а как насчет изменения имени ключа cookie с refresh на другое, например refreshone?

Damzaky 10.06.2024 14:58

Я тоже попробовал, но все равно не сохраняется. Я вижу файл cookie в ответе, и браузер не показывает никаких ошибок, но он просто не сохраняет файл cookie. Я тоже пробовал на сафари, и там тоже не работает.

RHSmith159 10.06.2024 17:21

Я не уверен, но, может быть, вам стоит попробовать установить срок годности в будущем?

franckfournier 10.06.2024 20:28

Токен доступа также установлен как Cookie? Вы устанавливаете токен доступа точно так же, и он работает, но обновление не работает?

Chukwujiobi Canon 10.06.2024 20:31

Вам следует проверить несколько моментов: 1. Path=/api/auth/web/token-refresh: файл cookie будет сохранен только для этого пути. 2. Secure: файл cookie будет установлен только на https 3.expires: его следует удалить в пользу max-age 4.Domain=.mydomain.com: файл cookie будет доступен только для субдомена

Duannx 11.06.2024 06:02

Привет всем, спасибо за все комментарии, очень ценю всю помощь. Франкфурнье, да, дата истечения срока действия установлена ​​на будущую дату, пример, который я разместил выше, относился к файлу cookie, установленному в этот день. ChukwujiobiCanon, токен доступа хранится в состоянии приложения. Думаю, мне, возможно, тоже придется хранить токен обновления в состоянии приложения? Дуаннкс, спасибо за этот контрольный список, я просмотрю его сегодня и отчитаюсь!

RHSmith159 11.06.2024 13:51

@Duannx Думаю, ты справился!! Я изменил Path на /, и теперь устанавливается файл cookie обновления! Однако я немного смущен: почему браузер не устанавливает файл cookie, когда путь установлен на конечную точку полного обновления? Если вы хотите опубликовать свое предложение проверить путь в качестве ответа, я приму + награду!

RHSmith159 11.06.2024 15:39
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
2
10
149
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Политики безопасности браузера могут блокировать файлы cookie из/в запросы ajax. Видеть

Для API перекрестного происхождения я бы предпочел вообще не использовать файлы cookie. Представьте себе любой API-клиент, кроме браузера! Файлы cookie предназначены для отслеживания сеансов просмотра веб-сайта, а не для хранения состояния в произвольных http-клиентах.

Просто включите токен обновления в тело ответа и сохраните его также в состоянии вашего приложения.

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

RHSmith159 11.06.2024 13:48

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

Мне кажется, ваша проблема связана со свойством expires файла cookie. Это приводит к тому, что файл cookie становится постоянным, и я ожидаю, что он установлен неправильно. Все остальное выглядит правильно.

Я думаю, вы можете решить свою проблему, если удалите это свойство cookie. Выполнение do также является рекомендуемым методом обеспечения безопасности и приводит к созданию файла cookie сеанса, который удаляется при закрытии браузера.

Кроме того, невозможно делать предположения о форматах токенов обновления или полезных нагрузках. Вместо этого токен обновления считается просроченным, когда вы пытаетесь использовать его в emdpoint токена сервера авторизации и получаете ответ с кодом ошибки invalid_grant. Поэтому при использовании файлов cookie, представляющих токены, всегда учитывайте срок действия базового токена.

Ответ принят как подходящий

Это не имеет ничего общего ни с Django, ни с React. Это способ установки файла cookie.

  1. Файл cookie с path может быть установлен где угодно, но доступен только на этом пути и его дочернем элементе. Таким образом, вы можете увидеть файл cookie только при посещении страницы /api/auth/web/token-refresh
  2. Рассмотрите возможность использования Max-Age вместо Expires, так как это менее подвержено ошибкам. Это цитата со страницы MDN:

Expires доступен дольше, чем Max-Age, однако Max-Age менее подвержен ошибкам и имеет приоритет, если установлены оба параметра. Обоснование этого заключается в том, что когда вы устанавливаете дату и время Expires, они относятся к клиенту, на котором устанавливается файл cookie. Если на сервере установлено другое время, это может привести к ошибкам.

  1. Безопасный файл cookie можно настроить только через https или localhost.

Ждал от вас ответа.

Chukwujiobi Canon 12.06.2024 18:52

Еще раз спасибо за помощь, установка пути к / в конце концов помогла, а также действительно интересная информация о данных Max-Age/Expires. Ваше здоровье!

RHSmith159 12.06.2024 21:29

Пожалуйста ;-)

Duannx 13.06.2024 04:37

Другие вопросы по теме

Похожие вопросы

Как устранить ошибку «AG Grid: не удалось создать сетку»?
Холст Threejs не уменьшается при повороте телефона назад
Как добавить объект JSON внутри тега сценария в NextJS
Анимация навигации с помощью Framer Motion
Как визуализировать сноски с отсутствующими определениями, используя реакции-уценку и примечание-gfm
Css работает локально, но не применяется после запуска «npm run build» в сборке в приложении реагирования
Правильный способ повторить тестовую логику в Cypress с динамическим повторным рендерингом DOM
Django, React, Axios возвращают html вместо данных json
Как предварительно настроить базовую анимацию движения кадра в полиморфном компоненте, использующем слот Radix?
Почему PWA на основе реагирования, размещенное в моей службе приложений Azure, случайно начинает возвращать ошибку 500 для ВСЕХ вызовов POST (GET работает нормально)? Исправлено: Перезапустить браузер?