好的,所以这是一个常见的错误,有很多原因。我正在尝试修改现有的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);
您根本不需要向/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
传递给查询字符串。
您需要对查询参数进行编码。
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模块能够解析结果。
我解决了这个错误。跟进进度。 Facebook登录 - >设置 - >应用程序 - >使用Facebook登录 - >删除您的应用程序。删除您的应用后,尝试使用Facebook登录按钮。