I am trying to authenticate a user with custom callback in passport js. I have written my code based on the passport documentation.
router.post("/signin/email", function (req, res, next) {
passport.authenticate("email-local", function (err, user, info) {
if (err) {
return res.send("err");
}
if (!user) {
return res.send(info);
}
req.logIn(user, function (err) {
if (err) {
return res.send(err);
}
next(user);
});
})(req, res, next),
UsersController.getToken;
});
I want to pass the user to the next middleware i.e UsersController.getToken ,but it is not being passed. How can i solve this issue?
Passport will add the user data to req.user after login is called so you don't need to pass it with next.
I would recommend simplifying the req.logIn call to the following:
return req.logIn(user, next)
Then within you UsersController.getToken middleware you can access the user data through the req object.
Related
I do not want a redirect in my sign-up route, it is a two stage process (the way I currently have it figured out), so I would like to submit the first form, save to db with ajax and return something, and then show the second form to complete sign up. The post route works, but the function does not run
router.route('/register')
.post((req, res, next) => {
console.log('this bit here works');
passport.authenticate('local-signup', function(error, user) {
console.log('it's here that nothing happens');
if(error) {
return res.status(500).json(error);
}
return res.json(user); //this is what I want to return;
})
})
Does passport only work with the one post call?
passport.authenticate() is an Express middleware, not a regular function.
As per the fine manual (search for "Custom Callback"), it should be used like this:
router.route('/register').post((req, res, next) => {
console.log('this bit here works');
passport.authenticate('local', function(error, user, info) {
console.log("it's here that something should happen now.");
if (error) {
return res.status(500).json(error);
}
return res.json(user);
})(req, res, next);
})
FWIW, user may not necessarily be a proper object (if authentication failed, for instance).
I have a simple passport setup with a local strategy for my login route. I'm not sure how to properly use the authentication function as a middleware though. Here is my Middleware that I call on the /login route before the controller:
exports.requireLogin = (req, res, next) => {
passport.authenticate('local', { session: false }, (err, user, info) => {
if (err) {
next(err);
} else if (!user) {
res.status(401).json(info.message);
} else {
req.login(user, (loginError) => {
if (loginError) {
console.log('error here');
next(new Error('test'));
} else {
next();
}
});
}
})(req, res, next);
};
As you can see, the passport function is immediately invoked with the middleware parameters. That is what I found here on Stackoverflow as how to use next in that function.
Now that doesn't work for some reason. The error is not really handled as error. I checked this by making a none-error middleware as last possible endpoint in express and console-logged it out. I can see that it logs out the error here right before the line where the error is passed to next but it also logs out the check that the normal middleware is called after that.
As far as I know Express shouldn't call any normal middleware when you pass an error to next. Why doesn't this example work?
Passport
passport.use('jwt', new JwtStrategy(opts, function(jwt_payload, done) {
User.where({id: jwt_payload.id}).fetch().then(function(user) {
if(user) {
return done(null, user);
} else {
return done(null, false);
}
}).catch(function(err) {
return done(err, false);
});
}));
Example 2
This works but when the JWT is not set, I get res = null when I think I should be getting an 401 response.
app.get('/user', getProfile);
getProfile = function(req, res, next) {
passport.authenticate('jwt', {session: false}, function(err, user, info) {
if(user) {
res.json(user);
} else {
res.json(err);
}
})(res, req, next);
};
Example 2
When the JWT is not set then I get the correct 401 response but if it is set I can't get user returned because res doesn't exist.
app.get('/user', passport.authenticate('jwt', {session: false}, getProfile);
getProfile = function(err, user) {
if(user) {
res.json(user);
} else {
res.json(err);
}
};
So how do I pass res into this function?
Example 1
In your first example, it looks like you've just mixed up the order of req and res in your function call. It should be
})(req, res, next);
not
})(res, req, next);
Example 2
In your second example, I think you're using the callback to passport.authenticate incorrectly.
The passport.authenticate method is just middleware to be called before your actual route gets hit. Its callback does not replace the regular route callback function you would define to handle sending a response - you still need to provide a route callback after the middleware.
app.get('/user',
passport.authenticate('jwt', { session: false }),
function(req, res, next) {
res.json(req.user);
});
The authenticate method should handle responding with an appropriate status code if the user was not authenticated, so you can safely call req.user in your route callback and know the user is authenticated.
I am using passport for my node.js app.
When I want to authenticate users local, I can simply do it
function local(req, res) {
req._passport.instance.authenticate('local', function(err, user, info) {
if(err) {
return workflow.emit('exception', err);
}
// and so on
res.end('some data');
}
}
But when I want to use facebook strategy, I must use redirectUrls like this.
function signinFacebook(req, res, next) {
req._passport.instance.authenticate('facebook')(req, res, next);
}
function facebookCallback(req, res, next) {
req._passport.instance.authenticate('facebook', {
successRedirect: '/',
failureRedirect: '/'
})(req, res, next);
}
This way I cant send with response data, that I am sending on local strategy.
Can anyone help me to fix it. I want not give success and failure Redirects, I want to call some function if all goes well like on local strategy.
I've found this in Passport's documentation, it may help.
app.get('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err); }
if (!user) { return res.redirect('/login'); }
req.logIn(user, function(err) {
if (err) { return next(err); }
return res.redirect('/users/' + user.username);
});
})(req, res, next);
});
Note that when using a custom callback, it becomes the application's responsibility to establish a session (by calling req.login()) and send a response.
I would like some help understanding the following example from the passport.js authenticate documentation:
app.get('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err); }
if (!user) { return res.redirect('/login'); }
req.logIn(user, function(err) {
if (err) { return next(err); }
return res.redirect('/users/' + user.username);
});
})(req, res, next); //***UNSURE ABOUT THIS***
});
I understand what the code does - but I don't know what the (req, res, next)at the end of the callback function is for. Why is it necessary? Does it provide the values for (err, user, info)? If that's the case, why don't I see more function calls ending with arguments - Is it perhaps something to do with passing on the next object?
Would love for someone to help me improve my understanding of this concept.
Request handlers are Express middleware; they get a request, a response, and a way to pass on execution to the next layer of middleware. passport.authenticate returns middleware, but it hasn’t been attached with app.use(), so you have to pass the appropriate arguments manually.
The fact that the callback from passport.authenticate also has three arguments is just a coincidence. They won’t have the same values.