Update or add fields in passport.js local-strategy

2019-08-12 16:29发布

Im all over the docs, but I cant seem to find a way to update credentials.

This is what I was able to pick up by analyzing the code.

passport.deserializeUser(function(id, done) {
    AppUser.findById(id, function(err, user) {
        done(err, user);
    });
});

DeserializeUser seems useful, but I am not sure how to use it to update a or add fields?

I was trying to hack away and copy the logic from the login and make sense of it.

passport.use('local-update', new LocalStrategy({
    usernameField : 'username',
    passReqToCallback : true
},
function(req, username, done) {

    console.log(req)
    // asynchronous
    // AppUser.findOne wont fire unless data is sent back
    // process.nextTick(function() {

    //     // find a user whose email is the same as the forms email
    //     // we are checking to see if the user trying to login already exists
    //     AppUser.findOne({ 'local.email' :  email }, function(err, user) {
    //         // if there are any errors, return the error
    //         if (err)
    //             return done(err);

    //         // check to see if theres already a user with that email
    //         if (!user) {
    //             //return done(null, false, req.flash('signupMessage', 'That email is already taken.'));
    //             return done(null, false);
    //         } else {

    //             // if there is a user with that email
    //             // create the username
    //             var updateUser = new AppUser();

    //             // set the user's local credentials
    //             newUser.local.email    = email;
    //             newUser.local.password = newUser.generateHash(password);

    //             // save the user
    //             newUser.update(function(err) {
    //                 if (err)
    //                     throw err;
    //                 return done(null, newUser);
    //             });
    //         }

    //     });    

    // });

}));

Then on the form submit I did this.

app.post('/profile', passport.authenticate('local-update', {
    successRedirect : '/', // redirect to the secure profile section
    failureRedirect : '/signup' // redirect back to the signup page if there is an error
    //failureFlash : true // allow flash messages
}));

This results in a failure redirect.

It doesn't work because there is no response, but I need to find the model in mongoDB. I'm trying to see the req in the console first, so that maybe I can see how to find the model, but there is nothing showing up.

Obviously HACKISH code above, but this is the best I could do. I need a concrete answer, I am sure its simple and I am missing it in the docs!

Edit: The idea here is when a user signs up/logs in they provide an email. Once the user is logged in and an account is created they can create a username.

Edit: So I cannot figure out how to make update requests with passport, but in my router I have something like this.

app.post('/', function(req, res) {
    if (req.user) {
        AppUser.findOne({ _id: req.user.id }, function (err, user) {
            user.local.username  = req.body.username;
            user.save(function(err) {
                if (err){
                    console.log('Error')
                } else {
                    console.log('Sucess')
                }
            });
        });
    }
});

The only problem is the browsers default action, it submits the form and keeps the page on an endless reload. But it does update my mongodb model. I had to addon to the Schema, and had to add that property in my passport signup logic.

But I could just add this logic into my client side code, and throw the POST method into backbone and that should work!

1条回答
ら.Afraid
2楼-- · 2019-08-12 17:11

In cases like this, you can add a callback array as an argument for the Express route.

I guess you can change your verify handler to something like:

function(req, username, done) {
    //perform here only the validations you need to let the login pass
    if (validationSuccess) {
        done();
    } else {
    done('an error occured');
    }
}

So, supposing this function will successfully validate the user credentials, you can write another one:

function doSomethingAfter(req, res, next) {
    //do anything else you need here
    //e.g.
    SomeModel.create(req.body.username);
    //the response is available here
    res.send('Everything ok');
}

Finally, you can edit your routing function

app.post('/profile', [passport.authenticate('local-update', {
    failureRedirect : '/signup' // redirect back to the signup page if there is an error
}), doSomethingAfter]);

That way, you can perform authentication and make anything you want after the request is properly authenticated. If you need to add more functions, you have to add them to the array and call next() on each one.

Hope it helps.

查看更多
登录 后发表回答