Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

If I send a login request using the form fields action="/login", method="post", it works just fine. Similar to the code available here or here.

But if instead, if I send the same information using jquery/ajax, then passport just doesn't seem to work. There is no actual login happening via passport, but the ajax call gives a misleading success message.

The below isn't working. Though I get "login success" message, login hasn't really happened.

$('#login_button').click(function () {

    var email = $('#email').val();
    var password = $('#password').val();
    alert ('email/pass:' + email + ", " + password);

    $.ajax({
        type: "POST",
        url: "/login",
        data: { email: email , password: password },
        dataType: 'html'
    })
            .done(function () {
                console.log("http request succeeded");
                alert("login success");
            });
});

I need to use the ajax method, so that I can do something useful on the client side, after successful login. E.g. start socket.io.

Please help. My modified code is available here: my-modified-code

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
190 views
Welcome To Ask or Share your Answers For Others

1 Answer

I tried your code and Passport-wise it works. I did "Local Signup", "Logout", then "Local Login" and was successfully authenticated but nothing indicated that in the UI.

This is related to that 302 you were talking about - the server replied 302 because you have defined successRedirect : '/profile', and then jQuery followed the redirect and received HTML which it cannot parse because it expects JSON. And since you don't have .fail() callback defined in your $.ajax call you don't see it.

The session is fine though which can be seen by going manually to /profile.

When you login using a regular HTML form the browser will send a single HTTP request and act according to the response (e.g render a HTML page, or perform a redirect if it was 302). The same happens but in different context when you call $.ajax - the AJAX call follows the redirect because it made the request, but the browser does not.

You should use separate routes for AJAX and HTML logins, or use a custom callback and determine what to return based on req.accepts().

The separate routes could be eg.

// AJAX logins to this URL, redirect on client side using
// window.location.href if login succeeds
app.post('/login/ajax', passport.authenticate('local-login'));

// HTTP login form send to this URL
app.post('/login', passport.authenticate('local-login', {
  successRedirect : '/profile',
  failureRedirect : '/login',
  failureFlash : true
}));

Custom callback could be something like this (not tested):

app.post('/login', function(req, res, next) {
  passport.authenticate('local-login', function(err, user, info) {
    switch (req.accepts('html', 'json')) {
      case 'html':
        if (err) { return next(err); }
        if (!user) { return res.redirect('/login'); }
        req.logIn(user, function(err) {
          if (err) { return next(err); }
          return res.redirect('/profile');
        });
        break;
      case 'json':
        if (err)  { return next(err); }
        if (!user) { return res.status(401).send({"ok": false}); }
        req.logIn(user, function(err) {
          if (err) { return res.status(401).send({"ok": false}); }
          return res.send({"ok": true});
        });
        break;
      default:
        res.status(406).send();
    }
  })(req, res, next);    
});

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...