Skip to content

Commit

Permalink
Added support for fbsr-cookie. fixes #16
Browse files Browse the repository at this point in the history
  • Loading branch information
DracoBlue committed Jan 5, 2012
1 parent 085a84d commit 328b6e2
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 21 deletions.
6 changes: 4 additions & 2 deletions README.md
@@ -1,7 +1,7 @@
node-facebook-client README
===========================

Version: 1.5-dev
Version: 1.5.0

Official Site: <http://dracoblue.net/>

Expand Down Expand Up @@ -145,7 +145,8 @@ Calculates the signature for a given set of parameters and the api_secret.
Changelog
---------

- 1.5-dev
- 1.5.0 (2012/01/05)
- added support for fbsr-cookie from new facebook auth #16
- added support for lazy-access-token retrieval if oauth-code is given
- 1.4.0 (2011/10/06)
- added multiquery-support. #12
Expand All @@ -168,6 +169,7 @@ Contributors

- DracoBlue http://dracoblue.net
- jharlap https://github.com/jharlap
- liuliu https://github.com/liuliu

License
--------
Expand Down
132 changes: 116 additions & 16 deletions lib/facebook-client/FacebookClient.js
Expand Up @@ -11,6 +11,7 @@ var sys = require("sys");
var http = require("http");
var https = require("https");
var querystring = require("querystring");
var crypto = require("crypto");

var FacebookSession = require("./FacebookSession").FacebookSession;
var FacebookToolkit = require("./FacebookToolkit");
Expand Down Expand Up @@ -139,6 +140,12 @@ var FacebookClient = function(api_key, api_secret, options) {
};
};

this.signaturePayload = function(payload) {
var hmac = crypto.createHmac('sha256', api_secret);
hmac.update(payload);
return hmac.digest('hex');
};

};

FacebookClient.prototype.getSessionByAccessToken = function(access_token) {
Expand All @@ -149,29 +156,76 @@ FacebookClient.prototype.getSessionByAccessToken = function(access_token) {
};
};

FacebookClient.prototype.getSessionByRequestHeaders = function(request_headers) {
FacebookClient.prototype.getSessionByOauthCode = function(oauth_code) {
var self = this;
return function(cb) {
if (!request_headers['cookie'])
var session = new FacebookSession(self, null, oauth_code);
cb(session);
};
};

FacebookClient.prototype.getSessionByFbsCookie = function(fbs_cookie) {
var self = this;

return function(cb) {
var facebook_cookie = querystring.parse(fbs_cookie);;

if (!facebook_cookie)
{
/*
* We have not even cookies on this request!
* The cookie cannot be parsed.
*/
cb();
return
return ;
}

var facebook_cookie_raw = request_headers["cookie"].match(/fbs_[\d]+\=\"([^; ]+)\"/);
if (!facebook_cookie_raw)
if (!facebook_cookie['access_token'] || !facebook_cookie['expires']) {
/*
* We don't have an access_token nor expires, this won't work.
*/
cb();
return ;
}

var now = new Date();
var expires_time = parseInt(facebook_cookie['expires'], 10) * 1000;

if (now.getTime() < expires_time)
{
/*
* There is no such thing as a fbs_ cookie in the request.
* The token is expired.
*/
cb();
return ;
}

self.getSessionByAccessToken(facebook_cookie['access_token'])(cb);
};
};

FacebookClient.prototype.getSessionByFbsrCookie = function(fbsr_cookie) {
var self = this;

return function(cb) {
var facebook_cookie = null;
var fbsr_cookie_parts = fbsr_cookie.split('.');
var signature = new Buffer(fbsr_cookie_parts[0].replace(/\-/g, '+').replace(/\_/g, '/'), 'base64').toString('hex');
var payload = fbsr_cookie_parts[1];
var facebook_cookie_raw_json = new Buffer(payload.replace(/\-/g, '+').replace(/\_/g, '/'), 'base64').toString('binary');

try
{
facebook_cookie = JSON.parse(facebook_cookie_raw_json);
}
catch (error)
{
/*
* Invalid json :(
*/
facebook_cookie = null;
}

var facebook_cookie = querystring.parse(facebook_cookie_raw[1]);

if (!facebook_cookie)
{
/*
Expand All @@ -181,26 +235,72 @@ FacebookClient.prototype.getSessionByRequestHeaders = function(request_headers)
return ;
}

if (!facebook_cookie['access_token'] || !facebook_cookie['expires']) {
if (!facebook_cookie['algorithm'] || !facebook_cookie['code'] || !facebook_cookie['issued_at']) {
/*
* We don't have an access_token nor expires, this won't work.
* We don't have an algorithm, code or issued_at, this won't work.
*/
cb();
return ;
}

if (facebook_cookie['algorithm'].toUpperCase() != 'HMAC-SHA256')
{
/*
* We cannot support any other alogrithm at the moment (actually
* this is the only one facebook supports right now).
*/
cb();
return ;
}

var expected_signature = self.signaturePayload(payload);

if (expected_signature !== signature)
{
/*
* The signature was wrong.
*/
cb();
return ;
}

var now = new Date();
var expires_time = parseInt(facebook_cookie['expires'], 10) * 1000;
self.getSessionByOauthCode(facebook_cookie['code'])(cb);
};
};

if (now.getTime() < expires_time)
FacebookClient.prototype.getSessionByRequestHeaders = function(request_headers) {
var self = this;

return function(cb) {
if (!request_headers['cookie'])
{
/*
* The token is expired.
* We have not even cookies on this request!
*/
cb();
return
}

var facebook_cookie_raw = request_headers["cookie"].match(/fbs_[\d]+\=\"([^; ]+)\"/);
if (facebook_cookie_raw)
{
self.getSessionByFbsCookie(facebook_cookie_raw[1])(cb);
return ;
}

self.getSessionByAccessToken(facebook_cookie['access_token'])(cb);

facebook_cookie_raw = request_headers["cookie"].match(/fbsr_[\d]+\=([^; ]+)/);

if (facebook_cookie_raw)
{
self.getSessionByFbsrCookie(facebook_cookie_raw[1])(cb);
return ;
}

/*
* There is no such thing as a fbs_ or fbsr_ cookie in the request.
*/

cb();
};
};

Expand Down
7 changes: 4 additions & 3 deletions package.json
@@ -1,6 +1,6 @@
{
"name" : "facebook-client",
"version": "1.4.0",
"version": "1.5.0",

"engines": { "node": ">= 0.4.0" },

Expand All @@ -11,7 +11,8 @@
"author": "DracoBlue <JanS@DracoBlue.de>",
"contributors": [
{ "name": "DracoBlue", "email": "JanS@DracoBlue.de" },
{ "name": "jharlap" }
{ "name": "jharlap" },
{ "name": "liuliu" }
],

"keywords": ["facebook", "oauth", "client"],
Expand All @@ -30,7 +31,7 @@
},

"bugs": {
"web": "http://github.com/DracoBlue/node-facebook-client/issues"
"url": "http://github.com/DracoBlue/node-facebook-client/issues"
},

"licenses" : [
Expand Down

0 comments on commit 328b6e2

Please sign in to comment.