Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passport js fails to maintain session in cross-domain

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);
});
like image 1000
Kundu Avatar asked Sep 27 '13 05:09

Kundu


People also ask

Does passport js use session?

Passport will establish a persistent login session after successful authentication. This session is maintained via a cookie in the user's browser.

Should I use passport js for authentication?

Passport is a popular, modular authentication middleware for Node. js applications. With it, authentication can be easily integrated into any Node- and Express-based app. The Passport library provides more than 500 authentication mechanisms, including OAuth, JWT, and simple username and password based authentication.

How does Passport js handle authorization?

Authorization is performed by calling passport. authorize() . If authorization is granted, the result provided by the strategy's verify callback will be assigned to req.account . The existing login session and req.

What is the difference between Passport local and passport JWT?

passport-local is the strategy you would use if you are authenticating against a username and password stored 'locally' i.e. in the database of your app - 'local' means local to your application server, not local to the end user. passport-jwt is the strategy for using JSON Web Tokens.


2 Answers

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

};
like image 50
Crocodile Avatar answered Oct 25 '22 03:10

Crocodile


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;
like image 21
Sriharsha Avatar answered Oct 25 '22 01:10

Sriharsha