У меня есть клиентский интерфейс, работающий на настраиваемом сервере Next.js, который извлекает данные с помощью клиента apollo. Мой бэкэнд - это графическая йога с призмой, использующая экспресс-сессию.
У меня проблема с выбором правильных настроек CORS для моего клиента и бэкэнда, чтобы файл cookie был правильно установлен в браузере, особенно на heroku.
В настоящее время я отправляю запрос graphql от клиента с помощью apollo-client, имеющего опцию
credentials: "include", но также пробовал "same-origin" без лучшего результата.
Я вижу ответ от клиента cookie из моего бэкэнда в заголовке Set-Cookie и в devTools / application / cookies. Но этот файл cookie прозрачен для браузера и теряется при обновлении.
С учетом сказанного я также попытался реализовать некоторое дополнительное ПО для apollo client как apolloLink, которое перехватывает cookie от response.headers, но оно пустое.
Пока что я думаю о том, чтобы использовать эти два пути решения проблемы.
(Я использую CORS только потому, что браузер не позволяет получать данные без него.)
КЛИЕНТ
Конфигурация ApolloClient для клиентской стороны:
const httpLink = new HttpLink({
credentials: "include",
uri: BACKEND_ENDPOINT,
});
Использование и конфигурация клиентского CORS:
app
.prepare()
.then(() => {
const server = express()
.use(cors(corsOptions))
.options("*", cors(corsOptions))
.set("trust proxy", 1);
...here goes rest of implementation
const corsOptions = {
origin: [process.env.BACKEND_ENDPOINT, process.env.HEROKU_CORS_URL],
credentials: true,
allowedHeaders: ["Content-Type", "Authorization", "X-Requested-With", "X-Forwarded-Proto", "Cookie", "Set-Cookie", '*'],
methods: "GET,POST",
optionsSuccessStatus: 200
};
Моя попытка получить заголовки из ответа в apolloClient (но заголовки пусты и данные не извлекаются впоследствии):
const middlewareLink = new ApolloLink((operation, forward) => {
return forward(operation).map(response => {
const context = operation.getContext();
const {response: {headers}} = context;
if (headers) {
const cookie = response.headers.get("set-cookie");
if (cookie) {
//set cookie here
}
}
return response;
});
});
НАЗАД
Реализация CORS (помните, что это gql-yoga, поэтому мне нужно сначала раскрыть ее)
server.express
.use(cors(corsOptions))
.options("*", cors())
.set("trust proxy", 1);
...here goes rest of implementation
const corsOptions = {
origin: [process.env.CLIENT_URL_DEV, process.env.CLIENT_URL_PROD, process.env.HEROKU_CORS_URL],
credentials: true,
allowedHeaders: ["Content-Type", "Authorization", "X-Requested-With", "X-Forwarded-Proto", "Cookie", "Set-Cookie"],
exposedHeaders: ["Content-Type", "Authorization", "X-Requested-With", "X-Forwarded-Proto", "Cookie", "Set-Cookie"],
methods: "GET,HEAD,PUT,PATCH,POST,OPTIONS",
optionsSuccessStatus: 200
};
Настройки сеанса, магазин - connect-redis
server.express
.use(
session({
store: store,
genid: () => uuidv4(v4options),
name: process.env.SESSION_NAME,
secret: process.env.SESSION_SECRET,
resave: true,
rolling: true,
saveUninitialized: false,
sameSite: false,
proxy: STAGE,
unset: "destroy",
cookie: {
httpOnly: true,
path: "/",
secure: STAGE,
maxAge: STAGE ? TTL_PROD : TTL_DEV
}
})
)
Я ожидаю, что cookie сеанса будет установлен на клиенте после аутентификации.
Фактический результат: Cookie виден только в заголовке ответа Set-Cookie, но прозрачен для браузера, не сохраняется и не устанавливается (теряется при обновлении или изменении страницы). Как ни странно, я все еще могу делать аутентифицированные запросы данных.
к сожалению, нет - мы перешли с next.js на cra по этой глупой причине
Мне удалось решить эту проблему, используя пользовательские домены во фронтенде и бэкэнде в heroku.





Это может быть не проблема CORS, это похоже на проблему сторонних файлов cookie.
Поведение в разных браузерах может отличаться, поэтому я рекомендую протестировать несколько из них. Firefox (начиная с версии 77) кажется менее строгим. В Chrome (начиная с версии 83) в правом углу строки URL-адреса есть индикатор, когда сторонний файл cookie заблокирован. Вы можете подтвердить, являются ли сторонние файлы cookie причиной проблемы, создав исключение для текущего веб-сайта.
Предполагая, что ваша текущая настройка выглядит следующим образом:
frontend.com
backend.herokuapp.com
Использование личного домена для вашего бэкэнда, который является поддоменом вашего внешнего интерфейса, решит вашу проблему:
frontend.com
api.frontend.com
Следующая установка не будет работать, потому что herokuapp.com включен в список общедоступных суффиксов Mozilla Foundation:
frontend.herokuapp.com
backend.herokuapp.com
ты решил это?