diff --git a/README.md b/README.md index b577e5c..9321012 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,28 @@ server.exchange(oauth2orizeFacebook(function (client, profile, scope, cb) { })); ``` + +## Options + +**requiredScopes** + +Required scopes allows the exchange middleware to throw an error if the user does not allow a permission required for the application to work. +The requiredScopes are specified within the options (`opts`) object. + +```js +// ... + +server.exchange( + oauth2orizeFacebook( + { + requiredScopes: ['scope1', 'scope2'] + }, + function (client, profile, scope, cb) { + // ... + } + ) +); +``` ## License MIT licensed. diff --git a/lib/index.js b/lib/index.js index 132117e..bfdc9ea 100644 --- a/lib/index.js +++ b/lib/index.js @@ -20,6 +20,15 @@ module.exports = function (opts, issue) { var userProperty = opts.userProperty || 'user'; var separators = opts.scopeSeparator || ' '; + var requiredScopes = opts.requiredScopes || []; + + if (!Array.isArray(requiredScopes)) { + if (typeof(requiredScopes) === 'string') { + requiredScopes = [ requiredScopes ]; + } else { + requiredScopes = []; + } + } if (!Array.isArray(separators)) { separators = [ separators ]; @@ -43,10 +52,10 @@ module.exports = function (opts, issue) { 'Missing Facebook access token!', 'invalid_request')); } - getFacebookProfile(token, function (err, profile) { + getFacebookProfile(token, requiredScopes, function (err, profile) { if (err) { return next(new AuthorizationError( - 'Could not get Facebook profile using provided access token.', + err.message || 'Could not get Facebook profile using provided access token.', 'invalid_request' )); } diff --git a/lib/util.js b/lib/util.js index d63956a..0d533b9 100644 --- a/lib/util.js +++ b/lib/util.js @@ -2,7 +2,7 @@ var request = require('request'); -exports.getFacebookProfile = function (accessToken, cb) { +exports.getFacebookProfile = function (accessToken, requiredScopes, cb) { request({ url: 'https://graph.facebook.com/me?access_token=' + accessToken, json: true @@ -17,6 +17,51 @@ exports.getFacebookProfile = function (accessToken, cb) { return cb(new Error(msg)); } - cb(null, body); + if (requiredScopes.length === 0) { + return cb(null, body); + } + + getFacebookPermissions(accessToken, function(err, scopes) { + var grantedScopes = []; + + for (var index in scopes) { + if (scopes.hasOwnProperty(index)) { + var scope = scopes[index]; + + if (scope.status === 'granted') { + grantedScopes.push(scope.permission); + } + } + } + + for (var index in requiredScopes) { + if (requiredScopes.hasOwnProperty(index)) { + var rScope = requiredScopes[index]; + if (grantedScopes.indexOf(rScope) === -1) { + var msg = 'Facebook profile authorization has insufficient scopes'; + return cb(new Error(msg)); + } + } + } + cb(null, body); + }); + }; + +getFacebookPermissions = function(accessToken, cb) { + request({ + url: 'https://graph.facebook.com/me/permissions?access_token=' + accessToken, + json: true + }, + function (err, res, body) { + if (err) { + return cb(err); + } + + if (body && body.error) { + var msg = body.error.message || 'Could not get Facebook profile permissions.'; + return cb(new Error(msg)); + } + + cb(null, body.data); }); -}; +} \ No newline at end of file