passport-facebook: Returning 500 error instead of redirecting to failureRedirect
I’m using the following code for my callback route.
app.get('/auth/facebook/callback', passport.authenticate('facebook', {
successRedirect : '/profile',
failureRedirect : '/',
failureFlash : true
}));
It works, authentication works as expected, but one thing I just can’t seem to understand is why if I visit /auth/facebook/callback?code=gfdgsdgfg it throws a 500 error and displays a stacktrace to the user?
Is there no way to use the failureRedirect?
Is there a work around or anything that can be done so that if the authentication fails (for any reason, mainly because a user has tampered with the url) it redirects the user to the failureRedirect location and gives them a generic error response.
About this issue
- Original URL
- State: open
- Created 10 years ago
- Reactions: 3
- Comments: 18
The resolution is to pass a custom callback to passport.authenticate( ) and handle the error using the callback flow. The design of everything in Passport is based on the middleware approach so understand that means understanding a custom callback must be provided for anything other than the default handling.
Here is an example:
This is the route that calls the above strategy and upon completion has the “done” handler defined which can provide custom logging, ensure the redirect occurs, whatever.
No matter what error you get from the facebook strategy (including invalid profile fields, invalid code, etc) will all result in logging it and redirecting to /login in the above coded scenario
You can handle it in an express error handler:
Strangely having pretty much the same experience as @jwerre except using the Google module.
If I go to
http://canvass.prototype.website/auth/google/callback?code=flubberI’m having a similar issue that may be related though my setup is slightly different. The issue is that errors are not passed back to the
authenticatecallback so I’m not able to handle them.Then, if I go to
/authorize/facebook/callback?code=flubbermy redirects are never reached and the following error is thrown:I tried the workaround suggested by @matthewerwin and I note a couple of things:
if you are using a session, then in the success state in the
/login/facebook/returnroute you have to callreq.logIn(user, err => {...dosomething... }). From what I can tell from sparse documentation when you take over the authenticate function you have to do all the steps yourself. thenext()in the above code doesn’t appear to do anything. Also the options forsuccessRedirectandfailureRedirectappear to be inoperative as well.I note that there should be a check for the
useras well, if theuseris not there an appropriate step should be taken (e.g.res.redirect(/some_error_url).I am unable to get the error message
unauthorizedpassed into the callback handler usingpassport-mocked. Unfortunate, as I’d like to pass the message back to the client. (I’m attempting implement account suspension for facebook users… I’d like to tell themsuspendedin the response text).passport-mockedhas a bugThe issue I had was that I was throwing an err if the user didn’t exist –
done(new Error("Invalid username"), null);and that doesn’t seem to be what Passport expects.It supports the notion of a falsy user in
doneas another sign of failure. So the appropriate signature would bedone(null, null)if you don’t find a user.That got things working for me.
You should not see the stack trace when you put the application in production mode (assuming you are using express), but it will still throw you a 500 error.
But 500 is wrong status code. It is not an internal server error but the user providing an invalid code. So probably a 400 or 404 status code would be correct.
I think this should be fixed in Passport, but you can easily catch this error your self and respond with the correct response.