Simple Third-Party Authentication in Ember with Firebase

08 March, 2016
post-banner

User authentication is almost always a vital feature in any modern Ember app. This is usually a difficult and time-consuming thing to implement, but is made really simple using Firebase.

In my last post on Firebase I talked about how easy it is to setup a Firebase backend and database for Ember apps. In this article I'm going to extend on the books example project I used before, and implement third-party user authentication using the EmberFire adapter. Using this we can allow users to sign in to our app with their Twitter, Facebook, Google, or GitHub accounts.

Prerequisites

To get started, you will need an Ember-CLI app configured with the Firebase adapter. If you are starting from scratch, you can check out my previous post on building Ember Data apps with Firebase. This article also assumes a basic understanding of the Ember framework.

The code for this tutorial is available at https://github.com/danielgynn/flint-books.

Install Torii

To be able to add user authentication to an EmberFire app, we need to install Torii, and configure a torii provider. Torii is 'a set of clean abstractions for authentication in Ember.js applications'. We can use it for managing the session of the current user in the application.

$ ember install torii

Once the Torii adapter has been installed, we can configure the session service into the config/environment.js file to hold the current user. This will allow all of the routes in the app to access the session property.

// config/environment.js
...
firebase: 'https://<APP-NAME>.firebaseio.com/',  
torii: {  
  sessionServiceName: 'session',
},
...

Now we need to create a Torii-adapter file to inject the ToriiFirebaseAdapter across the whole application. We can do this at app/torii-adapters/application.js.

// app/torii-adapters/application.js
import Ember from 'ember';  
import ToriiFirebaseAdapter from 'emberfire/torii-adapters/firebase';

export default ToriiFirebaseAdapter.extend({  
  firebase: Ember.inject.service(),
});

Enable Third-Party Services

To be able to use third-party services to authenticate our users, we'll need to enable the provider to generate the ID and secret key for our app. Once we generated these keys for each service, we can simply click 'enable authentication' and copy them into the Firebase dashboard.

This is done a little differently for each third-party service, so you can check out the Firebase documentation for authentication if you need a little more help. All of the services require you to have a verified account.

Facebook

For Facebook, we must create a new web app by heading to the Facebook developer API. The app must be given a name, and we can skip 'Quick Start' to access our keys and copy them into Firebase. A Facebook app also requires a callback URL, https://auth.firebase.com/v2/<YOUR-FIREBASE-APP>/auth/facebook/callback, to be configured in the Settings on the Advanced tab.

Twitter

For Twitter, just head to Twitter apps, create a new app and fill out the required details. The callback URL should be set to https://auth.firebase.com/v2/<YOUR-FIREBASE-APP>/auth/twitter/callback. We can then copy across the API key and API secret to Firebase.

GitHub

You can register a new GitHub application here to be able to authenticate using a GitHub account. Simply fill out the required details, and set the callback URL to https://auth.firebase.com/v2/<YOUR-FIREBASE-APP>/auth/github/callback. Once this has been successfully registered, you can copy across your Client ID and Client Secret to the Firebase dashboard.

Google

To register a new Google project, navigate to the developer dashboard and 'Create a project'. Fill out the name and ID of the project and then navigate to the 'Credentials' section of the API manager dashboard. From here you can create an OAuth client ID and follow the steps to finish. You will be asked to set Authorized JavaScript Origins to https://auth.firebase.com and the Authorized Redirect URI to https://auth.firebase.com/v2/<YOUR-FIREBASE-APP>/auth/google/callback. You will then, finally, be able to copy across the Client ID and Client Secret to Firebase.

Setup Sign In/Out Actions

To implement user authentication in out app, we'll need to define actions for signing in and out. We can do this on the application route with the injected session property.

// app/routes/application.js
import Ember from 'ember';

export default Ember.Route.extend({  
  beforeModel: function() {
    return this.get('session').fetch().catch(function() {
    });
  },

  actions: {
    ...
  },
});

What we are doing here is simply using the beforeModel hook to fetch the session on the application route to be able to be used in the actions.

// app/routes/application.js
...
actions: {  
    signIn: function(provider) {
      this.get('session').open('firebase', {
        provider: provider,
      }).then(function(data) {
        console.log(data.currentUser);
      });
    },

    signOut: function() {
      this.get('session').close();
    },
},
...

The signIn action simply opens up a Firebase session and passes in the third-party provider we want to authenticate with. We will be able to define what provider to use when calling the actions in our templates later on.

The signOut action then simply closes the session once the user has clicked our 'Sign Out' button.

Implement Actions on the Templates

Now that the actions have been defined, we can call them in a template to allow a user to be authenticated using a provider. To do this, we can create a button or link and use an Ember action. The action in the template will call the signIn action, and we can pass in the service we want as the provider parameter.

<!-- app/templates/index.hbs -->

<a {{action "signIn" "facebook"}} class="btn">{{fa-icon "facebook"}}</a>  
<a {{action "signIn" "twitter"}} class="btn">{{fa-icon "twitter"}}</a>  
<a {{action "signIn" "github"}} class="btn">{{fa-icon "github"}}</a>  
<a {{action "signIn" "google"}} class="btn">{{fa-icon "google"}}</a>  

This will render four links with icons for each service to allow a user to authenticate with their chosen service. When a button is clicked, a pop-up window will be displayed to allow you to log in with Google, for instance, and a new session will be started.

Once a user is authenticated, we can show that this has worked by displaying a 'logged in' message on the screen. We will also have a log out link, to allow the user to end their session.

<!-- app/templates/index.hbs -->

{{#if session.isAuthenticated}}
    <span>Currently logged in as {{session.currentUser.displayName}} with 
    {{session.provider}} - <a {{action "signOut"}}>Sign out</a></span>
{{/if}}

We can go a step further and only allow the user to interact with the app if they are authenticated. using the {{#if session.isAuthenticated}} helper, we are able to control what a user is able to do when they are logged in or out of the app.

{{#if session.isAuthenticated}}
   {{outlet}}
{{else}}
   {{partial "index"}}
{{/if}}

When the user is authenticated, the current template will be rendered inside of the application's {{outlet}}.

So now if we tried to navigate to around the app while still unauthenticated, we'd be displayed with the 'Please log in to continue' message, instead of being shown the selected route's template.

You should now have a working Ember app, complete with third-party authentication. This simple solution is great because it will allow you to spend more time working on what your app is actually supposed to do.


You can check out the whole example project on a repository here.

If you liked this post, you can check out some of my other posts on Ember.js and Firebase on my blog.

comments powered by Disqus