- Вопрос или проблема
- Описание проблемы
- Структура проекта:
- Детали
- Дополнительная информация
- Ответ или решение
- Проблема с хранилищем токенов в куках в Next.js на Vercel
- Описание проблемы
- Проверка конфигурации куки
- Проверка конфигурации 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
. Обратите внимание на следующие моменты:
-
Путь и срок действия:
'Set-Cookie': `token=${token}; Path=/; max-age=${cookieExpiresInSeconds}`,
Убедитесь, что
Path
установлен на/
, чтобы куки были доступны на всех маршрутах. -
Свойства куки:
Важно задать свойства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.
Рекомендации по дальнейшим действиям
- Логи и отладка: Включите логи, чтобы отслеживать процесс установки куки и убедиться, что они правильно получаются при каждом вызове.
- Проверка заголовков в сетевых запросах: Убедитесь, что заголовки, связанные с куками, не блокируются CORS. Вы можете просмотреть заголовки запросов и ответов в инструментах разработчика вашего браузера.
- Настройки для фронтенда: Если существует клиентская часть вашего приложения, убедитесь, что нет вызовов API, которые игнорируют куки. Запросы должны включать
credentials: 'include'
для передачи куки:fetch(url, { method: 'GET', credentials: 'include', });
Заключение
Проблема с потерей куков может быть решена, тщательно проверяя конфигурацию и настройки сервера, а также правильно устанавливая параметры куки. Тщательная отладка и логирование помогут выявить истинные причины проблемы. Если вы продолжаете сталкиваться с трудностями, возможно, стоит обратиться к документации Next.js и Vercel, а также проверить актуальность используемых версий инструментов.