0
votes

For our portal, i integrated my express server with passport to authenticate user. Once user authenticated need to fetch details for user from our api using same session from client. passport authentication working for my portal and able to see identity provider data for user logged in. but when any GraphQL call executed from react side, Apollo servers don't have user session in its request but express had.

Followed the steps mentioned here https://www.apollographql.com/docs/apollo-server/essentials/server.html#ssl but when setting up context for ApolloServer, req don't have passport in its session.

        const express = require('express');
        const session = require('express-session');
        const { ApolloServer } = require('apollo-server-express');
        const addResolveFunctionsToSchema = require('graphql-tools').addResolveFunctionsToSchema;
        const mongooseConnection = require('./src/persistence/mongooseConnection');
        const MongoSession = require('connect-mongo')(session);
        const config = require('config');
        const mongo = config.get('mongo');
        const fs = require('fs');
        const https = require('https');
        const bodyParser = require('body-parser');
        const cookieParser = require('cookie-parser');
        const configSession = config.get('session');
        const configPassport = config.get('passport');
        const configCommon = config.get('common');
        const resolvers = require('./src/resolvers');
        const schema = require('./src/schema');
        const uri = `${mongo.uri}/${mongo.database}`;
        const app = express();
        var passport = require('passport');
        const SamlStrategy = require('passport-saml').Strategy;
        const authRoute = require('./routes/auth');

        const apiRoute = require('./routes/userDetails');
        const Helmet = require('helmet');
        require('reflect-metadata');

        mongooseConnection.create();

        let mongoOptions = {};

        const mongoSessionStore = new MongoSession({
            url: `${uri}`,
            mongoOptions: mongoOptions,
            collection: configSession.mongo.collection
        });
        addResolveFunctionsToSchema(schema, resolvers);

        passport.use(
            new SamlStrategy(
                {
                    entryPoint: configPassport.entry_point,
                    // issuer: 'passport-saml',
                    protocol: 'https',
                    callbackURL: `${configCommon.dns}/${configPassport.callback_url}`,
                    // cert: adfsTokenSigningCert,
                    identifierFormat: null,
                    forceAuthn: true,
                    signatureAlgorithm: 'sha256',
                    acceptedClockSkewMs: -1
                },
                (profile, cb) => {
                    cb(null, profile);
                }
            )
        );

        passport.serializeUser(function(user, done) {
            done(null, userData);
        });

        passport.deserializeUser(function(obj, done) {
            done(null, obj);
        });

        app.use(cookieParser());

        app.use(
            session({
                secret: 'project',
                secret: configSession.config.secret,
                resave: false,
                saveUninitialized: false,
                store: mongoSessionStore,
                sameSite: true,
                rolling: true,
                name: 'project',
                cookie: {
                    secure: true,
                    domain: configCommon.cookie_domain
                }
            })
        );

        // Initialize Passport
        app.use(passport.initialize());
        app.use(passport.session());
        app.use(bodyParser.json());
        app.use(
            bodyParser.urlencoded({
                extended: false
            })
        );
        // setting up security headers
        app.use(Helmet());

        app.get('/s/health-check', (req, res) => {
            res.send(`I am alive!!!!`);
        });

        app.use('/s/api', apiRoute);
        app.use('/s/auth', authRoute); // API integration

        const isDev = process.env.NODE_ENV !== 'prod';

        const apolloServer = new ApolloServer({
            schema,
            resolvers,
            context: ({ req }) => {
                console.log(req) //req.session don't have passport in it
                return {
                    req
                };
            }
        });

        apolloServer.applyMiddleware({
            app,
            path: '/graphql'
        });

        apolloServer.installSubscriptionHandlers(app);

        https
            .createServer(
                {
                    key: fs.readFileSync(`./keys/server.key`),
                    cert: fs.readFileSync(`./keys/server.crt`)
                },
                app
            )
            .listen(process.env.PORT, () => {
                console.log('Express server is running on port 9091');
            });

        // Handle uncaughtException
        process.on('uncaughtException', err => {
            console.log(err.message);
            process.exit(1);
        });
1

1 Answers

4
votes

Double check that the request is sending the session cookies. I had the same problem, and I was using Graphql Playground as the client, and it disables sending the cookies by default. You can fix it by going to the settings in the top right of the playground, and setting "request.credentials": "same-origin". After I did that I saw the passport session initialized properly.