user3180402
user3180402

Reputation: 599

InternalOAuthError: Failed to obtain access token

Can anyone help me with what is wrong with the below code in the link GitHub oauth2-provider server with passport-oauth2 consumer

After I login with http://localhost:8082 and reach my callback URL: http://localhost:8081/auth/provider/callback, it throws an error

var express = require('express')
  , passport = require('passport')
  , util = require('util')
  , TwitterStrategy = require('passport-twitter').Strategy;

var TWITTER_CONSUMER_KEY = "--insert-twitter-consumer-key-here--";
var TWITTER_CONSUMER_SECRET = "--insert-twitter-consumer-secret-here--";

passport.serializeUser(function(user, done) {
  done(null, user);
});

passport.deserializeUser(function(obj, done) {
  done(null, obj);
});

passport.use(new TwitterStrategy({
    consumerKey: TWITTER_CONSUMER_KEY,
    consumerSecret: TWITTER_CONSUMER_SECRET,
    callbackURL: "http://127.0.0.1:3000/auth/twitter/callback"
  },
  function(token, tokenSecret, profile, done) {
    // asynchronous verification, for effect...
    process.nextTick(function () {

      return done(null, profile);
    });
  }
));


var app = express.createServer();

// configure Express
app.configure(function() {
  app.set('views', __dirname + '/views');
  app.set('view engine', 'ejs');
  app.use(express.logger());
  app.use(express.cookieParser());
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(express.session({ secret: 'keyboard cat' }));
  app.use(passport.initialize());
  app.use(passport.session());
  app.use(app.router);
  app.use(express.static(__dirname + '/public'));
});


app.get('/', function(req, res){
  res.render('index', { user: req.user });
});

app.get('/account', ensureAuthenticated, function(req, res){
  res.render('account', { user: req.user });
});

app.get('/login', function(req, res){
  res.render('login', { user: req.user });
});

app.get('/auth/twitter',
  passport.authenticate('twitter'),
  function(req, res){
    // The request will be redirected to Twitter for authentication, so this
    // function will not be called.
  });

app.get('/auth/twitter/callback', 
  passport.authenticate('twitter', { failureRedirect: '/login' }),
  function(req, res) {
    res.redirect('/');
  });

app.get('/logout', function(req, res){
  req.logout();
  res.redirect('/');
});

app.listen(3000);

function ensureAuthenticated(req, res, next) {
  if (req.isAuthenticated()) { return next(); }
  res.redirect('/login')
} 

InternalOAuthError: Failed to obtain access token

How can I resolve this issue?

Upvotes: 28

Views: 39551

Answers (9)

Obonyo
Obonyo

Reputation: 161

I was facing this issue, and I just changed my callback URL from callbackURL: 'auth/github/callback'

to callbackURL: '/auth/github/callback'

Added a forward slash at the beginning

Upvotes: 0

Mohodron
Mohodron

Reputation: 11

I was also getting the same error

InternalOAuthError: Failed to obtain access token

After surfing the internet I found that when my PC is not on a proxy server, the request passes through without any errors. Hope this works.

Upvotes: 1

Pedro Henrique Arthur
Pedro Henrique Arthur

Reputation: 93

I was facing the same issue using multiple strategies for passport (Spotify & Google). After a while investigating this issue, I found this Open PR on Github that fixes this issue.

It's a know issue on the passport-oauth2 and the solution (until the PR is approved) is to force passport-oauth2 to use [email protected] by adding an override into my project's package.json:

"overrides": {
    "oauth": "~0.10.0"
}

That will fix your error.

Upvotes: 0

Mythos
Mythos

Reputation: 1482

For anyone still struggling with this, there's an issue in the node-oauth package mentioned here.

Basically, on faster connections, node-oauth receives ECONNRESET and triggers the provided callback twice. A quick way to fix this is to add a single line to node_modules/oauth/lib/oauth2.js near line 161 inside the error listener:

   request.on('error', function(e) {
     if (callbackCalled) { return }  // Add this line
     callbackCalled= true;
     callback(e);
   });

There's already a PR from November, 2021 concerning this issue but it has not been merged. It seems like node-oauth is no longer being maintained. I lost past 2 working days scratching my head on this problem. Hoping you guys find this answer.

