Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Express redirect after login authentication

I'm working on an app which has node.js and express on the server, mongodb for the db and Backbone.js on the front-end. I'm working on enabling user logins, so I've used the passport.js library. I have a problem with my login 'post' method: It is not redirecting to another page (well it's an SPA, so I mean rendering a Backbone view). Here's the code:

//standard express setup...

app.post('/api/auth', function(req, res, next) {
  passport.authenticate('local', function(err, user, info) {
    if (err) { return next(err) }
    if (!user) {
      req.session.messages =  [info.message];
      return res.redirect('/')
    }
    req.logIn(user, function(err) {
      if (err) { 
    return next(err); 
  } else {
            console.log('yup, working'); //Can see the response in the console
    return res.redirect('/api'); 
  }
});
  })(req, res, next);
});

app.get('/api', function (request, response) {
  response.send( 'Login successful!' );
});

So I can see the console.log message fine, and a GET request for the route IS triggered...but nothing actually happens. So I'm thinking that I've misunderstood how 'res.redirect' works - I want to navigate to that route upon the login success. I've thought about using window.location, but is this a good long-term solution? I'm not using any html templates on the server, so I can't (I don't think) do something as simple as 'res.render('index')'

What would be the best way to approach this? Thanks in advance.

like image 943
cs_stackX Avatar asked Mar 01 '14 10:03

cs_stackX


1 Answers

I had a face-palm moment a few days after asking this question where I realized I had failed to grasp a core concept correctly. Let me answer my own question:

Rather than trying to serve the page from the server, I just need to send a response to the client and have Backbone do the rendering, depending on the response received. So my server does something more like this:

controller.post('/user', function(req, res, next) {
  passport.authenticate('local', function(err, user, info) {
    if (err) { return next(err) }
      user.save(function(err) {
    if(err){
        console.log(err);
        return res.json(401);
    } else {
        return res.json(200); //SEND RESPONSE - do not try to redirect
    }
  });

Then I do the page loading in the Backbone View, like this:

login: function (e) {
  e.preventDefault();
  console.log('submitting login request');
  var formValues = {
    username: $('#inputEmail').val(),
    password: $('#inputPassword').val()
  };

  var user = new User(); //user model
  user.set(formValues);

  function saveUserfunction (){
    if(user) {
        user.save(this.formValues, {
            success: function(model, response, options) {
                if (response == 200) { 
                    console.log('success :' + response);
                    window.location.href = 'http://localhost:4711/#/api/menu_auth'; //Here's my redirect - the router is listening for this route and will render accordingly
                } else {
                    console.log('error: '+response);
                }

            }, error: //Error handling etc.

As Pheonix pointed out in the comments, the best way to do this would be to listen to the the user model.

like image 89
cs_stackX Avatar answered Sep 26 '22 19:09

cs_stackX