Skip to content

Express 10 #5

Closed
wants to merge 8 commits into from
View
3 .gitmodules
@@ -1,6 +1,3 @@
[submodule "lib/support/express"]
path = lib/support/express
url = git://github.com/visionmedia/express.git
-[submodule "lib/support/hashlib"]
- path = lib/support/hashlib
- url = git://github.com/brainfucker/hashlib.git
View
105 README.textile
@@ -22,13 +22,6 @@ git submodule init
git submodule update
</code></pre>
-Also, we need to install "hashlib":http://github.com/brainfucker/hashlib, a NodeJS library provided by mr Brainfucker:
-
-<pre><code>git submodule add git://github.com/brainfucker/hashlib.git lib/support/hashlib
-cd lib/support/hashlib
-make
-</code></pre>
-
h2. Setting up your Project
1. Create the necessary folders:
@@ -62,65 +55,62 @@ h3. /app.js
<pre><code>require.paths.unshift(__dirname + '/lib')
require.paths.unshift(__dirname + '/lib/support/express/lib')
-require.paths.unshift(__dirname + '/lib/support/hashlib/build/default')
-
-require('express')
-require('express/plugins')
-
-configure(function(){
- use(MethodOverride)
- use(ContentLength)
- use(Cookie)
- use(Session)
- use(Logger)
- use(require('facebook').Facebook, {
+
+var express = require('express')
+var app = express.createServer();
+
+app.configure(function(){
+ app.use(express.methodOverride())
+ app.use(ContentLength)
+ app.use(Cookie)
+ app.use(Session)
+ app.use(Logger)
+ app.use(require('facebook').Facebook(dx{
apiKey: 'e1249f7d4bc25b8f90e5c9c7523e3ee1',
apiSecret: '4ae45734dd66fa85c7b189fc2d7d5b4c'
})
- set('root', __dirname)
+ app.set('root', __dirname)
})
// Called to get information about the current authenticated user
-get('/fbSession', function(){
- var fbSession = this.fbSession()
+app.get('/fbSession', function(req, res){
+ var fbSession = req.fbSession()
if(fbSession) {
// Here would be a nice place to lookup userId in the database
// and supply some additional information for the client to use
}
// The client will only assume authentication was OK if userId exists
- this.contentType('json')
- this.halt(200, JSON.stringify(fbSession || {}))
+ res.send(JSON.stringify(fbSession || {}), {'Content-Type: 'application/json'});
})
// Called after a successful FB Connect
-post('/fbSession', function() {
- var fbSession = this.fbSession() // Will return null if verification was unsuccesful
+app.post('/fbSession', function(req, res) {
+ var fbSession = req.fbSession() // Will return null if verification was unsuccesful
if(fbSession) {
// Now that we have a Facebook Session, we might want to store this new user in the db
// Also, in this.params there is additional information about the user (name, pic, first_name, etc)
// Note of warning: unlike fbSession, this additional information has not been verified
- fbSession.first_name = this.params.post['first_name']
+ fbSession.first_name = req.params['first_name']
}
- this.contentType('json')
- this.halt(200, JSON.stringify(fbSession || {}))
+ res.send(JSON.stringify(fbSession || {}), {'Content-Type: 'application/json'});
})
// Called on Facebook logout
-post('/fbLogout', function() {
- this.fbLogout();
- this.halt(200, JSON.stringify({}))
+app.post('/fbLogout', function(req, res) {
+ req.fbLogout();
+ res.send(JSON.stringify({}))
})
// Static files in ./public
-get('/', function(file){ this.sendfile(__dirname + '/public/index.html') })
-get('/xd_receiver.htm', function(file){ this.sendfile(__dirname + '/public/xd_receiver.htm') })
-get('/javascripts/jquery.facebook.js', function(file){ this.sendfile(__dirname + '/public/javascripts/jquery.facebook.js') })
+app.get('/', function(req, res){ res.sendfile(__dirname + '/public/index.html') })
+app.get('/xd_receiver.htm', function(req, res){ res.sendfile(__dirname + '/public/xd_receiver.htm') })
+app.get('/javascripts/jquery.facebook.js', function(res, res){ res.sendfile(__dirname + '/public/javascripts/jquery.facebook.js') })
-run()
+app.listen()
</code></pre>
@@ -193,49 +183,46 @@ h3. /app.js
<pre><code>require.paths.unshift(__dirname + '/lib')
require.paths.unshift(__dirname + '/lib/support/express/lib')
-require.paths.unshift(__dirname + '/lib/support/hashlib/build/default')
-
-require('express')
-require('express/plugins')
-
-configure(function(){
- use(MethodOverride)
- use(ContentLength)
- use(Cookie)
- use(Session)
- use(Logger)
- use(require('facebook').Facebook, {
+
+var express = require('express')
+var app = express,createServer();
+
+app.configure(function(){
+ app.use(express.methodOverride())
+ app.use(express.cookieDecoder())
+ app.use(express.session())
+ app.use(express.logger())
+ app.use(require('facebook').Facebook({
apiKey: 'e1249f7d4bc25b8f90e5c9c7523e3ee1',
apiSecret: '4ae45734dd66fa85c7b189fc2d7d5b4c'
})
- set('root', __dirname)
+ express.staticProvider(__dirname + '/public')
})
// This is the canvas URL set in the Facebook Application settings
-get('/iframe', function (){
- var fbSession = this.fbSession() // Will create a session based on verified data from the GET params
- this.sendfile(__dirname + '/public/iframe.html')
+app.get('/iframe', function(req, res) {
+ var fbSession = req.fbSession() // Will create a session based on verified data from the GET params
+ res.sendfile(__dirname + '/public/iframe.html')
})
// Called to get information about the current authenticated user
-get('/fbSession', function(){
- var fbSession = this.fbSession()
+app.get('/fbSession', function(req, res){
+ var fbSession = req.fbSession()
if(fbSession) {
// Here would be a nice place to lookup userId in the database
// and supply some additional information for the client to use
}
// The client will only assume authentication was OK if userId exists
- this.contentType('json')
- this.halt(200, JSON.stringify(fbSession || {}))
+ res.send(JSON.stringify(fbSession || {}), {'Content-Type: 'application/json'});
})
// Static files in ./public
-get('/xd_receiver.htm', function(file){ this.sendfile(__dirname + '/public/xd_receiver.htm') })
-get('/javascripts/jquery.facebook.js', function(file){ this.sendfile(__dirname + '/public/javascripts/jquery.facebook.js') })
+app.get('/xd_receiver.htm', function(req, res){ res.sendfile(__dirname + '/public/xd_receiver.htm') })
+app.get('/javascripts/jquery.facebook.js', function(req, res){ res.sendfile(__dirname + '/public/javascripts/jquery.facebook.js') })
-run()
+app.listen()
</code></pre>
View
146 lib/facebook.js
@@ -1,23 +1,27 @@
// Express - Facebook - By Dominiek ter Heide (MIT Licensed)
-sys = require('sys')
-hashlib = require('hashlib')
+var sys = require('sys')
+var base64 = require('base64')
+var crypto = require('crypto')
+var querystring = require('querystring')
-exports.FBSession = Class({
- init: function (userId) {
+function FBSession(userId) {
this.userId = userId;
- }
-});
+};
exports.getFingerprintForCookie = function (apiKey, cookies) {
- var fields = ['expires', 'session_key', 'ss', 'user'];
+ var values = querystring.parse(cookies[apiKey]);
+ var keys = [];
+ for (var i in values)
+ keys.push(i);
var fingerprint = '';
- fields.sort();
- for(var i in fields) {
- fingerprint += fields[i]+'='+cookies[apiKey + '_' + fields[i]];
- }
- return fingerprint;
+ keys.sort();
+ keys.forEach(function(key) {
+ if (key != 'sig')
+ fingerprint += key +'='+ values[key];
+ });
+ return {fingerprint: fingerprint, sig: values['sig']};
}
exports.getFingerprintForParams = function (params) {
@@ -38,85 +42,73 @@ exports.getFingerprintForParams = function (params) {
// --- Facebook
-exports.Facebook = Plugin.extend({
- extend: {
-
- /**
- * Initialize extensions.
- */
-
- init: function(options) {
- var apiKey = options['apiKey']
- var apiSecret = options['apiSecret']
-
- // --- Internal methods
-
- Request.include({
+exports.Facebook = function(options) {
+ options = options || {};
+ var apiKey = options['apiKey']
+ var apiSecret = options['apiSecret']
+ return function(req, res, next) {
/**
- * Find or create Facebook session based on stored session, GET params or cookie
+ * Try authenticating by verifying Facebook data in GET params and cookie
*
- * @param {hash} options
* @return {FBSession}
* @api public
*/
+ req.fbAuthenticate = function() {
+ var cookies = req.cookies;
+ var params = req.query;
+
+ // Get a fingerprint and signature
+ var fingerprint = null;
+ var signature = null;
+
+ if(cookies && cookies['fbs_'+apiKey]) {
+ var r = exports.getFingerprintForCookie('fbs_'+ apiKey, cookies)
+ fingerprint = r.fingerprint
+ signature = r.sig
+ }
+ if(params && params['fb_sig']) {
+ fingerprint = exports.getFingerprintForParams(params)
+ signature = params['fb_sig']
+ }
+ if(!fingerprint)
+ return null;
+
+ // Verify signature using apiSecret
+ var hash = crypto.createHash('md5')
+ hash.update(fingerprint+apiSecret)
+ var expected_signature = hash.digest('hex')
+ var valid = (expected_signature === signature)
+ if(!valid)
+ sys.puts("Warning, invalid signature: "+fingerprint)
+ return valid
+ };
- fbSession: function(options) {
- var session = this.session.fbSession;
- if(session && session.userId)
- return session;
- if(this.fbAuthenticate()) {
- var fbUserId = this.param('fb_sig_user') ? this.param('fb_sig_user') : this.cookie(apiKey + '_user')
- this.session.fbSession = new exports.FBSession(fbUserId);
- return this.session.fbSession;
- }
- return null;
- },
-
/**
- * Try authenticating by verifying Facebook data in GET params and cookie
- *
- * @param {hash} options
+ * Find or create Facebook session based on stored session, GET params or cookie
* @return {FBSession}
* @api public
*/
-
- fbAuthenticate: function(options) {
- var cookies = this.cookies;
- var params = this.params.get;
-
- // Get a fingerprint and signature
- var fingerprint = null;
- var signature = null;
- if(cookies && cookies[apiKey]) {
- fingerprint = exports.getFingerprintForCookie(apiKey, cookies)
- signature = cookies[apiKey]
- }
- if(params && params['fb_sig']) {
- fingerprint = exports.getFingerprintForParams(params)
- signature = params['fb_sig']
- }
- if(!fingerprint)
+ req.fbSession = function() {
+ var session = req.session.fbSession;
+ if(session && session.userId)
+ return session;
+ if(req.fbAuthenticate()) {
+ var fbUserId = req.query['fb_sig_user'] ? req.query['fb_sig_user'] : querystring.parse(req.cookies['fbs_'+apiKey])['uid']
+ req.session.fbSession = new FBSession(fbUserId);
+ return req.session.fbSession;
+ }
return null;
-
- // Verify signature using apiSecret
- var expected_signature = hashlib.md5(fingerprint+apiSecret);
- var valid = (expected_signature === signature)
- if(!valid)
- sys.puts("Warning, invalid signature: "+fingerprint)
- return valid
- },
-
+ };
/**
* Logout
* @return null
* @api public
*/
- fbLogout: function() {
- this.session.fbSession = null
- return null
- },
- })
- }
- }
-})
+ req.fbLogout = function() {
+ req.session.fbSession = null
+ return null
+ };
+ next();
+ };
+};
1 lib/support/hashlib
@@ -1 +0,0 @@
-Subproject commit a1a03f7dc857fa9c4f44430b7310f06a650eb99e
View
10 package.json
@@ -0,0 +1,10 @@
+{
+ "name":"facebook",
+ "description": "Simple Facebook Integration for NodeJS (and Express)",
+ "version":"0.0.3",
+ "author": "Dominiek ter Heide",
+ "main": "./lib/facebook",
+ "dependencies": {
+ "base64":""
+ }
+}
View
17 spec/node.js
@@ -1,21 +1,16 @@
-require.paths.unshift('spec', '/opt/local/lib/ruby/gems/1.8/gems/jspec-3.3.2/lib', 'lib')
-require.paths.unshift('spec', 'lib', 'spec/lib')
+require.paths.unshift('/home/francois/.gem/ruby/1.8/gems/jspec-4.3.3/lib')
require.paths.unshift(__dirname + '/../lib')
-require.paths.unshift(__dirname + '/../lib/support')
-require.paths.unshift(__dirname + '/../lib/support/express/lib')
-require.paths.unshift(__dirname + '/../lib/support/hashlib/build/default')
-require('jspec')
-require("express")
-require("express/spec")
+var JSPEC = require('jspec');
+var express = require("express")
-print = puts
+print = require('sys').puts
quit = process.exit
-Express.environment = 'test'
+//Express.environment = 'test'
JSpec
- .exec('./spec.plugins.facebook.js')
+ .exec(__dirname +'/spec.plugins.facebook.js')
.run({ reporter: JSpec.reporters.Terminal, fixturePath: 'spec/fixtures' })
.report()
View
22 spec/spec.plugins.facebook.js
@@ -1,20 +1,22 @@
describe 'Express'
before_each
- reset()
facebook = require('facebook')
- use(facebook.Facebook, {
+ var express = require('express')
+ var querystring = require('querystring')
+ app = express.createServer();
+ app.use(facebook.Facebook, {
apiKey: 'e1249f7d4bc25b8f90e5c9c7523e3ee1',
apiSecret: '4ae45734dd66fa85c7b189fc2d7d5b4c'
})
- validCookies = {
- "e1249f7d4bc25b8f90e5c9c7523e3ee1": "5b820bb72e780318acb26ff375db4cc9",
- "e1249f7d4bc25b8f90e5c9c7523e3ee1_user": "687215451",
- "e1249f7d4bc25b8f90e5c9c7523e3ee1_ss": "lWYbyFp0GP8e7BgPa1aLDg__",
- "e1249f7d4bc25b8f90e5c9c7523e3ee1_session_key": "3.LIysipyTte6aXFBcStEixg__.3600.1267714800-687215451",
- "e1249f7d4bc25b8f90e5c9c7523e3ee1_expires": "1267714800"
- }
+ validCookies = {"e1249f7d4bc25b8f90e5c9c7523e3ee1": querystring.stringify({
+ "sig" : "e",
+ "user":"687215451",
+ "ss":"lWYbyFp0GP8e7BgPa1aLDg__",
+ "session_key":"3.LIysipyTte6aXFBcStEixg__.3600.1267714800-687215451",
+ "expires":"1267714800"
+ })}
tamperedCookies = {
"e1249f7d4bc25b8f90e5c9c7523e3ee1": "5b820bb72e780318acb26ff375db4cc9",
@@ -78,7 +80,7 @@ describe 'Express'
it 'should return a well formatted fingerprint'
var fingerprint = facebook.getFingerprintForCookie('e1249f7d4bc25b8f90e5c9c7523e3ee1', validCookies)
- fingerprint.should.eql("expires=1267714800session_key=3.LIysipyTte6aXFBcStEixg__.3600.1267714800-687215451ss=lWYbyFp0GP8e7BgPa1aLDg__user=687215451")
+fingerprint.should.eql({fingerprint: "expires=1267714800session_key=3.LIysipyTte6aXFBcStEixg__.3600.1267714800-687215451ss=lWYbyFp0GP8e7BgPa1aLDg__user=687215451", sig: "e"})
end
end
Something went wrong with that request. Please try again.