How to use jquery/ajax data for passportjs

前端 未结 3 429
梦谈多话
梦谈多话 2020-12-06 03:29

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

相关标签:
3条回答
  • 2020-12-06 04:03

    Nobody can tell without looking at your server side code, AND which passport strategy you are using. For example,a snippet of the local strategy looks like this:

    function Strategy(options, verify) {
      // snip 
      this._usernameField = options.usernameField || 'username';
      this._passwordField = options.passwordField || 'password';
      // snip
    }
    // snip
    
    Strategy.prototype.authenticate = function(req, options) {
      options = options || {};
      var username = lookup(req.body, this._usernameField) || lookup(req.query, this._usernameField);
      var password = lookup(req.body, this._passwordField) || lookup(req.query, this._passwordField);
      // snip
    

    }

    The fields you pass from jQuery need to match up to how you have it configured on the server side, and what that strategy is looking for. In this case if you are using a local strategy without configuring the username and password, it looks for the username and passport fields to be passed in either the req.body or req.query.

    So no - email will not work. However you can instantiate the Strategy by passing in the options object a field which overrides the default username e.g.,

    {
       username: 'email'
    }
    

    I have used this previously to authenticate passport via jQuery:

      var login = function (un, pwd) {
    
            $.ajax({
                type: "POST",
                dataType: 'json',
                data: { "email": un.val(), "password": pwd.val() },
                url: "/rest/login/?format=json",
                success: function (data) {
                    window.location.href = '/somewhereElse'
                }
            });
        }
    

    I suspect your dataType needs to be 'json' not 'html'

    0 讨论(0)
  • 2020-12-06 04:04

    Perhaps this is a better place than buried in the comments. I experienced something similar months ago, and answered my own question here:

    Passport authenticate callback is not passed req and res

    essentially I was able to get it to work having the post handled with the signature: req, res, next and inside of that handler you call the passport.authenticate with the desired strategy. The passport.authenticate shouldn't be (or at least in my case wouldn't function as) the handler for the route

    server.post(route, function(req, res, next){
    
        passport.authenticate('local', function(err, user) {
    
        })
    
    })
    

    I was never able to get the passReqToCallback option to work.

    0 讨论(0)
  • 2020-12-06 04:16

    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);    
    });
    
    0 讨论(0)
提交回复
热议问题