MadPhysicist MadPhysicist - 5 months ago 48
Node.js Question

Reconciling Express (Passport) and AngularJS Routes

I am building a MEAN-stack application and am finally getting to the point of creating a user authentication. To do so, I followed this tutorial: http://code.tutsplus.com/tutorials/authenticating-nodejs-applications-with-passport--cms-21619

Now, when I incorporate this into my project it works, but only partially. Namely, it seems that the only page I can navigate to properly is the app's home page. If I click on any links or type something other than home in the address bar, it takes me back to the login screen.

What are some possible reasons for that?

My routes/index.js file looks as follows:

var express = require('express');
var router = express.Router();

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('/');
}

module.exports = function(passport){

/* GET login page. */
router.get('/', function(req, res) {
// Display the Login page with any flash message, if any
res.render('index', { message: req.flash('message') });
});

/* Handle Login POST */
router.post('/login', passport.authenticate('login', {
successRedirect: '/home',
failureRedirect: '/',
failureFlash : true
}));

/* GET Registration Page */
router.get('/signup', function(req, res){
res.render('register',{message: req.flash('message')});
});

/* Handle Registration POST */
router.post('/signup', passport.authenticate('signup', {
successRedirect: '/home',
failureRedirect: '/signup',
failureFlash : true
}));

/* GET Home Page */
router.get('/home', isAuthenticated, function(req, res){
res.render('home', { user: req.user });
});

/* Handle Logout */
router.get('/signout', function(req, res) {
req.logout();
res.redirect('/');
});

return router;
}


I also have some AngularJS routes specified in another file (application worked perfectly with these before I started adding authentication).

app.config(['$routeProvider', function($routeProvider){
$routeProvider

.when('/', {
templateUrl: 'partials/home.html',
controller: 'HomeCtrl'
})

.when('/calendar',{
templateUrl: 'partials/calendar.html',
//controller: 'Calendar'
})

.when('/add-activity', {

templateUrl: 'partials/activity-form.html',
controller: 'AddActivityCtrl'
})

.when('/activity/:id',{
templateUrl: 'partials/activity-form.html',
controller: 'EditActivityCtrl'
})

.when('/activity/delete/:id', {
templateUrl: 'partials/activity-delete.html',
controller: 'DeleteActivityCtrl'
})

.otherwise({
redirectTo: '/'
});
}]);


Is there something I am missing?

P.S. I noticed that currently my URL of home page is


http://localhost:3000/home#/


whereas previously it was


http://localhost:3000/#/


I added "home" to differentiate from "/" which is the authentication page; however, I am unsure about how "#" is tacked onto the path in the first quote.

Answer

I was able to resolve this as follows. I changed the Express routing to contain a

"login"

route and changed the home route to just

"/"

As a result, the home path became

http://localhost:3000/#/

The hash sign is tacked on by and for the Angular. From my understanding, the Angular treats such path as "/". Then, the remaining routing is done by Angular and I have a single-page AngularJS app.

Working code: Express

var express = require('express');
var router = express.Router();

module.exports = function(passport){

    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()){
                //console.log(next());
                return next();
            }
            // if the user is not authenticated then redirect him to the login page
            res.redirect('/login');
    }


    /* GET login page. */
    router.get('/login', function(req, res) {
        // Display the Login page with any flash message, if any
        res.render('login', { message: req.flash('message') });
    });

    /* Handle Login POST */
    router.post('/login', passport.authenticate('login', {
        successRedirect: '/',
        failureRedirect: '/login',
        failureFlash : true  
    }));

    /* GET Registration Page */
    router.get('/signup', function(req, res){
        res.render('register',{message: req.flash('message')});
    });

    /* Handle Registration POST */
    router.post('/signup', passport.authenticate('signup', {
        successRedirect: '/',
        failureRedirect: '/signup',
        failureFlash : true  
    }));

    /* GET Home Page when logged in */
    router.get('/', isAuthenticated, function(req, res){
        res.render('index', { user: req.user });
    });

    /* GET Home Page */
    router.get('/', isAuthenticated, function(req, res){
        res.render('index', { user: req.user });
    });

    /* Handle Logout */
    router.get('/signout', function(req, res) {
        req.logout();
        res.redirect('/login');
    });

    return router;
}

Working code: Angular

app.config(['$routeProvider', function($routeProvider){
    $routeProvider

        .when('/', {
            templateUrl: 'partials/home.html',
            controller: 'HomeCtrl'
        })

        .when('/calendar',{
            templateUrl: 'partials/calendar.html',
            //controller: 'Calendar'
        })

        .when('/add-activity', {

            templateUrl: 'partials/activity-form.html',
            controller: 'AddActivityCtrl'
        })

        .when('/activity/:id',{
            templateUrl: 'partials/activity-form.html',
            controller: 'EditActivityCtrl'
        })

        .when('/activity/delete/:id', {
            templateUrl: 'partials/activity-delete.html',
            controller: 'DeleteActivityCtrl'
        })

        .otherwise({
            redirectTo: '/'
        });
}]);