Ember-simple-auth with REST API and session cookie

I learned something new and realized I did it totaly wrong. So here’s a brief example of how simple auth, routes, models and a customized RESTAdapter work together. I’ll expand the example with serialization stuff once I stumbled through it.

Scenario:

/config/environment.js:

ENV['simple-auth'] = {
  authorizer: 'authorizer:custom',
  store: 'simple-auth-session-store:cookie', // optional
  crossOriginWhitelist: ['http://example.com'],
  routeAfterAuthentication: '/events'
};

/app/controllers/login.js:

import Ember from 'ember';
import LoginControllerMixin from 'simple-auth/mixins/login-controller-mixin';

export default Ember.Controller.extend(LoginControllerMixin, {
  authenticator: 'authenticator:custom'
});

/app/authenticators/custom.js:

import Ember from 'ember';
import Base from 'simple-auth/authenticators/base';

export default Base.extend({  
  restore: function(data) {
    return new Ember.RSVP.Promise(function (resolve, reject) {
      if (!Ember.isEmpty(data.session_name)) {
        resolve(data);
      }
      else {
        reject();
      }
    });
  },

  authenticate: function(options) {
    return new Ember.RSVP.Promise(function(resolve, reject) {
      Ember.$.ajax({
        type: "POST",
        url: 'http://example.com/api/user/login',
        data: JSON.stringify({
          username: options.identification,
          password: options.password
        })
      }).then(function(response) {
        Ember.run(function() {
          resolve(response);
        });
      }, function(xhr, status, error) {
        Ember.run(function() {
          reject(xhr.responseJSON || xhr.responseText);
        });
      });
    });
  },

  invalidate: function() {
    console.log('invalidate...');

    return new Ember.RSVP.Promise(function(resolve, reject) {
      Ember.$.ajax({
        type: "POST",
        url: 'http://example.com/api/user/logout',
      }).then(function(response) {
        Ember.run(function() {
          resolve(response);
        });
      }, function(xhr, status, error) {
        Ember.run(function() {
          reject(xhr.responseJSON || xhr.responseText);
        });
      });
    });
  },
});

/app/authorizers/custom.js: (this touches all local XHR requests + to hosts defined in crossOriginWhitelist)

import Ember from 'ember';
import Base from 'simple-auth/authorizers/base';

export default Base.extend({
  authorize: function(jqXHR, requestOptions) {
    requestOptions.contentType = 'application/json;charset=utf-8';
    requestOptions.crossDomain = true;
    requestOptions.xhrFields = {
      withCredentials: true
    };

    var token = this.get('session.token');
    if (this.get('session.isAuthenticated') && !Ember.isEmpty(token)) {
      jqXHR.setRequestHeader('X-CSRF-Token', token);
    }
  }
});

/app/router.js:

import Ember from 'ember';
import config from './config/environment';

var Router = Ember.Router.extend({
  location: config.locationType
});

Router.map(function() {
  this.route('login');
  this.resource('events', function() {
    this.route('show', { path: '/:event_id'});
  });
});

export default Router;

/app/routes/events.js:

import Ember from 'ember';
import AuthenticatedRouteMixin from 'simple-auth/mixins/authenticated-route-mixin';

export default Ember.Route.extend(AuthenticatedRouteMixin, {
  model: function(params) {
    return this.store.find('event');
  },

  setupController: function(controller, events) {
    controller.set('events', events);
  }
});

/app/adapters/application.js:

import DS from "ember-data";

var ApplicationAdapter = DS.RESTAdapter.extend({
  namespace: 'api',
  host: 'http://example.com',
  pathForType: function(type) {
    return type + '.json';
  }
});

export default ApplicationAdapter;
4 Likes