2016-03-08 56 views
1

好的,所以這是很多原因的常見錯誤。我試圖修改現有的Node-Passport-Facebook模塊,讓桌面上的本地圖像在登錄後上傳到用戶Facebook帳戶。這是我的目標。
這是我延長
https://github.com/passport/express-4.x-local-exampleFacebookTokenError:已使用此授權碼

代碼模塊而這又是基於 https://github.com/jaredhanson/passport-facebook

我從來沒有闖過的console.log(「ERROR這裏..,並帶有錯誤「此授權碼已被使用。」
令人困惑的是,返回的認證碼總是不一樣!所以當我嘗試將其交換爲訪問令牌時,它如何被使用?
任何人都可以提供一些建議,或者我可能會嘗試下一步嗎?我的直覺是,有一些Passport.js沒有正確實施。
所以我的問題是,如何修改下面的代碼(基於這個護照的例子)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); 
+0

我想補充一點,顯示Facebook登錄的按鈕或提示是一個讀取「上傳圖像到Facebook」的按鈕,因此用戶在登錄時默認授予將圖像上傳到其帳戶的權限。 –

回答

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


這樣做,才能夠發佈自己的飼料),你還需要在每次調用其替換到passport.authenticate

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

這樣的發帖權限請求當用戶第一次將您的應用程序。然後,您將能夠使用端點/user/photos上傳照片,並將之前保存在查詢字符串中的accessToken傳遞給您。

+0

謝謝!在其他地方使用Google進行大量搜索之後,我得出了同樣的結論(請參閱下面的評論)。在創建測試用戶之後,我還成功將圖像上傳到具有publish_actions的用戶帳戶。剩下的是以某種方式在用戶上傳圖片後自動從服務器登錄用戶。用戶登錄後,他們保持身份驗證,並且Facebook登錄始終被繞過。我假設這個身份驗證保存在cookie和/或會話中?無論如何會獎勵你的賞金,但會感謝退出問題的反饋。 –

+0

另外,如果我將accessToken定義爲要用於圖片上傳的全局變量,是否需要保存它? –

+0

嗨@eco_bach,謝謝你的賞金。我不認爲你想要將他們從Facebook註銷,因爲如果他們在另一個標籤中瀏覽Facebook,這將會非常煩人。沒有保存的cookie,但Facebook記住用戶已給予您的應用權限,因此您無需將它們發送到Facebook再發布。如果您想將它們發回,可以通過向[/me/permissions](https://developers.facebook.com/docs/graph-api/reference/user/permissions)發送HTTP DELETE請求將其與應用斷開連接#revoking)與您獲得的訪問令牌。 – Paulpro

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

我認爲這是您的問題。代碼本身看起來很好,除此之外。順便說一下,你需要查詢字符串模塊來解析結果。

+0

謝謝。獲取相同的錯誤。然而,進一步的谷歌搜索導致我相信我的代碼中存在更多更大的邏輯錯誤。在我的Passport.js回調函數函數(accessToken,refreshToken,profile,cb){我正在獲取訪問令牌,所以不需要額外的調用來獲取它!但是,現在得到一個'publish_actions'丟失的錯誤,導致其他問題1-如果需要發佈操作以將照片發佈到用戶的時間表,我是否需要提交我的申請以獲得批准才能啓用publish_actions?祝願Facebook更清晰! –

+0

是的,您通常需要通過Facebook批准您的服務才能在測試帳戶之外獲得任何工作。 –