auth0 / passport-linkedin-oauth2

Passport Strategy for LinkedIn OAuth 2.0
MIT License
119 stars 106 forks source link

LinkedIn Application is rejected error: user_cancelled_login #47

Open iramirezc opened 7 years ago

iramirezc commented 7 years ago

Hello!

Not sure if this should be an issue for passport-linkedin-oauth2 or passport-oauth2, but here I go.

I'm getting this error when I click on the 'Cancel' button while trying to sign in with my LinkedIn credentials:

AuthorizationError: The user cancelled LinkedIn login

LinkedIn's documentation talk about this

I might be doing something wrong or it is an unhandled error | exception.

Here's the code that throws that error, pretty standard:

apiRouter.get('/oauth/linkedin/callback', passport.authenticate('linkedin', {
    failureRedirect: '/signin',
    successRedirect: '/profile',
  }));

I expected to be redirected to '/signin' but instead, I'm getting the error I just mentioned above.

Here's how I'm 'manually' handling the callback if there's an error:

apiRouter.get('/oauth/linkedin/callback', (req, res, next) => {
    passport.authenticate('linkedin', (err, user, info) => {
      if (err) {
        // failureRedirect
        return res.redirect('/signin');
      }

      if (!user) {
        // failureRedirect
        return res.redirect('/signin');
      }

      // Note: https://github.com/jaredhanson/passport/blob/master/lib/middleware/authenticate.js#L52
      req.login(user, (err) => {
        if (err) {
          return next(err);
        }
        // successRedirect
        res.redirect('/profile');
      });
    })(req, res, next);
  });

Any thoughts?

Thanks!

pastorsj commented 7 years ago

I had a quick question for you @iramirezc. I tried your code and I got directed to the /signin route (when hitting the cancel button). Once I get to the signin route, what do I do from there? I am blanking on what I need to do. Thanks!

iramirezc commented 7 years ago

Yes, @pastorsj, the code I posted it works, but if you don't have a custom middleware by just having:

apiRouter.get('/oauth/linkedin/callback', passport.authenticate('linkedin', {
    failureRedirect: '/signin',
    successRedirect: '/profile',
}));

There's when the exception AuthorizationError: The user cancelled LinkedIn login happens, once you cancel the Linked In authentication process by clicking on the 'cancel' button.

The reason I posted this issue is that you might want to handle this exception directly in the strategy's code, as it seems to be unhandled.

Does that make sense?

Regards.

ennyta commented 6 years ago

Having the same issue, used your workaround @iramirezc, thanks!

donwanhk commented 6 years ago

I got this issue too, and i fixed with this code which is similar to what @iramirezc proposed:

app.get('/auth/linkedin/callback', (req, res, next) => {
    passport.authenticate('linkedin', {
        successRedirect: LINKEDIN_LOGIN_SUCCESS_REDIRECT,
        failureRedirect: LINKEDIN_LOGIN_FAILURE_REDIRECT
    }),
    (error, req, res, next) => {
        // Handle the error when the user cancelled the authorization
        res.redirect(LINKEDIN_LOGIN_FAILURE_REDIRECT);
    }
});

I am wondering why the strategy didn't handle too, maybe give more freedom for us to handle? But since cancelling authorization is very common, i think it should be mentioned in the docs.

Raghuvar commented 6 years ago

@donwanhk I have followed your inputs and it sorted out the cancel handling of LinkedIn login. But what if you want to add some more custom redirect handler in the callback function?? Any thoughts?

demosglok commented 6 years ago

so this issue happens because of this code in passport-oauth2/lib/strategy.js (near line 60) `OAuth2Strategy.prototype.authenticate = function(req, options) { options = options || {}; var self = this;

if (req.query && req.query.error) { if (req.query.error == 'access_denied') { //<<---- here return this.fail({ message: req.query.error_description }); } else { return this.error(new AuthorizationError(req.query.error_description, req. } }

`

oauth strategy treats only "access_denied" as valid error for failing (and thus using "failure" redirect) and everything else is treated as Error. while linkedin gives "user_cancelled_login" error here (error=user_cancelled_login) so just adding if (req.query.error == 'access_denied' || req.query.error == 'user_cancelled_login') { should fix the thing

i can double check and make pull request if you want

andreyrd commented 6 years ago

Looks like there's already a PR #53 that will fix this!

l5 commented 9 months ago

It seems like the PR got closed, but not merged. For me, the issue still persists. :(