UPDATE: Like @DustMason says in his answer, check out the awesome embercasts for authentication best-practices.
- Client Side Authentication Part I
- Client Side Authentication Part II
In order to completely separate the view (Ember app) from the server (Rails app) I want to use token authentication. I will likely use Devise on the Rails server.
Makes sense.
I need something like a before_filter equivalent in the Ember app where I can check if there is a current user and if that user has an authentication token set.
You can add an enter
hook on routes, this is roughly equivalent to a before_filter. But not sure that’s the best place to check for an auth-token.
The Rails server will return the current auth token on every call.
Makes sense. We use cookie-auth and fetch current user profile by calling /api/me
but either should work.
If it returns a null auth token the Ember app should detect this and transition to the unauthenticated state, redirecting to the login view.
Thing about this approach is that (unlike rails) it’s not easy to “protect” access to a particular ember routes. And no matter what a user can always pop open JS console and enter whatever state they want. So instead of thinking “user can only get into this state if authenticated” consider “what if unauthenticated user somehow navigates to this route”
I suspect I should be using an Ember state machine for this but I’m not sure how to proceed. Anyone tackled this problem yet?
Our auth needs are pretty simple so we’ve not found the need for a state machine. Instead we have an isAuthenticated
property on ApplicationController. We use this property in application.hbs
to replace the main view with a login form when a user is not authenticated.
{{if isAuthenticated}}
{{render "topnav"}}
{{outlet}}
{{else}}
{{render "login"}}
{{/if}}
From ApplicationRoute, we fetch user profile:
App.ApplicationRoute = Ember.Route.extend({
model: function() {
var profiles;
profiles = App.Profile.find({ alias: 'me' });
profiles.on("didLoad", function() {
return profiles.resolve(profiles.get("firstObject"));
});
return profiles;
}
});
Then our ApplicationController computes it’s isAuthenticated property based on the profile that was returned.