if you use passport.js
const app = express();
app.use(session({
secret: 'test',
}));
app.use(passport.initialize());
app.use(passport.session());
const server = new ApolloServer({
typeDefs,
resolvers,
context: ({ req }) => {
const user = req.user;
console.log({ user, 'req.session': req.session });
return {
user,
orm,
dataloader: compose(orm),
};
},
});
app.use('/graphql', (req, res, next) => {
console.log({
url: req.protocol + '://' + req.get('host') + req.originalUrl,
user: req.user,
sessionID: req.sessionID,
session: req.session,
cookie: JSON.stringify(req.cookie),
});
return next();
});
server.applyMiddleware({ app, path: '/graphql' });
if i comment out server.applyMiddleware({ app, path: '/graphql' });,
passport js session is present, otherwise not
if session would be present, it would able to restore user
full PR: https://github.com/eugene-matvejev/node-explorer/pull/73
I'm also seeing this issue. It doesn't seem like passport session is known to apollo's applyMiddleware
Any update?
My issue was in the graphql playground. So what I ended up doing was creating a session for a user in postman, then appending that session id to a header which I could control in playground. Then in the context function, I read the header value and looked up the valid session from store so I could append the user object to context. Not the cleanest but finally let me have the user object in context so my resolvers could work as if there was a valid session.
I think the fundamental issues is that playground doesn't have a good way to initiate a session and I'm not entirely sure its within its scope to do so.
@jonesmac I was so close to implementing your workaround since it's been 3 days that I've been trying to figure out what the heck is wrong with my code why session cookies are not appearing on front-end but being saved in a store e.g in my case Redis. So the issue in my case is I need to also set the credentials: include in Apollo Client
I have posted my answer here for the front-end: https://github.com/apollographql/apollo-client/issues/4190#issuecomment-540023803
As for my back-end, it's like this:
```js
const corsOptions = {
origin: ['http://localhost:5000', /.myproject.com$/],
credentials: true,
};
app.use(cors(corsOptions));
// setup session handling options
const sessionOptions = {
name: config.sessionStore.name,
secret: config.sessionStore.secret,
store: new RedisStore({ client: redisDB, prefix: config.sessionStore.redisSessionIdPrefix }),
resave: false,
saveUninitialized: false,
cookie: {
maxAge: config.sessionStore.lifetime,
sameSite: true,
secure: process.env.NODE_ENV === 'production',
},
};
app.use(session(sessionOptions));
const apolloServer = new ApolloServer({
typeDefs,
resolvers,
context: ({ req, res }) => ({
session: req.session,
redis: redisDB,
}),
playground:
process.env.NODE_ENV === 'production'
? false
: {
settings: {
'request.credentials': 'include',
},
},
});
apolloServer.applyMiddleware({ app, path: '/graphql', cors: false });
If anyone is looking for a working example using Apollo server and Passport.js here are one without and one with graphql-passport. There is also a couple of blog posts linked there if you want a more detailed explanation.
arvi's solution worked for me. Apparently, at line:
apolloServer.applyMiddleware({ app, path: '/graphql', cors: false });
cors: false is a crucial setting
I have the same issue. Setting cors to false obviously solves the problem, but how will the server secure client-server communication with cors set to false?
I had my cors originally set to the recommended option setting in numerous documentations, yet nothing works.
const corsOptions = { credentials: true, origin: '*', }
What is the working option setting?
@jonesmac I was so close to implementing your workaround since it's been 3 days that I've been trying to figure out what the heck is wrong with my code why session cookies are not appearing on front-end but being saved in a store e.g in my case Redis. So the issue in my case is I need to also set the
credentials: includeinApollo ClientI have posted my answer here for the front-end: apollographql/apollo-client#4190 (comment)
As for my back-end, it's like this:
const corsOptions = { origin: ['http://localhost:5000', /\.myproject\.com$/], credentials: true, }; app.use(cors(corsOptions)); // setup session handling options const sessionOptions = { name: config.sessionStore.name, secret: config.sessionStore.secret, store: new RedisStore({ client: redisDB, prefix: config.sessionStore.redisSessionIdPrefix }), resave: false, saveUninitialized: false, cookie: { maxAge: config.sessionStore.lifetime, sameSite: true, secure: process.env.NODE_ENV === 'production', }, }; app.use(session(sessionOptions)); const apolloServer = new ApolloServer({ typeDefs, resolvers, context: ({ req, res }) => ({ session: req.session, redis: redisDB, }), playground: process.env.NODE_ENV === 'production' ? false : { settings: { 'request.credentials': 'include', }, }, }); apolloServer.applyMiddleware({ app, path: '/graphql', cors: false });
My Dear Lord this got me out of a 4 hours bug hole. Thank you very much.
I see you have the apollo-server cors set to false. It also works fine with values like { credentials: true, origin: '*' }, but to work in tests also set the following to express
app.set('trust proxy', 1)
Most helpful comment
@jonesmac I was so close to implementing your workaround since it's been 3 days that I've been trying to figure out what the heck is wrong with my code why session cookies are not appearing on front-end but being saved in a store e.g in my case Redis. So the issue in my case is I need to also set the
credentials: includeinApollo ClientI have posted my answer here for the front-end: https://github.com/apollographql/apollo-client/issues/4190#issuecomment-540023803
As for my back-end, it's like this:
```js
const corsOptions = {
origin: ['http://localhost:5000', /.myproject.com$/],
credentials: true,
};
app.use(cors(corsOptions));
// setup session handling options
const sessionOptions = {
name: config.sessionStore.name,
secret: config.sessionStore.secret,
store: new RedisStore({ client: redisDB, prefix: config.sessionStore.redisSessionIdPrefix }),
resave: false,
saveUninitialized: false,
cookie: {
maxAge: config.sessionStore.lifetime,
sameSite: true,
secure: process.env.NODE_ENV === 'production',
},
};
app.use(session(sessionOptions));
const apolloServer = new ApolloServer({
typeDefs,
resolvers,
context: ({ req, res }) => ({
session: req.session,
redis: redisDB,
}),
playground:
process.env.NODE_ENV === 'production'
? false
: {
settings: {
'request.credentials': 'include',
},
},
});
apolloServer.applyMiddleware({ app, path: '/graphql', cors: false });