NodeJs Passport isAuthenticated() returning false even after login

12,690

Solution 1

You need to allow cookies to be set in cross domain

In express

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

And in ajax setup

 xhrFields: {
     withCredentials: true
 }

You can find relevant answers here and here

Solution 2

I think rdegges has part of the idea since cookies and session variables are part of what makes the state management work. I think that bodyParser is also required but I omitted it here.

I'm using Passport on my website (authenticating to a MongoDB users table) and here are excerpts from my code.

/server.js:

var cookieParser = require('cookie-parser');
...
var passport = require('passport');
var expressSession = require('express-session');
var initPassport = require('./passport/init');
initPassport(passport);
...
self.app.use(cookieParser());
self.app.use(expressSession({secret: 'MYSECRETISVERYSECRET', saveUninitialized: true, resave: true}));
self.app.use(passport.initialize());
self.app.use(passport.session());
...
var routes = require('./routes/index')(passport);
self.app.use('/', routes);

/passport/init.js:

var login = require('./login');
var signup = require('./register');
var User = require('../models/user');

module.exports = function(passport) {
  // Passport needs to be able to serialize and deserialize users to support persistent login sessions
  passport.serializeUser(function(user, done) {
    console.log('serializing user: ');
    console.log(user);
    done(null, user._id);
  });

  passport.deserializeUser(function(id, done) {
    User.findById(id, function(err, user) {
      console.log('deserializing user:', user);
      done(err, user);
    });
  });

  // Setting up Passport Strategies for Login and SignUp/Registration
  login(passport);
  signup(passport);
}

/routes/index.js:

var passport = require('passport');
var User = require('../models/user');
...
var isAuthenticated = function (req, res, next) {
  // if user is authenticated in the session, call the next() to call the next request handler 
  // Passport adds this method to request object. A middleware is allowed to add properties to
  // request and response objects
  if (req.isAuthenticated())
    return next();
  // if the user is not authenticated then redirect him to the login page
  res.redirect('/login');
}

For what it's worth I'm not seeing your isValidated() function anywhere defined.

Solution 3

Can be so many things.

1.) Order as in PassportJS Facebook login isAuthenticated returns false even though authentication succeeds (order seems correct though in your case).

2.) No req.login() as in Passport and Passport Local req.isAuthenticated always returns false

In this case I opt for the latter but for a different reason than in that question. You have provided your own LocalStrategy. To make the user log in, you will have to call req.login() yourself. Just as if you would define your own custom callback, as described in the passport documentation: http://passportjs.org/guide/authenticate/.

Share:
12,690

Related videos on Youtube

Kumar teja
Author by

Kumar teja

Updated on July 12, 2022

