Next.js куки-токен не сохраняется в продакшене на Vercel

Вопрос или проблема

Описание проблемы

Я сталкиваюсь с проблемой, когда токен cookie моего приложения Next.js не сохраняется в продуктивной среде на Vercel. Приложение работает нормально в среде разработки, но после развертывания токен cookie устанавливается, а затем исчезает через несколько секунд. Я хотел бы понять, почему это происходит и как это исправить.

Структура проекта:

  • web (корень)
    • src/middleware.ts
    • src/app/api/auth/call-back/route.ts
    • next.config.js

Детали

Когда приложение запускается в первый раз, cookie (redirectTo) устанавливается и корректно сохраняется. Вот соответствующая часть кода:

Код – web/src/middleware.ts:

import { NextRequest, NextResponse } from 'next/server';

const signInURL = `https://github.com/login/oauth/authorize?client_id=${process.env.NEXT_PUBLIC_GITHUB_CLIENT_ID}`;

export function middleware(request: NextRequest) {
  const token = request.cookies.get('token')?.value;

  if (!token) {
    return NextResponse.redirect(signInURL, {
      headers: {
        'Set-Cookie': `redirectTo=${request.url}; Path=/; HttpOnly; max-age=20;`,
      },
    });
  }

  return NextResponse.next();
}

export const config = {
  matcher: '/memories/:path*',
};

После возврата с кодом OAuth GitHub токен правильно устанавливается на стороне сервера, но почти сразу исчезает в продуктивной среде.

Код – src/app/api/auth/call-back/route.ts:

import { api } from '@/lib/api';
import { NextRequest, NextResponse } from 'next/server';

export async function GET(request: NextRequest) {
  const { searchParams } = new URL(request.url);
  const code = searchParams.get('code');
  const redirectTo = request.cookies.get('redirectTo')?.value;

  try {
    const registerResponse = await api.post('/register', {
      code,
    });

    const { token } = registerResponse.data;

    if (!token) {
      return new NextResponse('Токен не найден', { status: 400 });
    }

    const redirectURL = redirectTo ?? new URL("https://stackoverflow.com/", request.url);
    const cookieExpiresInSeconds = 60 * 60 * 24 * 30; // 30 дней

    return NextResponse.redirect(redirectURL, {
      headers: {
        'Set-Cookie': `token=${token}; Path=/; max-age=${cookieExpiresInSeconds}`,
      },
    });
  } catch (error) {
    console.error('Ошибка регистрации токена:', error);
    return new NextResponse('Не удалось зарегистрировать токен', { status: 500 });
  }
}

Код – next.config.js:

/** @type {import('next').NextConfig} */
const nextConfig = {
  images: {
    domains: ['avatars.githubusercontent.com', 'localhost', 'https://mydomain.vercel.app/'],
  },
  async headers() {
    return [
      {
        source: "/api/:path*",
        headers: [
          { key: "Access-Control-Allow-Origin", value: "*" },
          { key: "Access-Control-Allow-Methods", value: "GET,OPTIONS,PATCH,DELETE,POST,PUT" },
        ],
      },
    ];
  },
};

module.exports = nextConfig;

Дополнительная информация

  • Эта проблема возникает только в продуктивной среде на Vercel.
  • Версия Next.js: 13.4

Что я пробовал:

  • Установка Secure, HttpOnly и SameSite=None
  • Настройка значений SameSite (None, Strict, Lax)

Кто-нибудь сталкивался с этой проблемой ранее? Любые подсказки о том, почему токен cookie исчезает так быстро и как решить эту проблему, были бы очень ценны.

Ответ или решение

Проблема с хранилищем токенов в куках в Next.js на Vercel

Описание проблемы

С учетом вашего описания проблемы, вы столкнулись с ситуацией, при которой токен куки не сохраняется в среде продакшн на платформе Vercel, в то время как в окружении разработки все работает корректно. Токен устанавливается, но исчезает через несколько секунд. Это может быть связано с несколькими причинами, любая из которых может быть важна для решения вашей задачи.

Проверка конфигурации куки

Первым шагом давайте проанализируем установку куки. В вашем коде установлены куки с помощью заголовка Set-Cookie. Обратите внимание на следующие моменты:

  1. Путь и срок действия:

    'Set-Cookie': `token=${token}; Path=/; max-age=${cookieExpiresInSeconds}`,

    Убедитесь, что Path установлен на /, чтобы куки были доступны на всех маршрутах.

  2. Свойства куки:
    Важно задать свойства HttpOnly, Secure, и SameSite для куки. Наиболее безопасным подходом будет уставновка Secure в значение true, особенно если ваше приложение работает через HTTPS.
    Пример:

    'Set-Cookie': `token=${token}; Path=/; max-age=${cookieExpiresInSeconds}; HttpOnly; Secure; SameSite=Strict`

    Убедитесь, что:

    • Secure — куки будут передаваться только по защищенному соединению (HTTPS).
    • HttpOnly — куки не доступны через JavaScript, что защищает их от атак XSS.
    • SameSite — помогает предотвратить атаки CSRF, поэтому на этапе тестирования лучше использовать Lax или Strict.

Проверка конфигурации Vercel

Убедитесь, что ваше приложение настроено правильно на Vercel. Проверьте, что для вашего домена включен HTTPS. Использование нестандартного порта или старых протоколов может вызвать проблемы с куками. Используйте только безопасные и актуальные URL.

Темы сопоставления для идентификации

Когда куки устанавливаются и доступны в одном месте, но исчезают в другом, стоит обратить внимание на следующее:

  • Используете ли вы несколько механизмов аутентификации? Если да, убедитесь, что они не конфликтуют друг с другом.
  • Проверьте наличие ошибок в консоли и сетевых запросах на предмет блокировок или ошибок настройки CORS.

Рекомендации по дальнейшим действиям

  1. Логи и отладка: Включите логи, чтобы отслеживать процесс установки куки и убедиться, что они правильно получаются при каждом вызове.
  2. Проверка заголовков в сетевых запросах: Убедитесь, что заголовки, связанные с куками, не блокируются CORS. Вы можете просмотреть заголовки запросов и ответов в инструментах разработчика вашего браузера.
  3. Настройки для фронтенда: Если существует клиентская часть вашего приложения, убедитесь, что нет вызовов API, которые игнорируют куки. Запросы должны включать credentials: 'include' для передачи куки:
    fetch(url, {
      method: 'GET',
      credentials: 'include',
    });

Заключение

Проблема с потерей куков может быть решена, тщательно проверяя конфигурацию и настройки сервера, а также правильно устанавливая параметры куки. Тщательная отладка и логирование помогут выявить истинные причины проблемы. Если вы продолжаете сталкиваться с трудностями, возможно, стоит обратиться к документации Next.js и Vercel, а также проверить актуальность используемых версий инструментов.

Оцените материал
Добавить комментарий

Капча загружается...