× {{alert.msg}} Never ask again
Receive New Tutorials
GET IT FREE

An Overview of Ember Simple Auth

– {{showDate(postTime)}}

This article will cover the core concepts of how Ember Simple Auth works. Ember Simple Auth is a lightweight library used for session management, authentication, and authorization. This post is based on the Codementor Office Hours hosted by Marco Otte-Witte, the author of Ember Simple Auth.


Introduction

Ember Simple Auth is from Simplabs and it’s one of the most popular Ember libraries. The three most important things Ember Simple Auth does are:

1. Maintaining Sessions
2. Authentication
3. Authorization

Maintaining Sessions

Maintaining sessions is the most important thing about Ember Simple Auth, because in the context of traditional web applications, you always have to have that server session as well as the session cookie that remembers that session. You don’t have that in Ember applications, but you need to have it whether the session is authenticated or not.

{{#if session.isAuthenticated}}
	<a {{ action ‘invalidateSession’ }}>Logout</a>
{{else}}
	{{#link-to ‘login’}}Login{{/link-to}}
{{/if}}

The Ember Simple Auth library maintains the client-side session inside of your Ember app and the session is quite simple. There are templates for doing things such as showing the logout link if the session is authenticated, and showing the login page if it is not authenticated.

Ember.Controller.extend({
	actions: {
		authenticate: function() {
			this.get(‘session’).authenticate(
				‘authenticator:some’,
				{ /*credentials*/}
			);
		}
	}
});

This is also accessible in all routes, controllers and components. In a controller or a component, you can authenticate the session.

In addition, the session is synced between tabs and windows . Suppose you have two tabs of the same application open where you’re logged in for both. If you log out in one tab, the session’s still accessible because you still have all the data in the memory in the second tab of that client-side application. However, you would expect that as soon as you log out of that application, that data is protected. That’s why the library syncs the session state between tabs and windows.

You can see, I’m logged into two tabs. Then I log out of one of them, and you can see I’m logged out of both tabs. And now I log in again and you see I’m logged in in both tabs.

It’s basically a security feature where it makes sure that as soon as you log out that all the tabs are logged out and by default, Simple Auth will reload the page so that all the memory data gets destroyed and nothing is maintained in the other tabs or windows that people would then be able to access although they should be out because you have logged out already.

Authentication

The second thing that the library does is offering mechanisms to actually authenticate that session.

Ember.Controller.extend({
	action: {
		authenticate: function() {
			var credentials = this.getProperties(
				'identification', 'password'
			);
			this.get('session').authenticate(
				'simple-auth-authenticator:oauth2-password-grant',
				credentials
			);
		}
	}
});

The session can be authenticated in any way that’s suitable for your application, and you do that by choosing from a set of authentication strategies based on the application and how you want the actual authentication to work.

OAuth

For example, you can be using OAuth 2.0, or specifically one specific grant type out of that specification.

Ember.Controller.extend({
	action: {
		authenticate: function() {
			var credentials = this.getProperties(
				'identification', 'password'
			);
			this.get('session').authenticate(
				'simple-auth-authenticator:oauth2-password-grant'
				credentials
			);
		}
	}
}); 

simple-auth-authenticator:oauth2-password-grant is a very simple grant that’s just a specification of sending a user identification and password to the server, and then in return the server would respond if those credentials are valid.

Devise

There is also an authenticator for Devise, which is a popular Rails authentication gem.

Ember.Controller.extend({
	action: {
		authenticate: function() {
			var credentials = this.getProperties(
				'identification’, ‘password’
			);
			this.get('session').authenticate(
				'simple-auth-authenticator:devise',
				credentials
			);
		}
	}
});

This code works more or less the same way as it does with Oauth, but instead of saying you want to authenticate the sessions with that OAuth 2.0 authenticator, you’re using the Simple Auth authenticator Devise authenticator.

Torii

The authenticator for Torii, which is a library for interfacing with external authentication providers such as Facebook and Google+.

Ember.Controller.extend({
	action: {
		authenticate: function() {
			this.get('session').authenticate(
				'simple-auth-authenticator:torii',
				'facebook-oauth2'
			);
		}
	}
}); 

So, instead of specifying credentials, you’d be specifying the torii provider you want to use. This will then open a new window. In that case, it would be a Facebook window where you enter your Facebook credentials. If those are valid, then it returns it. From a session perspective, it’s the same mechanism.

It’s very easy to implement your own authenticator with Ember Simple Auth. You just need to implement three methods, and all the information you need for that is in this README file. In addition, there are several blog posts on the web where you can find detailed instructions for how to implement your own authenticator mechanism.

Authorization

Authentication is used when you’re unsure that the user is who he pretends to be, and authorization is used when you’re determining whether that the user is allowed to do something that he requests to do.

In the context of a JavaScript application, authentication is logging in and authorization is adding something to the request to the API server if you have one. If you don’t have one, you don’t have authorization. In the case that you have an API server, you need to add something to your outgoing requests that the API can then use to determine whether the request is actually allowed or not.

The library authorizes requests and that is implanted by a strategy where you can choose from that set of strategies and pick one that makes sense for your application.

Authorization: Bearer <access_token>

For example, OAuth 2.0 again, or specifically bearer tokens where it just adds a bearer token header to outgoing requests using that same header that has previously been acquired by the authenticator.

Authorization: Token token="<token>", email="<email>"

There is also an authorization for devise, which is the authorization header as well, but the request payload looks a bit different. There’s a simple way to implement your own authorizers as well, so you don’t have to use the authorization header.

When the session is authenticated, you use the authentication information to authorize outgoing directives. During the lifetime of the session, you have a number of events that happen.

sessionAuthenticationSucceeded
sessionAuthenticationFailed
authorizationFailed 

For example, if the session authentication succeeded, maybe your application would want to respond to the event that someone has successfully logged in. If the session authentication failed, maybe your app will want to display something. Furthermore, an authorization failed event gets raised when a request fails and the API returns a 401 error, which means that the user is not authorized to make certain requests. In that case, a Simple Auth would invalidate the session and would effectively log the user out, because the assumption is that when a 401 error happens that the session has somehow expired.

Mixins for Convenience

Ember Simple Auth library defines a set of mixins that make your life a little easier when using all these things like sessions, session events, and authenticators.

App.ApplicationRoute = Ember.Route.extend(
	SimpleAuth.ApplicationRouteMixin
	);

For example, there is the application route mixin that would convert all session events into actions, which are then handled automatically via the ApplicationRouteMixin in the ApplicationRoute.

App.ProtectedRoute = Ember.Route.extend(
	SimpleAuth.AuthenticatedRouteMixin
);

This mixin makes sure the route is only accessible when the session is authenticated. The authenticated route mixin checks in the route if the session is authenticated, and if not, it just redirects the user to the configured login route.

 App.LoginRoute = Ember.Route.extend(
	SimpleAuth.UnauthenticatedRouteMixin
); 

The unauthenticated route mixin makes sure that the session can only be accessed when the session is not authentic. This is useful for the login route when you don’t want people to visit that route if they are already authenticated, because there’s nothing they could do there. By default this just redirects users to the index page.

Demo

As you can see from the demo, if I’m logged in, I can visit a protected page. If I log out, I go back to the start page. If I’m not logged in, I’d see that login button. When I try to access the login route, I’m redirected to the login route, and as soon as I login then the previously transition to the protected route is then retried and of course that works because now the session is authenticated.

So, if we look at the code of the app, you can see it is a one-page application with a simple layout with a home link and the link to the protected page.

      // use the provided mixins in the application route and login controller
      App.ApplicationRoute = Ember.Route.extend(SimpleAuth.ApplicationRouteMixin, {
        actions: {
          invalidateSession: function() {
            this.get('session').invalidate();
          }
        }
      });

From this part of the code, you can see that it uses the globalized distribution of Simple Auth, which exports that Simple Auth global. However, this is just an example – in real life you would (hopefully) use Ember CLI.

{{if session.isAuthenticated}}
	<a {{ action 'invalidateSession'}} class-"btn btn-danger navbar-btn nabber-right">Logout</a>
{{else}}
	{{#link-to 'login' class="btn btn-success navbar-btn navbar-right"}}Login{{/link-to}}
{{/if}} 

Depending on whether the session is authenticated, the user would see a button that triggers the invalidate session action. If it’s not authenticated, the login link goes to the login route.

      App.Router.map(function() {
        // login route
        this.route('login');
        // protected route that's inaccessible without authentication
        this.route('protected');
      });

We define the route with the login route and protected route with the code above.

      // use the provided mixins in the application route and login controller
      App.ApplicationRoute = Ember.Route.extend(SimpleAuth.ApplicationRouteMixin, {
        actions: {
          invalidateSession: function() {
            this.get('session').invalidate();
          }
        }
      });

The application route mixin also defines the invalidated session action that we saw in the template above with invalidateSession: function() {.

          {{! display logout button when the session is authenticated, login button otherwise }}
          {{#if session.isAuthenticated}}
            Logout
          {{else}}
            {{#link-to 'login' class="btn btn-success navbar-btn navbar-right"}}Login{{/link-to}}
          {{/if}}

When the session is authenticated, we display the logout link and that places the invalidate session action – the implementation is really simple. You just get the session, call the session invalidate method, and that will invalidate the session and the user is logged out.

      App.LoginController = Ember.Controller.extend({
        actions: {
          authenticate: function() {
            var credentials = this.getProperties('identification', 'password');
            this.get('session').authenticate('simple-auth-authenticator:oauth2-password-grant', credentials);
          }
        }
      });

As we saw above in the login template, if users submit the login form they’d be using the authenticate action implemented in the code above. The login controller gets the credentials and the values for identification and password input. And then we call the this.get('session').authenticate method with an OAuth 2.0 authenticator to pass the credentials.

      // make this route protected
      App.ProtectedRoute = Ember.Route.extend(SimpleAuth.AuthenticatedRouteMixin);
      // make the login route only accessible when the session is not authenticated
      App.LoginRoute = Ember.Route.extend(SimpleAuth.UnauthenticatedRouteMixin);

Finally, we have the protected route. As long as the session is not authenticated, it will not be accessible. This is done by mixing in that AuthenticatedRouteMixin. When the session is authenticated, I should not be able to access the login route, which is achieved by adding the UnauthenticatedRouteMixin to the login route.

How to Get Started with Ember Simple Auth

Naturally, you should read the extensive README – I took a lot of time writing that! There’s a step by step guide on how to set things up.

However, the best way to start is to just use the Simple Auth’s OAuth 2.0 flow, because that really works great out-of-the-box and there’s a lot of middle-ware available for various service decks such as Rails, PHP, and Java. There are hundreds of middle-wares usable on the server-side as well, so Ember Simple Auth is really a solution that works with most existing applications. There are also some videos on YouTube, and if you google a bit you will find various blog posts on how to set a project up with Simple Auth.

 >>Q&A: Ember Simple Auth vs. Torii, Bearer Tokens, and Why Marco Chose Ember over AngulaJS




Questions about this tutorial?  Get Live 1:1 help from Ember.js experts!
Dean Levinson
Dean Levinson
Node.js developer with 8 years of experience
I work for a company that provides a subscription based embedded hardware product for screen mirroring / classroom collaboration. We provide an app...
Hire this Expert
Victor Kane
Victor Kane
4.9
Seasoned Full Stack Web App Engineer & Architect. Lean Agile Project & Team Mentor.
FullStack (Process Engineering = Lean UX && Agile && Kanban && UML, Devops = true) => { (React && Redux || Vue && Vuex && Nuxt.js && Vuetify) &&...
Hire this Expert
comments powered by Disqus