diff --git a/.gitignore b/.gitignore index 3c3629e..44f7ca4 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -node_modules +./node_modules/* diff --git a/README.md b/README.md index 9ff569b..cfb84a0 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # faceplate - + A Node.js wrapper for Facebook authentication and API ## Usage @@ -20,14 +20,14 @@ var app = require('express').createServer( // show friends app.get('/friends', function(req, res) { - req.facebook.get('/me/friends', { limit: 4 }, function(err, friends) { + req.facebook.get('/me/friends', { limit: 4 }, function(friends) { res.send('friends: ' + require('util').inspect(friends)); }); }); // use fql to show my friends using this app app.get('/friends_using_app', function(req, res) { - req.facebook.fql('SELECT uid, name, is_app_user, pic_square FROM user WHERE uid in (SELECT uid2 FROM friend WHERE uid1 = me()) AND is_app_user = 1', function(err, friends_using_app) { + req.facebook.fql('SELECT uid, name, is_app_user, pic_square FROM user WHERE uid in (SELECT uid2 FROM friend WHERE uid1 = me()) AND is_app_user = 1', function(friends_using_app) { res.send('friends using app: ' + require('util').inspect(friends_using_app)); }); }); @@ -38,9 +38,9 @@ app.get('/multiquery', function(req, res) { likes: 'SELECT user_id, object_id, post_id FROM like WHERE user_id=me()', albums: 'SELECT object_id, cover_object_id, name FROM album WHERE owner=me()', }, - function(err, result) { + function(result) { var inspect = require('util').inspect; - res.send('Your likes: ' + inspect(result.likes) + ', your albums: ' + inspect(result.albums) ); + res.send('Yor likes: ' + inspect(result.likes) + ', your albums: ' + inspect(result.albums) ); }); }); diff --git a/index.js b/index.js index 3e365be..ea10b21 100644 --- a/index.js +++ b/index.js @@ -2,6 +2,16 @@ var b64url = require('b64url'); var crypto = require('crypto'); var qs = require('querystring'); var restler = require('restler'); + + +function safeParse(str){ +// console.log('parsing str: ', str) + if(typeof(str) != 'string') return str; + try{ return JSON.parse(str)} + catch(e){ + return {error: e, response: str} + } +} var Faceplate = function(options) { @@ -12,14 +22,17 @@ var Faceplate = function(options) { this.secret = this.options.secret; this.middleware = function() { - return function faceplate(req, res, next) { + return function(req, res, next) { + if (req.body.signed_request) { self.parse_signed_request(req.body.signed_request, function(err, decoded_signed_request) { req.facebook = new FaceplateSession(self, decoded_signed_request); next(); }); } else if (req.cookies["fbsr_" + self.app_id]) { - self.parse_signed_request(req.cookies["fbsr_" + self.app_id], function(err, decoded_signed_request) { + console.log('in') + self.parse_signed_request(req.cookies["fbsr_" + self.app_id], function(err,decoded_signed_request){ + console.log('out') req.facebook = new FaceplateSession(self, decoded_signed_request); next(); }); @@ -35,38 +48,36 @@ var Faceplate = function(options) { var sig = encoded_data[0]; var json = b64url.decode(encoded_data[1]); - var data = JSON.parse(json); + var data = safeParse(json); // check algorithm if (!data.algorithm || (data.algorithm.toUpperCase() != 'HMAC-SHA256')) { cb(new Error("unknown algorithm. expected HMAC-SHA256")); - return; } // check signature var secret = self.secret; var expected_sig = crypto.createHmac('sha256', secret).update(encoded_data[1]).digest('base64').replace(/\+/g,'-').replace(/\//g,'_').replace('=',''); - if (sig !== expected_sig) { + if (sig !== expected_sig) cb(new Error("bad signature")); - return; - } // not logged in or not authorized if (!data.user_id) { + console.log('no user id') cb(null,data); return; } + var user_id = data.user_id; if (data.access_token || data.oauth_token) { + console.log('has access token') cb(null,data); return; } - if (!data.code) { + if (!data.code) cb(new Error("no oauth token and no code to get one")); - return; - } var params = { client_id: self.app_id, @@ -78,13 +89,19 @@ var Faceplate = function(options) { var request = restler.get('https://graph.facebook.com/oauth/access_token', { query:params }); + console.log('sending request') request.on('fail', function(data) { - var result = JSON.parse(data); + console.log('failed..') + var result = safeParse(data); + result.user_id = user_id cb(result); }); request.on('success', function(data) { - cb(null,qs.parse(data)); + console.log('win...', data) + data = qs.parse(data) + data.user_id = user_id + cb(null,data); }); }; }; @@ -94,10 +111,12 @@ var FaceplateSession = function(plate, signed_request) { var self = this; this.plate = plate; + //console.log('request: ', signed_request) if (signed_request) { this.token = signed_request.access_token || signed_request.oauth_token; this.signed_request = signed_request; } + console.log('token: ', this.token) this.app = function(cb) { self.get('/' + self.plate.app_id, function(err, app) { @@ -128,10 +147,14 @@ var FaceplateSession = function(plate, signed_request) { var request = restler.get('https://graph.facebook.com' + path, { query: params }); request.on('fail', function(data) { - cb(data); + console.log('fb fail ~> ', data) + var result = safeParse(data); + cb(result); }); request.on('success', function(data) { - cb(null, data); + var result = safeParse(data); + console.log('fb ~>', data) + cb(null, result); }); } catch (err) { cb(err); @@ -147,7 +170,7 @@ var FaceplateSession = function(plate, signed_request) { method = 'fql.query'; params.query = query; onComplete = function(res){ - var result = JSON.parse(res); + var result = safeParse(res); cb(null, result.data ? result.data : result); }; } @@ -168,7 +191,7 @@ var FaceplateSession = function(plate, signed_request) { var request = restler.get('https://api.facebook.com/method/'+method, { query: params }); request.on('fail', function(data) { - var result = JSON.parse(data); + var result = safeParse(data); cb(result); }); request.on('success', onComplete); @@ -180,11 +203,11 @@ var FaceplateSession = function(plate, signed_request) { {query: {access_token: self.token}, data: params} ); request.on('fail', function(data) { - var result = JSON.parse(data); + var result = safeParse(data); cb(result); }); request.on('success', function (data) { - var result = JSON.parse(data); + var result = safeParse(data); cb(null, result.data ? result.data : result); }); }; diff --git a/package.json b/package.json index 1a1c5e5..8dce5bc 100644 --- a/package.json +++ b/package.json @@ -1,18 +1,19 @@ -{ - "name": "faceplate", - "version": "0.5.0", - "author": "Heroku", - "homepage": "https://github.com/heroku/faceplate", - +{ + "name": "faceplate", + "version": "0.5.0", + "author": { + "name": "Heroku" + }, + "homepage": "https://github.com/IlskenLabs/faceplate", "description": "Wrapper for Facebook authentication and API", - "repository": { "type": "git", - "url": "https://github.com/heroku/faceplate" + "url": "https://github.com/IlskenLabs/faceplate.git" }, - "dependencies": { - "b64url": "1.0.3", - "restler": "2.0.0" - } + "b64url": "1.0.3", + "restler": "~2.0.0" + }, + "readme": "# faceplate\n\nA Node.js wrapper for Facebook authentication and API\n\n## Usage\n\nUse as a connect middleware\n\n```javascript\n// create an express webserver\nvar app = require('express').createServer(\n express.bodyParser(),\n express.cookieParser(),\n require('faceplate').middleware({\n app_id: process.env.FACEBOOK_APP_ID,\n secret: process.env.FACEBOOK_SECRET,\n scope: 'user_likes,user_photos,user_photo_video_tags'\n })\n);\n\n// show friends\napp.get('/friends', function(req, res) {\n req.facebook.get('/me/friends', { limit: 4 }, function(friends) {\n res.send('friends: ' + require('util').inspect(friends));\n });\n});\n\n// use fql to show my friends using this app\napp.get('/friends_using_app', function(req, res) {\n req.facebook.fql('SELECT uid, name, is_app_user, pic_square FROM user WHERE uid in (SELECT uid2 FROM friend WHERE uid1 = me()) AND is_app_user = 1', function(friends_using_app) {\n res.send('friends using app: ' + require('util').inspect(friends_using_app));\n });\n});\n\n// perform multiple fql queries at once\napp.get('/multiquery', function(req, res) {\n req.facebook.fql({\n likes: 'SELECT user_id, object_id, post_id FROM like WHERE user_id=me()',\n albums: 'SELECT object_id, cover_object_id, name FROM album WHERE owner=me()',\n },\n function(result) {\n var inspect = require('util').inspect;\n res.send('Yor likes: ' + inspect(result.likes) + ', your albums: ' + inspect(result.albums) );\n });\n});\n\n// See the full signed request details\napp.get('/signed_request', function(req, res) {\n res.send('Signed Request details: ' + require('util').inspect(req.facebook.signed_request));\n});\n\n```\n\n## License\n\nMIT\n", + "readmeFilename": "README.md" } diff --git a/strategy.js b/strategy.js new file mode 100644 index 0000000..e69de29