Ember ♥ Facebook

Heather Brysiewicz / @caligoanimus

Outline

1. Initialize Facebook JavaScript SDK

2. Send Dialog Component

3. Authenticate Component

Preamble!

1. I am not a Facebook Expert (... who is?)

2. Buuut...? Because Facebook

Create an App in Facebook

Create an Ember App

1. Initialize Facebook JavaScript SDK

ember facebook components post

Initializers: allow you to run setup for your app

Examples: registering and injecting services such as sessions, google analytics & other third party SDKS


/* global FB */
export default {
  name: 'facebook',

  initialize: function() {
    var fbAsyncInit = function() {
      FB.init({
        appId      : "801296653273082",
        xfbml      : true,
        version    : 'v2.2'
      });
    };

    (function(d, s, id){
       var js, fjs = d.getElementsByTagName(s)[0];
       if (d.getElementById(id)) {return;}
       js = d.createElement(s); js.id = id;
       js.src = "//connect.facebook.net/en_US/sdk.js";
       fjs.parentNode.insertBefore(js, fjs);
     }(document, 'script', 'facebook-jssdk'));

    window.fbAsyncInit = fbAsyncInit;
  }
};
					

1. Initialize Facebook JavaScript SDK

2. Send Dialog Component

facebook docs - javascript sdk UI - send dialog


/* global FB */
import Ember from "ember";

export default Ember.Component.extend({
  actions: {
    invite: function() {
      FB.ui({
        method: "send",
        link: this.get("url"),
      });
    }
  }
});
					

facebook docs - javascript sdk UI reference

2. Send Dialog Component

3. Authenticate Component

facebook docs - javascript sdk UI - send dialog

Facebook says

1. Checking the login status to see if someone's already logged into your app.

2. If they are not logged in, invoke the login dialog and ask for a set of data permissions.

3. Verify their identity.

4. Store the resulting access token.

5. Make API calls.

6. Log out.


/* global FB */
import Ember from 'ember';

export default Ember.Component.extend({
  getLoginStatus: function() {
    return new Ember.RSVP.Promise(function(resolve, reject) {
      FB.getLoginStatus(function(response) {
        if (response.status) {
          resolve(response.status);
        } else {
          reject();
        }
      });
    });
  },

  getAccessToken: function() {
    return new Ember.RSVP.Promise(function(resolve, reject) {
      FB.login(function(response) {
        if (response.authResponse) {
          resolve(response.authResponse.accessToken);
        } else {
          reject(response);
        }
      }, { scope: 'email,user_birthday,publish_actions' });
    });
  },

  getAccountAttributes: function() {
    var self = this;

    return new Ember.RSVP.Promise(function(resolve, reject) {
      FB.api('/me', function(response) {
        if (!response || response.error || Ember.isEmpty(response.email)) {
          reject("An error occured or priveleges required to sign up were not granted.");
        } else {
          resolve(response);
        }
      }, { scope: 'email,user_birthday,publish_actions' });
    });
  },

  authenticate: function(accessToken) {
    var self = this;
    var token = Ember.$('meta[name="csrf-token"]').attr('content');

    return self.getAccountAttributes().then(function(accountAttributes) {
      return Ember.$.ajax({
        url: '/api/v1/session/oauth2/facebook/callback',
        data: {
          token: accessToken,
          account_attributes: accountAttributes
        },
        type: 'post',
        headers: { "X-CSRF-Token": token }
      });
    });
  },

  actions: {
    authorize: function() {
      var self = this;

      this.getLoginStatus().then(function() {
        self.getAccessToken().then(function(accessToken) {
          self.authenticate(accessToken).then(function(user) {
            self.sendAction('success', user);
          }, function(reason) {
            self.sendAction('failure', reason);
          });
        });
      });
    }
  }
});
					

  actions: {
    authorize: function() {
      var self = this;

      this.getLoginStatus().then(function() {
        self.getAccessToken().then(function(accessToken) {
          self.authenticate(accessToken).then(function(user) {
            self.sendAction('success', user);
          }, function(reason) {
            self.sendAction('failure', reason);
          });
        });
      });
    }
  }
					

Facebook says

1. Checking the login status to see if someone's already logged into your app.

2. If they are not logged in, invoke the login dialog and ask for a set of data permissions.

3. Verify their identity.

4. Store the resulting access token.

5. Make API calls.

6. Log out.

getLoginStatus()


getLoginStatus: function() {
  return new Ember.RSVP.Promise(function(resolve, reject) {
    FB.getLoginStatus(function(response) {
      if (response.status) {
        resolve(response.status);
      } else {
        reject();
      }
    });
  });
},
					

Facebook says

1. Checking the login status to see if someone's already logged into your app.

2. If they are not logged in, invoke the login dialog and ask for a set of data permissions.

3. Verify their identity.

4. Store the resulting access token.

5. Make API calls.

6. Log out.

getAccessToken()


getAccessToken: function() {
  return new Ember.RSVP.Promise(function(resolve, reject) {
    FB.login(function(response) {
      if (response.authResponse) {
        resolve(response.authResponse.accessToken);
      } else {
        reject(response);
      }
    }, { scope: 'email,user_birthday,publish_actions' });
  });
},
					

Facebook says

1. Checking the login status to see if someone's already logged into your app.

2. If they are not logged in, invoke the login dialog and ask for a set of data permissions.

3. Verify their identity.

4. Store the resulting access token.

5. Make API calls.

6. Log out.

authenticate()


authenticate: function(accessToken) {
  var self = this;

  return self.getAccountAttributes().then(function(accountAttributes) {
    return Ember.$.ajax({
      url: '/api/v1/session/oauth2/facebook/callback',
      data: {
        token: accessToken,
        account_attributes: accountAttributes
      },
      type: 'post'
    });
  });
},
					

getAccountAttributes()


getAccountAttributes: function() {
  var self = this;

  return new Ember.RSVP.Promise(function(resolve, reject) {
    FB.api('/me', function(response) {
      if (!response || response.error || Ember.isEmpty(response.email)) {
        reject("An error occured or priveleges required to sign up were not granted.");
      } else {
        resolve(response);
      }
    }, { scope: 'email,user_birthday,publish_actions' });
  });
},
					

Facebook says

1. Checking the login status to see if someone's already logged into your app.

2. If they are not logged in, invoke the login dialog and ask for a set of data permissions.

3. Verify their identity.

4. Store the resulting access token.

5. Make API calls.

6. Log out.

Facebook says

1. Checking the login status to see if someone's already logged into your app.

2. If they are not logged in, invoke the login dialog and ask for a set of data permissions.

3. Verify their identity.

4. Store the resulting access token.

4+. Request extended token on the server side

5. Make API calls.

6. Log out.

Extended Token

1. Last ~60 days

2. Publish Actions

3. Post to feed

Thoughts and Questions