Skip to content

Latest commit

 

History

History
 
 

ember-simple-auth-devise

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 

The API docs for Ember Simple Auth Devise are available here

Ember Simple Auth Devise

This is an extension to the Ember Simple Auth library that provides an authenticator and an authorizer that are compatible with customized installations of Devise.

Server-side setup

As token authentication is not actually part of Devise anymore, there are some customizations necessary on the server side (most of this is adapted from José Valim's gist on token authentication).

First, a new column for the authentication token must be added to the users table:

class AddAuthenticationTokenToUser < ActiveRecord::Migration
  def change
    add_column :users, :authentication_token, :string
  end
end

That authentication token must be auto-generated by the model on creation:

class User < ActiveRecord::Base
  before_save :ensure_authentication_token

  def ensure_authentication_token
    if authentication_token.blank?
      self.authentication_token = generate_authentication_token
    end
  end

  private

    def generate_authentication_token
      loop do
        token = Devise.friendly_token
        break token unless User.where(authentication_token: token).first
      end
    end
end

By default, Devise's sessions controller only responds to HTML request. In order for it to work with Ember Simple Auth it must also respond to JSON. To achieve that, define a custom sessions controller (if HTML responses are not needed the format handling can be left out of course):

class SessionsController < Devise::SessionsController
  def create
    respond_to do |format|
      format.html { super }
      format.json do
        self.resource = warden.authenticate!(auth_options)
        sign_in(resource_name, resource)
        data = {
          user_token: self.resource.authentication_token,
          user_email: self.resource.email
        }
        render json: data, status: 201
      end
    end
  end
end

and configure Devise to use that controller instead of the default one:

MyRailsApp::Application.routes.draw do
  devise_for :users, controllers: { sessions: 'sessions' }
end

Finally, the Rails application must authenticate users by their authentication token and email if present:

class ApplicationController < ActionController::Base
  before_filter :authenticate_user_from_token!

  private

    def authenticate_user_from_token!
      authenticate_with_http_token do |token, options|
        user_email = options[:user_email].presence
        user       = user_email && User.find_by_email(user_email)

        if user && Devise.secure_compare(user.authentication_token, token)
          sign_in user, store: false
        end
      end
    end
end

The Rails application should also not issue session cookies but authentication should be done exclusively via the authentication token as described above. The easiest way to disable sessions in Rails is to add an initializer config/initializers/session_store.rb and disable the session store in that:

Rails.application.config.session_store :disabled

If disabling sessions completely is not an option, make sure no session cookies are sent for JSON requests as described here.

If the server sends session cookies to the Ember frontend this will lead to the situation that the user is actually still logged in after Ember Simple Auth invalidates the session as the Rails session cookie will still be present because Ember Simple Auth does not know anything about that cookie and will not delete it on session invalidation!

The Authenticator

In order to use the Devise authenticator (see the API docs for Authenticators.Devise) the application needs to have a login route:

App.Router.map(function() {
  this.route('login');
});

This route displays the login form with fields for identification, password:

<form {{action 'authenticate' on='submit'}}>
  <label for="identification">Login</label>
  {{input id='identification' placeholder='Enter Login' value=identification}}
  <label for="password">Password</label>
  {{input id='password' placeholder='Enter Password' type='password' value=password}}
  <button type="submit">Login</button>
</form>

The authenticate action that is triggered by submitting the form is provided by the LoginControllerMixin that the respective controller in the application can include (the controller can also implement its own action and use the session API directly; see the API docs for Session). It then also needs to specify the Devise authenticator to be used:

// app/controllers/login.js
import LoginControllerMixin from 'simple-auth/mixins/login-controller-mixin'

export default Ember.Controller.extend(LoginControllerMixin, {
  authenticator: 'simple-auth-authenticator:devise'
});

The Authorizer

The authorizer (see the API docs for Authorizers.Devise) authorizes requests by adding user_token and user_email properties from the session in the Authorization header:

Authorization: Token token="<user_token>", user_email="<user_email>"

To use the authorizer, configure it in the global environment object:

window.ENV = window.ENV || {};
window.ENV['simple-auth'] = {
  authorizer: 'simple-auth-authorizer:devise'
}

Installation

To install Ember Simple Auth Devise in an Ember.js application there are several options:

  • If you're using Ember CLI, just add the Ember CLI Addon to your project and Ember Simple Auth Devise will setup itself.

  • The Ember Simple Auth Devise extenion library is also included in the "ember-simple-auth" bower package both in a browserified version as well as an AMD build. If you're using the AMD build from bower be sure to require the autoloader:

    require('simple-auth-devise/ember');

    The browserified version will, like the Ember CLI addon, also setup itself once it is loaded in the application.

  • Download a prebuilt version from the releases page