+
+ First, you'll need to register your app on Facebook. Follow these steps:
+
+
+ -
+ Visit https://developers.facebook.com/apps
+
+ -
+ Click "Add a New App".
+
+ -
+ Select "Website" and type a name for your app.
+
+ -
+ Click "Create New Facebook App ID".
+
+ -
+ Select a category in the dropdown and click "Create App ID".
+
+ -
+ Under "Tell us about your website", set Site URL to: {{siteUrl}} and click "Next".
+
+ -
+ Click "Skip to Developer Dashboard".
+
+ -
+ Go to the "Settings" tab and add an email address under "Contact Email". Click "Save Changes".
+
+ -
+ Go to the "Status & Review" tab and select Yes for "Do you want to make this app and
+ all its live features available to the general public?". Click "Confirm".
+
+ -
+ Go back to the Dashboard tab.
+
+
+
diff --git a/packages/facebook/facebook_configure.js b/packages/facebook/facebook_configure.js
new file mode 100755
index 00000000..412ee505
--- /dev/null
+++ b/packages/facebook/facebook_configure.js
@@ -0,0 +1,12 @@
+Template.configureLoginServiceDialogForFacebook.helpers({
+ siteUrl: function () {
+ return Meteor.absoluteUrl();
+ }
+});
+
+Template.configureLoginServiceDialogForFacebook.fields = function () {
+ return [
+ {property: 'appId', label: 'App ID'},
+ {property: 'secret', label: 'App Secret'}
+ ];
+};
diff --git a/packages/facebook/facebook_server.js b/packages/facebook/facebook_server.js
new file mode 100755
index 00000000..c30eb575
--- /dev/null
+++ b/packages/facebook/facebook_server.js
@@ -0,0 +1,95 @@
+Facebook = {};
+
+OAuth.registerService('facebook', 2, null, function(query) {
+
+ var response = getTokenResponse(query);
+ var accessToken = response.accessToken;
+
+ // include all fields from facebook
+ // http://developers.facebook.com/docs/reference/login/public-profile-and-friend-list/
+ var whitelisted = ['id', 'email', 'name', 'first_name',
+ 'last_name', 'link', 'gender', 'locale', 'age_range'];
+
+ var identity = getIdentity(accessToken, whitelisted);
+
+ var serviceData = {
+ accessToken: accessToken,
+ expiresAt: (+new Date) + (1000 * response.expiresIn)
+ };
+
+
+ var fields = _.pick(identity, whitelisted);
+ _.extend(serviceData, fields);
+
+ return {
+ serviceData: serviceData,
+ options: {profile: {name: identity.name}}
+ };
+});
+
+// checks whether a string parses as JSON
+var isJSON = function (str) {
+ try {
+ JSON.parse(str);
+ return true;
+ } catch (e) {
+ return false;
+ }
+};
+
+// returns an object containing:
+// - accessToken
+// - expiresIn: lifetime of token in seconds
+var getTokenResponse = function (query) {
+ var config = ServiceConfiguration.configurations.findOne({service: 'facebook'});
+ if (!config)
+ throw new ServiceConfiguration.ConfigError();
+
+ var responseContent;
+ try {
+ // Request an access token
+ responseContent = HTTP.get(
+ "https://graph.facebook.com/v2.8/oauth/access_token", {
+ params: {
+ client_id: config.appId,
+ redirect_uri: OAuth._redirectUri('facebook', config),
+ client_secret: OAuth.openSecret(config.secret),
+ code: query.code
+ }
+ }).data;
+ } catch (err) {
+ throw _.extend(new Error("Failed to complete OAuth handshake with Facebook. " + err.message),
+ {response: err.response});
+ }
+
+ // Handle response
+ var fbAccessToken = responseContent.access_token;
+ var fbExpires = responseContent.expires_in;
+
+ if (!fbAccessToken) {
+ throw new Error("Failed to complete OAuth handshake with facebook " +
+ "-- can't find access token in HTTP response. " + responseContent);
+ }
+ return {
+ accessToken: fbAccessToken,
+ expiresIn: fbExpires
+ };
+};
+
+var getIdentity = function (accessToken, fields) {
+ try {
+ return HTTP.get("https://graph.facebook.com/v2.8/me", {
+ params: {
+ access_token: accessToken,
+ fields: fields.join(",")
+ }
+ }).data;
+ } catch (err) {
+ throw _.extend(new Error("Failed to fetch identity from Facebook. " + err.message),
+ {response: err.response});
+ }
+};
+
+Facebook.retrieveCredential = function(credentialToken, credentialSecret) {
+ return OAuth.retrieveCredential(credentialToken, credentialSecret);
+};
diff --git a/packages/facebook/package.js b/packages/facebook/package.js
new file mode 100755
index 00000000..0698dadd
--- /dev/null
+++ b/packages/facebook/package.js
@@ -0,0 +1,23 @@
+Package.describe({
+ summary: "Facebook OAuth flow",
+ version: "1.2.2"
+});
+
+Package.onUse(function(api) {
+ api.use('oauth2', ['client', 'server']);
+ api.use('oauth', ['client', 'server']);
+ api.use('http', ['server']);
+ api.use('templating', 'client');
+ api.use('underscore', 'server');
+ api.use('random', 'client');
+ api.use('service-configuration', ['client', 'server']);
+
+ api.export('Facebook');
+
+ api.addFiles(
+ ['facebook_configure.html', 'facebook_configure.js'],
+ 'client');
+
+ api.addFiles('facebook_server.js', 'server');
+ api.addFiles('facebook_client.js', 'client');
+});
diff --git a/private/config.json.template b/private/config.json.template
index 51a57dae..573b8932 100644
--- a/private/config.json.template
+++ b/private/config.json.template
@@ -22,5 +22,5 @@
"queueEnabled": true,
"expirationDelay": 1800000
},
- "defaultMentor": true
+ "defaultMentor": false
}