EDIT: The PR has been merged as of 23th July 2022, but the dependency versions haven't been updated in passport-oauth2 and passport-google-oauth2. Here are corresponding issues to follow: passport-oauth2 issue and passport-google-oauth2 issue

Upvotes: 3

Hitesh Subnani
Hitesh Subnani

Reputation: 593

I was facing the same issue with GitHub Authentication and I found out that adding a middleware can help with this, please find the example attached below :-

app.get(
  "/auth/github",
  (req, res, next) => {
    if (req.user) {
      console.log("user");
      res.redirect("/dashboard");
    } else next();
  },
  passport.authenticate("github", {
    scope: ["user:email"],
  })
);

Please note :- This might not be the best solution but worked for me fine. Thank you! Have a good code day :)

Upvotes: 0

Abdul.Moqueet
Abdul.Moqueet

Reputation: 1067

I have also faced the same issue, i was using cookie-session in my case the issue was i was mistakenly returning an undefined object in callback.

passport.use(new GoogleStrategy({
    clientID: process.env.GOOGLE_CLIENT_ID,
    clientSecret: process.env.GOOGLE_CLIENT_SECRET,
    callbackURL: "http://localhost:5000/auth/google/callback"
},
    async function (accessToken, refreshToken, profile, done) {

        const googleId = profile.id;
        const name = profile.displayName;
        const email = profile.emails[0].value;

        const existingUser = await User.findOne({googleId});

        if(existingUser){
            //as u can notice i should return existingUser instaded of user
            done(null, user); // <------- i was returning undefined user here.
        }else{
            const user = await User.create({ googleId, name, email });
            done(null, user);
        }
    }
)); 

Upvotes: 1

Lim Min Chien
Lim Min Chien

Reputation: 1070

I believe you need to obtain TWITTER_CONSUMER_KEY and TWITTER_CONSUMER_SECRET first. Here's how.

How to obtain Twitter Consumer Key

Then plug it into your code.

Upvotes: 1

bmaupin
bmaupin

Reputation: 15995

I ran into a similar issue trying to get passport-oauth2 working. The error message, as you've observed, is less than helpful:

InternalOAuthError: Failed to obtain access token
    at OAuth2Strategy._createOAuthError (node_modules/passport-oauth2/lib/strategy.js:382:17)
    at node_modules/passport-oauth2/lib/strategy.js:168:36
    at node_modules/oauth/lib/oauth2.js:191:18
    at ClientRequest.<anonymous> (node_modules/oauth/lib/oauth2.js:162:5)
    at emitOne (events.js:116:13)
    at ClientRequest.emit (events.js:211:7)
    at TLSSocket.socketErrorListener (_http_client.js:387:9)
    at emitOne (events.js:116:13)
    at TLSSocket.emit (events.js:211:7)
    at emitErrorNT (internal/streams/destroy.js:64:8)

I found a suggestion to make a small change to passport-oauth2:

--- a/lib/strategy.js
+++ b/lib/strategy.js
@@ -163,7 +163,10 @@ OAuth2Strategy.prototype.authenticate = function(req, options) {

    self._oauth2.getOAuthAccessToken(code, params,
        function(err, accessToken, refreshToken, params) {
-          if (err) { return self.error(self._createOAuthError('Failed to obtain access token', err)); }
+          if (err) {
+            console.warn("Failed to obtain access token: ", err);
+            return self.error(self._createOAuthError('Failed to obtain access token', err));
+          }

Once I did that, I got a much more helpful error message:

Failed to obtain access token:  { Error: self signed certificate
    at TLSSocket.<anonymous> (_tls_wrap.js:1103:38)
    at emitNone (events.js:106:13)
    at TLSSocket.emit (events.js:208:7)
    at TLSSocket._finishInit (_tls_wrap.js:637:8)
    at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:467:38) code: 'DEPTH_ZERO_SELF_SIGNED_CERT' }

In my case I believe the root cause was that the authorization server I was testing with was using a self-signed SSL cert, which I was able to work around by adding this line:

require('https').globalAgent.options.rejectUnauthorized = false;

Upvotes: 24

Victor R Hdez
Victor R Hdez

Reputation: 127

same here I got the same issue. Finally I found a solution is related with the corporate proxy and you can check it out the workaround here

Upvotes: 9

Related Questions