Access Cookies from the Context Function not working

Hello,

A lot of documentation shows that we can get the authorization token from the header inside the context function like :

context: async ({ req, res }) => {
const token = req.headers.authorization || ‘’;
const user = await getUser(token);
return { user };
},

I want to do the same but using the cookie such as :

context: async ({ req, res }) => {
const cookie = req.headers.cookie || ‘’;
const user = await getUser(cookie[“token”]);
return { user };
},

But the context function does not include any cookie information, i always get undefined.
I have tried different attribute nothing works :

const cookie = req.headers.cookie || ‘’;

const cookie = req.cookies || ‘’;

I have create a middleware that can get the cookie without issues but when it comes to the context function the cookie disappear from the req variable.

Do you know why i can not access the cookie from the context function?
How can I pass the cookie value inside the context?

Do I have to use the middleware to extract the cookie and add the value of the cookie to the req.headers.authorization key and then use the req.headers.authorization inside my context function?

Is it the right way to do it?

Here is my code

import cookieParser from ‘cookie-parser’

const testmiddleware=(req,res,next)=>{
  console.log(req.cookies) # This is working
  res.cookie(‘auth’,102, { maxAge: 86400 * 2, httpOnly: true, secure: true, sameSite : ‘None’ });
  next()
}

app.use(
  ‘/’,
  cookieParser(),
  json(),
  cors(corsOptions),
  testmiddleware,
  expressMiddleware(server, {
    context: async ({ req,res,t }) => {
      console.log(req.cookies) #undefined
      console.log(req.headers.cookies) #undefined
    },
  }),
);

Thank you for your help

Hi @cyril36 are you using Apollo Server 3 or 4 for this? I would expect the cookie to be there on the headers in the context function.

Hello @watson

Thank you for your answer.

I am using apollo server 4,

The root cause seems to be the nginx reverse-proxy in front of my graphql backend.
If I directly request the graphql backend, i get the following header with the cookie :

{
host: ‘localhost:8002’,

accept: ‘/’,
‘sec-fetch-site’: ‘same-origin’,
‘sec-fetch-mode’: ‘cors’,
‘sec-fetch-dest’: ‘empty’,
referer: ‘http://localhost:8002/’,
‘accept-encoding’: ‘gzip, deflate, br’,
‘accept-language’: ‘en-US,en;q=0.9’,
cookie: ‘auth=102’        # I HAVE THE COOKIE HERE
}

If I send the request through the reverse proxy, the cookie get deleted as in the following header

{
host: ‘localhost:8002’,

accept: ‘/’,
‘sec-fetch-site’: ‘same-origin’,
‘sec-fetch-mode’: ‘cors’,
‘sec-fetch-dest’: ‘empty’,
referer: ‘http://localhost:8002/’,
‘accept-encoding’: ‘gzip, deflate, br’,
‘accept-language’: ‘en-US,en;q=0.9’,
}

My nginx setup is like :

server {
     listen 80;
     location /super {
         proxy_ssl_session_reuse off;
         proxy_set_header Origin http://localhost:8002; # the url of my react app
         proxy_hide_header Access-Control-Allow-Origin;
         add_header Access-Control-Allow-Origin $http_origin;
         add_header Access-Control-Allow-Headers *;
         proxy_pass http://172.17.0.1:8002;
    }

}
Do you know why?
what should i update in my proxy configuration to do not delete my cookie?

I’m not positive myself to be honest, but I think you need to use proxy_set_header to add that cookie header:

server {
     listen 80;
     location /super {
         proxy_ssl_session_reuse off;
         proxy_set_header Origin http://localhost:8002; # the url of my react app
         proxy_set_header cookie $cookie
         proxy_hide_header Access-Control-Allow-Origin;
         add_header Access-Control-Allow-Origin $http_origin;
         add_header Access-Control-Allow-Headers *;
         proxy_pass http://172.17.0.1:8002;
    }
…
}

this line gives me an error : unknown “cookie” variable, i will check online what to do but i hadalready try the following and it was not working (i think it is more or less the same thing that you suggested.

proxy_set_header Cookie “name=john; age=30; male=1”;

I have also tried this nginx configuration but no luck :

   proxy_pass_request_headers      on;

I forgot to mention earlier that in the graphql backend i have added this line :

app.set(‘trust proxy’,true);

I dont know if i have to add something else in the graphql backend to accept cookie from proxy

any other suggestion?

More i am thinking about it more i think it is an issue in graphql backend.

why would i be able to get the cookie in a middleware type of function but not in the context function.
So the cookie is correctly send to the graphql backend but between the middleware and the context function there is something that make it disappear.

I will share my code here just in case you see something wrong :

import { ApolloServer } from ‘@apollo/server’;
import { ApolloGateway } from ‘@apollo/gateway’;
import { readFileSync } from ‘fs’;
import bodyParser from ‘body-parser’;
const { json } = bodyParser;
import { expressMiddleware } from ‘@apollo/server/express4’;
import { ApolloServerPluginDrainHttpServer } from ‘@apollo/server/plugin/drainHttpServer’;
import { ApolloServerPluginInlineTrace } from ‘@apollo/server/plugin/inlineTrace’;
import express from ‘express’;
import http from ‘http’;
import cors from ‘cors’;
import cookieParser from ‘cookie-parser’

const supergraphSdl = readFileSync(‘./src/supergraph.graphql’).toString()
const gateway = new ApolloGateway({
   supergraphSdl,
   debug:true,
});
const app = express();
const httpServer = http.createServer(app);
const server = new ApolloServer({
   gateway,
   csrfPrevention: false,
   plugins: [ApolloServerPluginDrainHttpServer({ httpServer }),ApolloServerPluginInlineTrace()],
});
await server.start();

########### This middleware get the cookie and display it ###########
const testmdl=(req,res,next)=>{
   console.log(req.cookies) ### works
   res.cookie(‘auth’,102, { httpOnly: true, secure: false, sameSite : ‘None’ });
   next()
}
###########################################################
app.use(
   ‘/’,
   cookieParser(),
   json(),
   cors(),
   testmdl,
   expressMiddleware(server, {
########## This Context function does not get the Cookie in the header ###########
     context: async ({ req,res }) => {
       console.log(req.headers) # not working
       console.log(req.headers.cookie) # not working
     },
######################################################################
   }),
);

app.set(‘trust proxy’,true);

let port = 4000
await new Promise((resolve) => httpServer.listen({ port: port }, resolve));

console.log(🚀 Server ready at http://localhost:${port}/);

I hope this can help to help me :smiley:

@watson I have found the issue.
it is the same issue as the topic Can't pass session data into Apollo Server Context - #2 by trevor.scheer

I have not try with a real frontend yet. i am using apollo studio and apparently i have to add the following :
plugins: [ApolloServerPluginDrainHttpServer({ httpServer }),
ApolloServerPluginLandingPageLocalDefault({ includeCookies: true })],
});

So ,when Using Apollo Explorer, you have to setup the following to be able to use the Cookies in the context function :
plugins: [ApolloServerPluginDrainHttpServer({ httpServer }),
ApolloServerPluginLandingPageLocalDefault({ includeCookies: true })],
});

Thank you for your help.

1 Like