Recently I’ve setup an ember project and I needed authentication. There is an excellent library / cli plug-in called ember-simple-auth. While the guides are great, the most recent version of Ember(1.13 / 2) doesn’t play nicely with the latest ember-simple-auth.

Ember-Simple-Auth, provides a special branch called jjAbrams (PR 602). While it is an awesome library, getting it to work can be somewhat tricky as not everything is as documented and requires some tweaks here and there. I’m trying to outline what I did, in the hopes it will save time for many others. And help prevent other devs from banging their heads against their keyboards, posting issues on git repositories or irc channels, or reading simple-auth source code to understand why things don’t work they way they are suppose to (as I did) in the hopes of understanding why things don’t work. Especially if you’re running against a custom server, like I did.

Here are the steps to get it working.

<

ul class=”regular”>

First create an ember app using ember-cli ember new app-name 1 ember new app - name

Then follow the instructions on ember-simple-auth, how to get this specials build. It’s rather simple but still you need to make sure you don’t have any of the ember-simple-auth / simple-auth packages in your package.json / bower.json and also delete them from your node_modules / bower_components directories. Here is the pull request for it (make sure to read it as it explain how to get setup). https://github.com/simplabs/ember-simple-auth/pull/602

<li>Next create an application route (if you don't have one). open the command prompt and type: 1 2 < li > Next create an application route ( if you don ' t have one ) . open the command prompt and type :

ember g route application 1 ember g route application

<li>Then add the application route mixin to the route: 1 2 < li > Then add the application route mixin to the route :

// app/routes/application.js import ApplicationRouteMixin from 'ember-simple-auth/mixins/application-route-mixin'; export default Ember.Route.extend(ApplicationRouteMixin,{ ... rest of application route code }); 1 2 3 4 5 6 // app/routes/application.js import ApplicationRouteMixin from 'ember-simple-auth/mixins/application-route-mixin' ; export default Ember . Route . extend ( ApplicationRouteMixin , { . . . rest of application route code } ) ;

