FacebookTokenError:此授权码已被使用 [英] FacebookTokenError: This authorization code has been used

查看:396
本文介绍了FacebookTokenError:此授权码已被使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

https ://github.com/passport/express-4.x-local-example



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



我从来没有超过 console.log('ERROR HERE .. 。出现错误此授权码已被使用。

令人困惑的是,返回的验证码总是不一样的,所以当我尝试交换访问令牌时,怎么可能已经被使用?

任何人都可以提供我可以尝试一些建议,还是接下来的步骤?我的希望是,有一些关于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')。

var CLIENTSECRET ='< client secret>';

var APPID ='< app id>';


//配置Facebook策略供Passport使用。
//
//基于OAuth 2.0的策略需要一个`verify`函数,它接收
//凭据(`accessToken`),用于访问用户
上的Facebook API //代表用户的个人资料。该函数必须使用用户对象调用`cb`
//,在
//身份验证之后,路由处理程序将被设置为`req.user`。
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,个人资料,cb){
//在这个例子中,用户的Facebook个人资料是作为用户
//记录提供的。在生产质量应用程序中,Facebook个人资料应该是
//与应用程序数据库中的用户记录相关联,其中
//允许与其他身份
// provider的帐户链接和身份验证
cb(null,profile);
} ));


//配置Passport验证的会话持久性。
//
//为了在HTTP请求之间恢复身份验证状态,Passport需要
//将用户序列化并将用户从串行排除在会话之外。在
//生产质量应用程序中,通常会像
//一样简单,当序列化时提供用户ID,并从数据库查询ID
//的用户记录,反序列化。然而,由于这个
//示例没有数据库的事实,完整的Twitter配置文件被序列化为
//并被反序列化。
passport.serializeUser(function(user,cb){
cb(null,user);
});

passport.deserializeUser(function(obj,cb){
console.log();
console.log(ASSERT passport.deserializeUser被调用);
console.log();
cb(null,obj);
});


//创建一个新的Express应用程序。
var app = express();

//配置视图引擎来呈现EJS模板。
app.set('views',__dirname +'/ views');
app.set('view engine','ejs');

//使用应用程序级中间件实现常用功能,包括
//日志记录,解析和会话处理。
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}));

//初始化Passport并从
//会话恢复身份验证状态(如果有)。
app.use(passport.initialize());
//app.use(passport.session());


//定义路由。
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'}),
函数,res){

//我的代码更改从这里开始!!
var code = req.query.code;

console.log(1 ASSERT after成功登录!code =+ code;
if(req.query.error){
//用户可能不允许该应用程序
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.setEncoding('utf8');
res .on('data',function(chunk){
console.log('ERROR HERE'+ chunk);
});
});


console.log(成功登录后的2 ASSERT)

//我的代码更改结束于此!

});

app.get('/ profile',
require('connect-ensure-login')。sureLoggedIn(),
函数(req,res){
res.render('profile',{user:req.user});
});

app.listen(3000);


解决方案

您不需要向 / oauth / access_token (你做的很好,但护照已经为你处理了)。该端点是在没有访问权限时获取访问令牌,但是您已经有访问令牌:

 护照.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){
//你有这个访问令牌
cb(null,profile);
}));

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






如果您希望用户授予发布权限(您需要他们做,能够发布到自己的Feed),您还需要将每个呼叫替换为 passport.authenticate 与:

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

让用户首次添加您的应用时请求发布权限。然后,您可以使用 / user / photos 端点上传照片,传递您先前在查询字符串中保存的 accessToken


Ok, so this is a common error with many causes. I am trying to modify an existing Node-Passport-Facebook module to have local images from the desktop uploaded to a users Facebook account after they log in. That is my goal.
This is the code module I am extending
https://github.com/passport/express-4.x-local-example

which in turn is based on https://github.com/jaredhanson/passport-facebook

I never get past console.log('ERROR HERE... with an error of "This authorization code has been used."
What's confusing is that the auth code returned is ALWAYS DIFFERENT! so how could it already have been used when I try and exchange it for an access token?
Can anyone offer some suggestions, and or next steps I might try? My hunch is that there is something about Passport.js that is not implemented properly.
So my question is, how would I modify the code below (based on this passport facebook example) https://github.com/passport/express-4.x-facebook-example/blob/master/server.js
to upload an image after logging in?

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

解决方案

You don't need to make a request to /oauth/access_token at all (well you do, but passport has already handled it for you). That endpoint is for getting an access token when you don't have one, but you already have an access token here:

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

You'll need to save that accessToken some way, so that you can use it later when you make requests to the Graph API. You'll probably want to save it to the user's session, but you can also use a strategy like this: https://stackoverflow.com/a/24474900/772035


If you want the user to grant permission to publish (which you will need them to do, to be able to post to their feeds) you also need to replace every call to passport.authenticate with:

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

So that the posting permission is requested when the user first adds your app. Then you'll be able to use the /user/photos endpoint to upload a photo, passing the accessToken that you saved earlier in the query string.

这篇关于FacebookTokenError:此授权码已被使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