Почему кука исчезает после перезагрузки страницы и как это исправить

    При разработке веб-приложений на ASP.NET с разделением бэкенда и фронтенда (через ngrok) разработчики часто сталкиваются с проблемой: кука устанавливается корректно, но после обновления страницы (F5) она исчезает. Это нарушает работу аутентификации и сессий. Рассмотрим основные причины и пошаговое решение.

    Основные причины исчезновения куки

    Кука может пропадать из-за несоответствия настроек SameSite, Secure или политики CORS. В вашем коде используется SameSiteMode.None и Secure = true, что корректно для кросс-доменных запросов (через ngrok). Однако есть нюансы.

    1. Проблема с Secure-флагом и HTTP

    Если ваш сайт открыт по HTTP (а не HTTPS), браузер не сохранит куку с флагом Secure = true. Проверьте: ngrok по умолчанию предоставляет HTTPS-ссылку, но фронтенд может обращаться к нему через HTTP. Убедитесь, что все запросы идут по HTTPS. В противном случае установите Secure = false (только для разработки).

    2. Неправильная настройка SameSite

    Значение SameSiteMode.None требует обязательного использования HTTPS. Если соединение не защищено (HTTP), браузер (Chrome, Firefox) проигнорирует куку. Решение: либо используйте HTTPS, либо временно (для отладки) поставьте SameSiteMode.Lax - это позволит куке сохраняться при переходах с того же сайта.

    3. CORS и AllowCredentials

    Вы правильно настроили AllowCredentials() и SetIsOriginAllowed(origin => true). Но убедитесь, что на стороне фронтенда (JavaScript) в запросе (например, fetch или axios) указан параметр credentials: 'include'. Иначе браузер не отправит куку и не сохранит её после перезагрузки.

    Как проверить и исправить: пошаговая инструкция

    Шаг 1. Проверьте протокол

    Откройте вкладку Network в DevTools браузера. Найдите запрос, который устанавливает куку. Посмотрите на заголовок Set-Cookie - если там есть Secure, но соединение HTTP, браузер отбросит куку. Решение: используйте app.UseHttpsRedirection() в ASP.NET или настройте ngrok на HTTPS.

    Шаг 2. Настройте SameSite для разработки

    Временно измените SameSiteMode.None на SameSiteMode.Lax. Это позволит куке сохраняться при обычной навигации (перезагрузка страницы). После завершения разработки верните None и включите HTTPS.

    Шаг 3. Проверьте Expires / Max-Age

    Убедитесь, что Expires имеет корректное значение (например, +24 часа). Если кука не имеет срока жизни (сессионная), она будет удалена после закрытия вкладки. В вашем коде всё верно - Expires задан.

    Пример исправленного кода для разработки

    var cookieOptions = new CookieOptions
    {
        HttpOnly = true,
        Secure = false, // Временно, для HTTP
        SameSite = SameSiteMode.Lax, // Временно, для тестов
        Path = "/",
        Expires = DateTime.UtcNow.AddHours(options.Value.ExpiresHours)
    };

    Также на фронтенде (JavaScript) добавьте:

    fetch('https://your-ngrok-url/api/login', {
        method: 'POST',
        credentials: 'include',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(data)
    });

    После перезагрузки страницы кука должна сохраниться. Для продакшена обязательно верните Secure = true и SameSiteMode.None при использовании HTTPS.

    Дополнительные советы

    • Используйте app.UseCookiePolicy() с CookiePolicyOptions для глобальной настройки.
    • Проверьте, не блокирует ли браузер сторонние куки (в настройках конфиденциальности).
    • Для отладки открывайте DevTools -> Application -> Cookies - смотрите, какие куки сохранены для вашего домена.

    Часто задаваемые вопросы