Created
November 3, 2010 19:50
-
-
Save chanon/661597 to your computer and use it in GitHub Desktop.
Facebook iframe Canvas App Authentication in node.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var querystring = require("querystring"); | |
var base64ToString = function(str) { | |
return (new Buffer(str || "", "base64")).toString("ascii"); | |
}; | |
var base64UrlToString = function(str) { | |
return base64ToString( base64UrlToBase64(str) ); | |
}; | |
var base64UrlToBase64 = function(str) { | |
var paddingNeeded = (4- (str.length%4)); | |
for (var i = 0; i < paddingNeeded; i++) { | |
str = str + '='; | |
} | |
return str.replace(/\-/g, '+').replace(/_/g, '/') | |
}; | |
var getAuthorizeUrl = function() { | |
var oauth_url = 'https://www.facebook.com/dialog/oauth/?' | |
var options = { | |
client_id: YOUR_APP_ID, | |
redirect_uri: 'https://apps.facebook.com/YOUR_APP/', | |
scope: COMMA_SEPARATED_LIST_OF_PERMISSION_NAMES | |
}; | |
// for scope see https://developers.facebook.com/docs/authentication/permissions/ | |
// eg. it could be "publish_stream,email" | |
return oauth_url + querystring.stringify(options); | |
}; | |
app.get('/fb', function(req, res) { | |
var signed_request = req.param('signed_request'); | |
var parts = signed_request.split('.'); | |
var sig = base64UrlToBase64(parts[0]); | |
var payload = parts[1]; | |
var data = JSON.parse(base64UrlToString(payload)); | |
if (!data.user_id) { | |
// send over to authorize url | |
res.send("<script>window.top.location='" + getAuthorizeUrl() + "'</script>"); | |
} | |
else { | |
// lets verify | |
if (data.algorithm.toUpperCase() !== 'HMAC-SHA256') { | |
res.send('Unknown algorithm. Expected HMAC-SHA256'); | |
return; | |
} | |
var secret = YOUR_APP_SECRET; | |
var hmac = require('crypto').createHmac('sha256', secret); | |
hmac.update(payload); | |
var expected_sig = hmac.digest('base64'); | |
if (sig != expected_sig){ | |
console.log('expected [' + expected_sig + '] got [' + sig + ']'); | |
res.send('Hello, this is my app! you are CHEATING! .. expected [' + expected_sig + '] got [' + sig + ']'); | |
} | |
else { | |
res.send('Hello, this is my app! you passed verification and are ' + data.user_id); | |
} | |
} | |
}); |
So to explain, what it's doing: First it checks if there is a user_id in the signed_request. If there is no user_id, that means the user hasn't authorized the app. So we redirect them to the facebook authorization page so they can authorize our app. At the same time we send some permissions to that page through the "scope" option to request from the user.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Good question.
That should actually go in the part that I wrote "// send over to authorize url".
I just updated the code so there is a full example of how to do that (line 39).
The facebook docs here: https://developers.facebook.com/docs/authentication/canvas/ explain it under "2a. Redirect to OAuth Dialog upon page load". I'm just using 'getAuthorizeUrl()' the prepare the url server-side instead.
Not 100% sure if this addition works, might be typos.