FacebookTokenError:已使用此授权码

问题描述 投票:1回答:3

好的,所以这是一个常见的错误,有很多原因。我正在尝试修改现有的Node-Passport-Facebook模块,以便在桌面登录后将桌面上的本地图像上传到用户的Facebook帐户。这是我的目标。 这是我正在扩展的代码模块 https://github.com/passport/express-4.x-local-example

而这又基于https://github.com/jaredhanson/passport-facebook

我从来没有通过console.log('错误在这里......错误“已使用此授权码。” 令人困惑的是返回的验证码总是不同的!那么当我尝试将其替换为访问令牌时,它怎么可能已被使用? 任何人都可以提供一些建议,或者我可能会尝试下一步吗?我的预感是Passport.js有些东西没有正确实现。 所以我的问题是,我将如何修改下面的代码(基于这个护照facebook的例子)https://github.com/passport/express-4.x-facebook-example/blob/master/server.js 登录后上传图片?

var express = require('express');
var passport = require('passport');
var Strategy = require('passport-facebook').Strategy;

var CLIENTSECRET ='<client secret>';

var APPID ='<app id>';


// Configure the Facebook strategy for use by Passport.
//
// OAuth 2.0-based strategies require a `verify` function which receives the
// credential (`accessToken`) for accessing the Facebook API on the user's
// behalf, along with the user's profile.  The function must invoke `cb`
// with a user object, which will be set at `req.user` in route handlers after
// authentication.
passport.use(new Strategy({

    clientID: APPID,
    clientSecret: CLIENTSECRET,
    callbackURL: 'http://localhost:3000/login/facebook/return',
    enableProof: true
    //callbackURL: 'http://localhost:3000/login/facebook/return'
  },
  function(accessToken, refreshToken, profile, cb) {
    // In this example, the user's Facebook profile is supplied as the user
    // record.  In a production-quality application, the Facebook profile should
    // be associated with a user record in the application's database, which
    // allows for account linking and authentication with other identity
    // providers.
    cb(null, profile);
  }));


// Configure Passport authenticated session persistence.
//
// In order to restore authentication state across HTTP requests, Passport needs
// to serialize users into and deserialize users out of the session.  In a
// production-quality application, this would typically be as simple as
// supplying the user ID when serializing, and querying the user record by ID
// from the database when deserializing.  However, due to the fact that this
// example does not have a database, the complete Twitter profile is serialized
// and deserialized.
passport.serializeUser(function(user, cb) {
  cb(null, user);
});

passport.deserializeUser(function(obj, cb) {
    console.log(" ");
    console.log("ASSERT passport.deserializeUser being called");
    console.log(" ");
    cb(null, obj);
});


// Create a new Express application.
var app = express();

// Configure view engine to render EJS templates.
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');

// Use application-level middleware for common functionality, including
// logging, parsing, and session handling.
app.use(require('morgan')('combined'));
app.use(require('cookie-parser')());
app.use(require('body-parser').urlencoded({ extended: true }));
app.use(require('express-session')({ secret: 'keyboard cat', resave: true, saveUninitialized: true }));

// Initialize Passport and restore authentication state, if any, from the
// session.
app.use(passport.initialize());
//app.use(passport.session());


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

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

app.get('/login/facebook',
  passport.authenticate('facebook'));

app.get('/login/facebook/return', 
  passport.authenticate('facebook', { failureRedirect: '/login' }),
  function(req, res) {

    //my code changes start here!!
    var code = req.query.code;

    console.log("1 ASSERT after successful login! code="+code);
    if(req.query.error) {
        // user might have disallowed the app
        return res.send('login-error ' + req.query.error_description);
    } else if(!code) {
        return res.redirect('/');
    }

    var options={
        host:'graph.facebook.com',      
        path:'/oauth/access_token?client_id='+APPID+'&code='+code +'&client_secret='+CLIENTSECRET+'&redirect_uri=http://localhost:3000/login/faceboo k/return'
    }       
    var https=require('https'); 
    https.get(options,function(res){
         res.setEncoding('utf8');       
         res.on('data', function (chunk) {
                console.log('ERROR HERE'+chunk);
        });
    });    


    console.log("2  ASSERT after successful login!")

     //my code changes end here!!

});

app.get('/profile',
  require('connect-ensure-login').ensureLoggedIn(),
  function(req, res){
    res.render('profile', { user: req.user });
  });

app.listen(3000);
node.js facebook facebook-graph-api oauth passport.js
3个回答
1
投票

您根本不需要向/oauth/access_token提出请求(好吧,但护照已经为您处理了)。该端点用于在您没有访问令牌时获取访问令牌,但您已在此处拥有访问令牌:

passport.use(new Strategy({
    clientID: APPID,
    clientSecret: CLIENTSECRET,
    callbackURL: 'http://localhost:3000/login/facebook/return',
    enableProof: true
    //callbackURL: 'http://localhost:3000/login/facebook/return'
  },
  function(accessToken, refreshToken, profile, cb) {
    // You have the access token here!
    cb(null, profile);
  }));

您需要以某种方式保存accessToken,以便以后在向Graph API发出请求时使用它。您可能希望将其保存到用户的会话中,但您也可以使用如下策略:https://stackoverflow.com/a/24474900/772035

如果您希望用户授予发布权限(您需要他们执行此操作,以便能够发布到他们的Feed),您还需要将对passport.authenticate的每次调用替换为:

passport.authenticate('facebook', { scope: ['publish_actions'] } );

因此,当用户首次添加您的应用时,会请求发布权限。然后,您将能够使用/user/photos端点上传照片,并将之前保存的accessToken传递给查询字符串。


0
投票

您需要对查询参数进行编码。

var qs = {
    client_id: APPID,
    redirect_uri: 'http://localhost:3000/login/facebook/return',
    client_secret: CLIENTSECRET,
    code: code,
};
options = {
    host:'graph.facebook.com',
    path:'/oauth/access_token?' + require('querystring').stringify(qs),
};

我认为这是你的问题。代码本身除此之外看起来很好。您还希望querystring模块能够解析结果。


0
投票

我解决了这个错误。跟进进度。 Facebook登录 - >设置 - >应用程序 - >使用Facebook登录 - >删除您的应用程序。删除您的应用后,尝试使用Facebook登录按钮。

© www.soinside.com 2019 - 2024. All rights reserved.