Сеансовый cookie не установлен в браузере - PullRequest
0 голосов
/ 14 января 2019

У меня есть клиентский клиент, работающий на пользовательском сервере 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, но он прозрачен для браузера и не является ни постоянным, ни установленным (теряется при обновлении или изменении страницы). Забавно, но я все еще могу делать аутентифицированные запросы данных.

...