Using aurelia-auth with Auth0 and separate login page

That’s a long and windy title, but it was a long and windy process to get this far too.

I’m trying to get up and running on a new project using Aurelia for the frontend. I want to use Auth0 as my identity provider, but I don’t want to use any of the social features. And I don’t want to use the Auth0 Lock widget.

There is an Aurelia plugin called aurelia-auth that is a port of the Satellizer-plugin for Angular. This plugin takes care of keeping tokens around and providing some syntactic sugar for checking login status and such. Using this function, my main.ts file looks like this (I use Typescript for my developent here)

import 'bootstrap';
import {Aurelia} from 'aurelia-framework';
import {AuthService} from "aurelia-auth";

export function configure(aurelia: Aurelia) {
  aurelia.use
    .standardConfiguration()
    .developmentLogging()
    .plugin("aurelia-auth", (baseConfig) => {
      baseConfig.configure({
        loginUrl: "https://<mydomain>.auth0.com/oauth/ro",
        redirectUri: "#/"
      });
    })
    .feature("Components");

  let auth: AuthService = aurelia.container.get(AuthService);
  aurelia.start().then((a) => 
  {
    if (auth.isAuthenticated()) {
      a.setRoot("app");
    } else {
      a.setRoot("login");
    }
  });
}

If you have dabbled around in Aurelia you might see something funny around the aurelia.start method. Since I want to use a separate login screen (this is a admin/dashboard app) I can’t set the root to the app directly. I need to check if the user is logged in. If she is, I can redirect them to the app. I figured out this way to do it from here. But since I wanted to use aurelia-auth to figure out if there was a user or not, I needed to get to the AuthService that the plugin provides. And it turns out you can’t inject stuff into a function.

After some googling (read: few hours) I finally figured out that you can get objects from the DI-system using aurelia.container.get(ServiceName). And that completed the puzzle.

So now my login.ts looks something like this:

import {AuthService} from "aurelia-auth";
import {inject, Aurelia} from "aurelia-framework";

@inject(AuthService, Aurelia)
export class Login {
    email: string;
    password: string;
    
    constructor(private auth: AuthService, private aurelia: Aurelia) {

    }

    login() {
        var authRequest = {
            "client_id": "<myid>",
            "username": this.email,
            "password": this.password,
            "connection": "<connectionname>",
            "grant_type": "password",
            "scope": "openid"
        };
        
        return this.auth.login(authRequest)
            .then(response => {
                console.log(`Success: ${response}`);
                this.aurelia.setRoot("app");
                
            })
            .catch(error => {
                console.log(`Error! ${error}`);
            })
    }
}

And it works! Notice that in the success-path of the login request I set a new root for the app.

To logout, I just use aurelia-auth’s logout function. This clears the tokens from localstorage and redirects to the app root. Which detects that I’m not logged in, and redirects to the login page.

Huzza!