Comments

  • Kumar teja
    Kumar teja almost 2 years

    I'm new to Angular.js and trying to build local authentication for a website. I have gone through various sources and Authentication in Single Page Applications was very helpful. When I tried build the same in my localhost my code went in to a loop.

    app.post('/login',.....) is returning user in the response but after that while loading the admin page it is checking whether the user is logged in by calling app.get('/loggedin',... ) and req.isAuthenticated() is returning false even after login and it goes to a loop. I can't understand why this is happening please help me.

    Server Side code

    var express = require('express');
    var http = require('http');
    var path = require('path');
    var passport = require('passport');
    var LocalStrategy = require('passport-local').Strategy;
    
    //==================================================================
    // Define the strategy to be used by PassportJS
    passport.use(new LocalStrategy(
      function(username, password, done) {
        if (username === "admin" && password === "admin") // stupid example
          return done(null, {name: "admin"});
    
        return done(null, false, { message: 'Incorrect username.' });
      }
    ));
    
    // Serialized and deserialized methods when got from session
    passport.serializeUser(function(user, done) {
        done(null, user);
    });
    
    passport.deserializeUser(function(user, done) {
        done(null, user);
    });
    
    // Define a middleware function to be used for every secured routes
    var auth = function(req, res, next){
      if (!req.isAuthenticated()) 
        res.send(401);
      else
        next();
    };
    //==================================================================
    
    // Start express application
    var app = express();
    
    // all environments
    app.set('port', process.env.PORT || 3000);
    app.use(express.favicon());
    app.use(express.cookieParser()); 
    app.use(express.bodyParser());
    app.use(express.methodOverride());
    app.use(express.session({ secret: 'securedsession' }));
    app.use(passport.initialize()); // Add passport initialization
    app.use(passport.session());    // Add passport initialization
    app.use(app.router);
    
    app.all('*', function(req, res, next) {
      res.header("Access-Control-Allow-Origin", "*");
      res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
      next();
    });
    
    // development only
    if ('development' == app.get('env')) {
      app.use(express.errorHandler());
    }
    
    //==================================================================
    // routes
    app.get('/', function(req, res){
      res.render('index', { title: 'Express' });
    });
    
    app.get('/users', auth, function(req, res){
      res.send([{name: "user1"}, {name: "user2"}]);
    });
    //==================================================================
    
    //==================================================================
    // route to test if the user is logged in or not
    app.get('/loggedin', function(req, res) {
      res.send(req.isAuthenticated() ? req.user : '0');
    });
    
    // route to log in
    app.post('/login', passport.authenticate('local'), function(req, res) {
      res.send(req.user);
    });
    
    // route to log out
    app.post('/logout', function(req, res){
      req.logOut();
      res.send(200);
    });
    //==================================================================
    
    http.createServer(app).listen(app.get('port'), function(){
      console.log('Express server listening on port ' + app.get('port'));
    });
    

    Client Side Js file

    'use strict';
    
    /**********************************************************************
     * Angular Application
     **********************************************************************/
    var app = angular.module('app', ['ngResource','ngRoute'])
      .config(function($routeProvider, $locationProvider, $httpProvider) {
        //================================================
        // Check if the user is connected
        //================================================
        var checkLoggedin = function($q, $timeout, $http, $location, $rootScope){
          // Initialize a new promise
          var deferred = $q.defer();
    
          // Make an AJAX call to check if the user is logged in
          $http.get('http://localhost:3000/loggedin').success(function(user){
            // Authenticated
            if (user !== '0')
              $timeout(deferred.resolve, 0);
    
            // Not Authenticated
            else {
              $rootScope.message = 'You need to log in.';
              $timeout(function(){deferred.reject();}, 0);
              $location.url('/login');
            }
          });
    
          return deferred.promise;
        };
        //================================================
    
        //================================================
        // Add an interceptor for AJAX errors
        //================================================
        $httpProvider.responseInterceptors.push(function($q, $location) {
          return function(promise) {
            return promise.then(
              // Success: just return the response
              function(response){
                return response;
              }, 
              // Error: check the error status to get only the 401
              function(response) {
                if (response.status === 401)
                  $location.url('/login');
                return $q.reject(response);
              }
            );
          }
        });
        //================================================
    
        //================================================
        // Define all the routes
        //================================================
        $routeProvider
          .when('/', {
            templateUrl: 'views/main.html'
          })
          .when('/admin', {
            templateUrl: 'views/admin.html',
            controller: 'AdminCtrl',
            resolve: {
              loggedin: checkLoggedin
            }
          })
          .when('/login', {
            templateUrl: 'views/login.html',
            controller: 'LoginCtrl'
          })
          .otherwise({
            redirectTo: '/login'
          });
        //================================================
    
      }) // end of config()
      .run(function($rootScope, $http){
        $rootScope.message = '';
    
        // Logout function is available in any pages
        $rootScope.logout = function(){
          $rootScope.message = 'Logged out.';
          $http.post('http://localhost:3000/logout');
        };
      });
    
    
    /**********************************************************************
     * Login controller
     **********************************************************************/
    app.controller('LoginCtrl', function($scope, $rootScope, $http, $location) {
      // This object will be filled by the form
      $scope.user = {};
    
      // Register the login() function
      $scope.login = function(){
        $http.post('http://localhost:3000/login', {
          username: $scope.user.username,
          password: $scope.user.password,
        })
        .success(function(user){
          // No error: authentication OK
          $rootScope.message = 'Authentication successful!';
          $location.url('/admin');
        })
        .error(function(){
          // Error: authentication failed
          $rootScope.message = 'Authentication failed.';
          $location.url('/login');
        });
      };
    });
    
    
    
    /**********************************************************************
     * Admin controller
     **********************************************************************/
    app.controller('AdminCtrl', function($scope, $http) {
      // List of users got from the server
      $scope.users = [];
    
      // Fill the array to display it in the page
      $http.get('http://localhost:3000/users').success(function(users){
        for (var i in users)
          $scope.users.push(users[i]);
      });
    });
    
  • Ben Orozco
    Ben Orozco about 9 years
    Why wouldn't the browser keep the cookie? It's suppose to be its default behavior!
  • rdegges
    rdegges about 9 years
    This can happen for many reasons: eg, when the cookie is set it's set with an expirey time.