Skip to content

Instantly share code, notes, and snippets.

@izelnakri
Last active February 3, 2017 11:54
Show Gist options
  • Select an option

  • Save izelnakri/4a3ed3135cd4700871406a6fec229553 to your computer and use it in GitHub Desktop.

Select an option

Save izelnakri/4a3ed3135cd4700871406a6fec229553 to your computer and use it in GitHub Desktop.
Ember.js token based authentication without a library
import Ember from 'ember';
import config from '../config/environment';
import fetch from 'ember-network/fetch';
const { Service, inject, RSVP } = Ember;
export default Service.extend({
store: inject.service(),
authenticationToken: undefined,
currentUser: undefined,
fetchCurrentUser() {
return new RSVP.Promise((resolve, reject) => {
if (this.get('authenticationToken')) {
return fetch(`${config.apiHost}/me`, {
method: 'GET',
mode: 'cors',
headers: {
'Authorization': this.get('authenticationToken') ?
`Token ${this.get('authenticationToken')}` : undefined
}
}).then((response) => {
if (response.status === 200) {
return response.json();
}
return reject();
}).then((json) => {
if (json.id) { // unfortunate need due to the fetch() function
this.get('store').pushPayload({ user: json });
this.set('currentUser', this.get('store').peekRecord('user', json.id));
if (Raven) {
Raven.setUserContext({ user_id: this.get('currentUser.id') });
}
return resolve(this.get('currentUser'));
}
return reject(); // unfortunate need due to the fetch() function
}).catch(() => {
return reject(); // unfortunate need due to the fetch() function
});
}
return reject();
});
},
login(authenticationToken) {
return new RSVP.Promise((resolve, reject) => {
this.set('authenticationToken', authenticationToken);
this.fetchCurrentUser().then((user) => {
localStorage.setItem('yourapp_authentication_token', authenticationToken);
return resolve(user);
}).catch(() => {
return reject();
});
});
},
logout() {
return new RSVP.Promise((resolve, reject) => {
if (this.get('currentUser')) {
localStorage.removeItem('yourapp_authentication_token');
this.set('authenticationToken', null);
this.set('currentUser', null);
return resolve();
}
return reject();
});
}
});
// routes/application.js
// this ensures the /me gets loaded before app goes to other route model()'s:
import Ember from 'ember';
const { Route } = Ember;
export default Route.extend({
model() {
if (window && window.localStorage) { // ember fastboot edit
this.get('session').set(
'authenticationToken', localStorage.getItem('yourapp_authentication_token')
);
return this.get('session').fetchCurrentUser().then(() => {
return; // finally() doesn't work somehow, Bluebird > Ember.RSVP
}).catch(() => {
return;
});
}
}
});
// routes/base.js
// you can call login() and logout functions throughout the app route and controller functions:
// it needs ember-route-action-helper package
// like: this.send('login', model.get('authenticationToken'));
import Ember from 'ember';
import ScrollResetMixin from 'frontend/mixins/scroll-reset';
export default Ember.Route.extend(ScrollResetMixin, {
actions: {
login(authenticationToken) {
this.get('session').login(authenticationToken).then((user) => {
if (user.isAdmin) {
return this.transitionTo('admin.index');
}
return this.transitionTo('public.profile');
});
},
logout() {
this.get('session').logout().then(() => {
this.transitionTo('public');
}); // maybe a flashMessage
}
}
});
// initializers/session.js
// to make this.get('session') available everywhere:
export default {
name: 'session',
after: 'ember-data',
initialize(app) {
app.inject('route', 'session', 'service:session');
app.inject('controller', 'session', 'service:session');
app.inject('application', 'session', 'service:session');
app.inject('component', 'session', 'service:session');
}
};
// adapters/application.js
// to ensure that we send the authenticationToken for Ember Data requests:
import config from 'frontend/config/environment';
import Ember from 'ember';
import DS from 'ember-data';
const { inject, computed } = Ember;
export default DS.RESTAdapter.extend({
host: config.apiHost,
session: inject.service('session'),
headers: computed('session.authenticationToken', function() { // this part is awesome:
return {
'Authorization': this.get('session.authenticationToken') ?
`Token ${this.get('session.authenticationToken')}` : undefined
};
})
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment