InternalOAuthError:获取访问令牌失败

Posted

技术标签:

【中文标题】InternalOAuthError:获取访问令牌失败【英文标题】:InternalOAuthError: Failed to obtain access token 【发布时间】:2014-02-03 11:35:52 【问题描述】:

谁能帮我解决链接GitHub中的以下代码有什么问题? oauth2-provider 服务器和 passport-oauth2 消费者

在我使用http://localhost:8082 登录并到达我的回调 URL 后: http://localhost:8081/auth/provider/callback,会报错

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')
 

我该如何解决这个问题?

【问题讨论】:

你有没有想过这个问题? 这没有意义。没有得到“access_token”怎么登录成功?我认为这个问题有所不同,这里缺少一些信息。 可能是序列化和反序列化函数? 我对 Google OAuth2 策略有同样的问题。你搞清楚了吗? 我有同样的问题(facebook)。我怀疑原因可能是公司代理。 【参考方案1】:

我在尝试让 passport-oauth2 工作时遇到了类似的问题。正如您所观察到的,该错误消息没有多大帮助:

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)

我找到a suggestion 对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));
+          

一旦我这样做了,我会收到一条更有帮助的错误消息:

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' 

就我而言,我认为根本原因是我正在测试的授权服务器使用的是自签名 SSL 证书,我可以通过添加以下行来解决这个问题:

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

【讨论】:

您的建议( require('https').globalAgent.options.rejectUnauthorized = false; )解决了我的问题!谢谢! 添加调试信息很有用。就我而言,原因是 SSO 服务器主机不可访问。【参考方案2】:

在这里我也遇到了同样的问题。终于我找到了解决方案与企业代理有关,您可以查看解决方法here

【讨论】:

我们与其他网站有些不同;这不是一个论坛,而是一个问答网站,我们在其中保留答案空间以供答案。请查看我们的简短tour。您能否请edit 这个更直接地解决这个问题?【参考方案3】:

我相信你需要先获取 TWITTER_CONSUMER_KEY 和 TWITTER_CONSUMER_SECRET。这是如何做。

How to obtain Twitter Consumer Key

然后将其插入您的代码中。

【讨论】:

【参考方案4】:

我也遇到了同样的问题,在我的情况下我使用的是 cookie-session,问题是我错误地在回调中返回了一个未定义的对象。

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);
        
    
)); 

【讨论】:

【参考方案5】:

我在 GitHub 身份验证方面遇到了同样的问题,我发现添加中间件可以帮助解决这个问题,请在下面找到示例:-

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

请注意:- 这可能不是最好的解决方案,但对我来说很好。谢谢!祝代码日愉快:)

【讨论】:

以上是关于InternalOAuthError:获取访问令牌失败的主要内容,如果未能解决你的问题,请参考以下文章

护照因 404 失败 - GitHub 的 InternalOAuthError 为啥?

如何从刷新令牌中获取访问令牌?刷新令牌会过期吗?

Google Analytics:从刷新令牌中获取访问令牌

从passportjs中的刷新令牌获取oauth访问令牌

过期后使用刷新令牌获取访问令牌(JWT)

从刷新令牌获取新访问令牌的当前方法