Next add a Login page and login controller and a protected page (notice I’m not using the LoginMixin as in many of Ember-Auth examples as it states it’s deprecated and I’ve also chosen not to use the Unauthenticated mixin (just because I’d rather leave that always accessible). ember g route login ember g controller login ember g route protected 1 2 3 4 ember g route login ember g controller login ember g route protected

edit the login controller file: import Ember from 'ember'; // app/controllers/login.js export default Ember.Controller.extend({ session: Ember.inject.service('session'), actions: { // called when the login button is pressed // will authenticate agains the ember-simple-auth authentication infrastructur authenticate: function() { this.set('errorText',null); //in case your want to display an error var creditionals = {}; var that = this; creditionals.identification = this.get('model.identification'); creditionals.password = this.get('model.password'); new Ember.RSVP.Promise(function (resolve,reject) { return (that.get('session.isAuthenticated')) ? that.get('session').invalidate() : resolve(true); }) //first invalidate, so we clear past data. .then (function () { return that.get('session').authenticate('authenticator:custom',creditionals); }) .then(function authSuccess() { // this hook is not automatically called, and seemed to have change, so I just trigger the action myself. that.send('sessionAuthenticationSucceeded'); },function authFailed() { that.set('errorText','Login Failed!'); }); } } }); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 import Ember from 'ember' ; // app/controllers/login.js export default Ember . Controller . extend ( { session : Ember . inject . service ( 'session' ) , actions : { // called when the login button is pressed // will authenticate agains the ember-simple-auth authentication infrastructur authenticate : function ( ) { this . set ( 'errorText' , null ) ; //in case your want to display an error var creditionals = { } ; var that = this ; creditionals . identification = this . get ( 'model.identification' ) ; creditionals . password = this . get ( 'model.password' ) ; new Ember . RSVP . Promise ( function ( resolve , reject ) { return ( that . get ( 'session.isAuthenticated' ) ) ? that . get ( 'session' ) . invalidate ( ) : resolve ( true ) ; } ) //first invalidate, so we clear past data. . then ( function ( ) { return that . get ( 'session' ) . authenticate ( 'authenticator:custom' , creditionals ) ; } ) . then ( function authSuccess ( ) { // this hook is not automatically called, and seemed to have change, so I just trigger the action myself. that . send ( 'sessionAuthenticationSucceeded' ) ; } , function authFailed ( ) { that . set ( 'errorText' , 'Login Failed!' ) ; } ) ; } } } ) ; and the protected page route // app/routes/protected.js import Ember from 'ember'; import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin'; export default Ember.Route.extend(AuthenticatedRouteMixin,{ }); 1 2 3 4 5 6 7 8 9 10 // app/routes/protected.js import Ember from 'ember' ; import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin' ; export default Ember . Route . extend ( AuthenticatedRouteMixin , { } ) ; then edit the login template (I have some bootstrap styling here) <div class="container"> <div id="loginbox" class="mainbox col-md-6 col-md-offset-3 col-sm-6 col-sm-offset-3"> <div class="panel panel-default" > <div class="panel-heading"> <div class="panel-title text-center"><img class="logo_image" src="/images/logo.png" /> </div> </div> <div class="panel-body" > <form name="form" id="form" class="form-horizontal"> <div class="input-group"> <span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span> {{input value=model.identification class="form-control" placeholder='Enter Login'}} </div> <div class="input-group"> <span class="input-group-addon"><i class="glyphicon glyphicon-lock"></i></span> {{input value=model.password class="form-control" placeholder='Enter Password' type='password'}} </div> <div class="form-group"> <!-- Button --> <div class="col-sm-12 controls"> <button {{action "authenticate"}} class="btn btn-primary pull-right"><i class="glyphicon glyphicon-log-in"></i> Log in</button> </div> </div> <div class="form-group"> <div class="col-sm-12 controls"> {{errorText}} </div> </div> </form> </div> </div> </div> </div> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 < div class = "container" > < div id = "loginbox" class = "mainbox col-md-6 col-md-offset-3 col-sm-6 col-sm-offset-3" > < div class = "panel panel-default" > < div class = "panel-heading" > < div class = "panel-title text-center" > < img class = "logo_image" src = "/images/logo.png" / > < / div > < / div > < div class = "panel-body" > < form name = "form" id = "form" class = "form-horizontal" > < div class = "input-group" > < span class = "input-group-addon" > < i class = "glyphicon glyphicon-user" > < / i > < / span > { { input value = model . identification class = "form-control" placeholder = 'Enter Login' } } < / div > < div class = "input-group" > < span class = "input-group-addon" > < i class = "glyphicon glyphicon-lock" > < / i > < / span > { { input value = model . password class = "form-control" placeholder = 'Enter Password' type = 'password' } } < / div > < div class = "form-group" > < ! -- Button -- > < div class = "col-sm-12 controls" > < button { { action "authenticate" } } class = "btn btn-primary pull-right" > < i class = "glyphicon glyphicon-log-in" > < / i > Log in < / button > < / div > < / div > < div class = "form-group" > < div class = "col-sm-12 controls" > { { errorText } } < / div > < / div > < / form > < / div > < / div > < / div > < / div >

Next create an authenticators directory and an custom.js (authenticates login requests and restores session on refresh)

Notice I use the same name everywhere (access_token) as once you resolve when authenticating it stores all the info in the session. //app/authentiactors/custom.js import Ember from 'ember'; import Base from 'ember-simple-auth/authenticators/base'; export default Base.extend({ restore: function(data) { return new Ember.RSVP.Promise(function(resolve, reject) { if (!Ember.isEmpty(data.access_token)) { resolve(data); } else { reject(); } }); }, authenticate: function(credentials) { return new Ember.RSVP.Promise(function (resolve, reject) { // make the request to authenticate the user at /authpath endpoint. Ember.$.ajax({ url: '/authpath', type: 'POST', contentType : 'application/json', dataType : 'json', data: JSON.stringify({"email":credentials.identification,"password":credentials.password}), }).then(function (response) { resolve({ access_token: response.token, account_id: response.id }); //saving to the session. }, function (xhr, status, error) { reject(xhr.responseText); }); }); }, invalidate: function(data) { return new Ember.RSVP.resolve(true); //does nothing for now, you should add code for this to work. (clear the session, send a logout to the server) } }); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 //app/authentiactors/custom.js import Ember from 'ember' ; import Base from 'ember-simple-auth/authenticators/base' ; export default Base . extend ( { restore : function ( data ) { return new Ember . RSVP . Promise ( function ( resolve , reject ) { if ( ! Ember . isEmpty ( data . access_token ) ) { resolve ( data ) ; } else { reject ( ) ; } } ) ; } , authenticate : function ( credentials ) { return new Ember . RSVP . Promise ( function ( resolve , reject ) { // make the request to authenticate the user at /authpath endpoint. Ember . $ . ajax ( { url : '/authpath' , type : 'POST' , contentType : 'application/json' , dataType : 'json' , data : JSON . stringify ( { "email" : credentials . identification , "password" : credentials . password } ) , } ) . then ( function ( response ) { resolve ( { access_token : response . token , account_id : response . id } ) ; //saving to the session. } , function ( xhr , status , error ) { reject ( xhr . responseText ) ; } ) ; } ) ; } , invalidate : function ( data ) { return new Ember . RSVP . resolve ( true ) ; //does nothing for now, you should add code for this to work. (clear the session, send a logout to the server) } } ) ;

Then add an initializer for the authenticator

ember g initializer custom-authenticator 1 ember g initializer custom - authenticator

and the file itself: import CustomAuthenticator from '../authenticators/custom'; export function initialize(container, application) { application.register('authenticator:custom', CustomAuthenticator); } export default { before: 'ember-simple-auth', name: 'custom-authenticator', initialize: initialize }; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 import CustomAuthenticator from '../authenticators/custom' ; export function initialize ( container , application ) { application . register ( 'authenticator:custom' , CustomAuthenticator ) ; } export default { before : 'ember-simple-auth' , name : 'custom-authenticator' , initialize : initialize } ;

And now create an authorizers directory and a custom authorizer

Notice that the info is is accessible via that.get(‘session.authentication’) (not session.secure as in other documentation!).. // app/authorizers/custom.js import Ember from 'ember'; import Base from 'ember-simple-auth/authorizers/base'; export default Base.extend({ //notice the change, it will add an authorization header, in this case I'm using basic http authentication. authorize: function(addHeaderFunction, requestOptions) { if (this.get('session.isAuthenticated') && !Ember.isEmpty(this.get('session.authenticated.access_token'))) { var basicHTTPToken = btoa(this.get('session.authenticated.account_id') + ":" + this.get('session.authenticated.access_token')); addHeaderFunction('Authorization', 'Basic ' + basicHTTPToken); } } }); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 // app/authorizers/custom.js import Ember from 'ember' ; import Base from 'ember-simple-auth/authorizers/base' ; export default Base . extend ( { //notice the change, it will add an authorization header, in this case I'm using basic http authentication. authorize : function ( addHeaderFunction , requestOptions ) { if ( this . get ( 'session.isAuthenticated' ) && !Ember.isEmpty(this.get('session.authenticated.access_token'))) { var basicHTTPToken = btoa(this.get('session.authenticated.account_id') + ":" + this.get('session.authenticated.access_token')); addHeaderFunction ( 'Authorization' , 'Basic ' + basicHTTPToken ) ; } } } ) ;

Then an an initializer for the custom authorizer: ember g initializer custom-authorizer 1 ember g initializer custom - authorizer //app/intializers/custom-authorizer.js import CustomAuthorizer from '../authorizers/custom'; export function initialize(container, application) { application.register('authorizer:custom', CustomAuthorizer); } export default { name: 'custom-authorizer', before: 'ember-simple-auth', initialize: initialize }; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 //app/intializers/custom-authorizer.js import CustomAuthorizer from '../authorizers/custom' ; export function initialize ( container , application ) { application . register ( 'authorizer:custom' , CustomAuthorizer ) ; } export default { name : 'custom-authorizer' , before : 'ember-simple-auth' , initialize : initialize } ;

Here is a Git Repo with a working example https://github.com/DoryZi/SimpleAuth

This hopefully will get you up and running! enjoy 🙂