У меня есть клиентский клиент, работающий на пользовательском сервере Next.js, который извлекает данные с помощью клиента apollo.
Мой бэкэнд - это Graphql-йога с призмой с использованием экспресс-сессии.
У меня проблема с выбором правильных настроек 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;
});
});
BACKEND
Реализация CORS (помните, что это gql-йога, поэтому мне нужно сначала выставить экспресс из нее)
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, но он прозрачен для браузера и не является ни постоянным, ни установленным (теряется при обновлении или изменении страницы). Забавно, но я все еще могу делать аутентифицированные запросы данных.