The Session Service — Auth State

ember-simple-auth or Your Own

The Session Service — Auth State

A session service holds the authenticated user, the token, and helpers like authenticate and invalidate.

4 min read Level 3/5 #ember#auth#services
What you'll learn
  • Use ember-simple-auth or roll your own
  • Expose a tracked currentUser
  • Persist sessions via a session store

Most apps have a single source of truth for “who is logged in.” In Ember, that’s a session service — either the popular ember-simple-auth addon or a small service you write yourself.

Roll Your Own

For straightforward token auth, a custom service is short and clear:

// app/services/session.js
import Service, { service } from '@ember/service';
import { tracked } from '@glimmer/tracking';

export default class SessionService extends Service {
  @service store;

  @tracked currentUser = null;
  @tracked token = localStorage.getItem('token');

  get isAuthenticated() {
    return Boolean(this.token);
  }

  async login(email, password) {
    const res = await fetch('/api/login', {
      method: 'POST',
      body: JSON.stringify({ email, password }),
    });
    const { token, user } = await res.json();
    this.token = token;
    this.currentUser = user;
    localStorage.setItem('token', token);
  }

  invalidate() {
    this.token = null;
    this.currentUser = null;
    localStorage.removeItem('token');
  }
}

Use It Everywhere

// app/adapters/application.js
import JSONAPIAdapter from '@ember-data/adapter/json-api';
import { service } from '@ember/service';

export default class ApplicationAdapter extends JSONAPIAdapter {
  @service session;

  get headers() {
    return this.session.token
      ? { Authorization: `Bearer ${this.session.token}` }
      : {};
  }
}

ember-simple-auth

For more complex flows (OAuth, refresh tokens, multiple session stores), use the addon:

ember install ember-simple-auth

It ships with authenticators, session stores (cookie, localStorage, ephemeral), and route mixins. The newer pattern is to check auth in beforeModel:

import Route from '@ember/routing/route';
import { service } from '@ember/service';

export default class ProtectedRoute extends Route {
  @service session;
  @service router;

  beforeModel() {
    if (!this.session.isAuthenticated) {
      this.router.transitionTo('login');
    }
  }
}
State Management With Services →