Passport js fails to maintain session in cross-domain

12,689

Solution 1

I was having the same problem. Before configuring anything in express app, use the following(exactly the same) to set header of response for cross-domain :

app.use(function(req, res, next) {
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Origin', req.headers.origin);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
if ('OPTIONS' == req.method) {
     res.send(200);
 } else {
     next();
 }
});

It works for me. Best of luck!

Solution 2

As per Sriharsha's answer:

  • Set res.header("Access-Control-Allow-Credentials", "true");

  • Make sure you pass the credentials in the client side call. For example for AJAX, add this to your call: xhrFields: {withCredentials: true},

Additionally:

  • Don't use the wildcard for Access-Control-Allow-Origin with a credentialed request

    As explained on MDN:

    when responding to a credentialed request, server must specify a domain, and cannot use wild carding


I use this file, and call it from my main module with require("./enable-cors.js")(app);

// enable-cors.js
module.exports = function(app) {

    var methodOverride = require('method-override')
    app.use(methodOverride());
    var allowCrossDomain = function(req, res, next) {
        res.header('Access-Control-Allow-Credentials', true);
        res.header('Access-Control-Allow-Origin', req.headers.origin);
        res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
        res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');

        // intercept OPTIONS method
        if ('OPTIONS' == req.method) {
            res.send(200);
        }
        else {
            next();
        }
    };
    app.use(allowCrossDomain);
    // Built upon: http://cuppster.com/2012/04/10/cors-middleware-for-node-js-and-express/#sthash.WdJmNaRA.dpuf

};

Solution 3

Allow the credentials to be shared by setting Access-Control-Allow-Credentials header. (I am not sure why you have commented in your code)

res.header("Access-Control-Allow-Credentials", "true");

then pass the credentials from javascript through XHR object.

xhr.withCredentials = true;
Share:
12,689

Related videos on Youtube

Kundu
Author by

Kundu

Updated on September 14, 2022

Comments

  • Kundu
    Kundu over 1 year

    I am using passport JS, express and mongoose to make an API. When I test it in same domain it maintain session and works fine. But in cross domain it fails. Any clue how can i maintain the session in cross domain using the same configuration. Following is the code

     allowCrossDomain = function(req, res, next) {
        res.header("Access-Control-Allow-Origin", "*");
        res.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
        res.header("Access-Control-Allow-Headers", req.headers["access-control-request-headers"]);
        // res.header("Access-Control-Allow-Credentials", "true");
        if ("OPTIONS" == req.method) {
            res.send(200);
        } else {
            next();
        }
    
      //allow all crossDomain request
    app.use(allowCrossDomain);
    
    //session handling
    app.use(express.cookieParser("gallery"));
    app.use(express.session());
    app.use(passport.initialize());
    app.use(passport.session());
    
    app.use(function(req, res, next) {
        // check if client sent cookie
        var cookie = req.cookies.cokkieName;
        if (cookie === undefined) {
            //set up cookie here by a random number
            });
        }
        next(); // <-- important!
    });
    passport.use(new LocalStrategy({
        usernameField: "email"
    },
    function(email, password, done) {
        User.authenticate(email, password, function(err, reply) {
           //authenticate user and call the callback
                return done(err, false);
    
        });
    }));
    
    
    passport.serializeUser(function(user, done) {
    return done(null, user._id);
    });
    
    
    passport.deserializeUser(function(id, done) {
    //find user via id and return the user details
    return done(null, user._id);
    });
    
       app.post("/login", function(req, res, next) {
        passport.authenticate("local",
            function(err, data, info) {
                //custom callback
                user.getProfile(req, res, next, err, data, info);
            })(req, res, next);
    });