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!

9 thoughts on “Using aurelia-auth with Auth0 and separate login page”

  1. Hi Christian,

    Thanks for posting this. It has really helped me in my development. However, I’m running into an error where none of the routes are loaded when I set the root to ‘app’. No matter what I put for the loginRedirectUrl, I get route not found.

    Did you have this issue? If so, how did you solve it? If you’re down to help, I can certainly give some more info.

    Thanks man… looking forward to hearing from you.

    1. Where do you keep your routes? I put my routes in my app.ts file, which is the root I set when the authentication was successful. So I don’t really set a loginRedirectUrl at all. The root takes care of this for me.

      1. my auth-config file looks like this:

        var config = {

        // Our Node API is being served from localhost:3001
        baseUrl: ‘http://localhost:3001’,
        // The API specifies that new users register at the POST /users enpoint
        //signupUrl: ‘users’,
        // Logins happen at the POST /sessions/create endpoint
        loginUrl: ‘sessions/create’,
        // The API serves its tokens with a key of id_token which differs from
        // aureliauth’s standard
        tokenName: ‘id_token’,
        // Once logged in, we want to redirect the user to the welcome view
        //loginRedirect: ‘#/home’

        }

        export default config;

        so i’m not really setting a login redirect url either… i looked at that aurelia-auth source code and it was defaulting to #/

      2. my router-config.js file looks like this:

        import { AuthorizeStep } from ‘aurelia-auth’;
        import { inject } from ‘aurelia-framework’;
        import { Router } from ‘aurelia-router’;

        @inject(Router)
        export class AppRouterConfig {
        constructor(router) {
        this.router = router;
        }

        configure() {
        console.log(‘about to configure router’); //for what it’s worth worth, this never prints

        var appRouterConfig = function (config) {
        config.title = ‘My App’;

        config.addPipelineStep(‘authorize’, AuthorizeStep);

        config.map([
        {
        route: [”, ‘home’],
        name: ‘home’,
        moduleId: ‘./components/home/home’,
        nav: true,
        title: ‘Home’,
        auth: true
        },
        {
        route: [’employees’],
        name: ’employees’,
        moduleId: ‘./components/employees/employees’,
        nav: true,
        title: ‘Employees’,
        auth: true
        }
        ]);

        this.router.configure(appRouterConfig);
        }

        };

        }

      3. hmmm… i’m wondering if the fact that console.log never prints has something to do with it… like the router never gets created…

        here’s the relevant part of the main.js file

        let authService = aurelia.container.get(AuthService);
        aurelia.start()
        .then(a => {
        if (authService.isAuthenticated()) {
        a.setRoot(‘app’);
        } else {
        a.setRoot(‘login’);
        }
        });

        then in app.js, i have

        import { Router } from ‘aurelia-router’;
        import { AppRouterConfig } from ‘./router-config’;
        import { FetchConfig } from ‘aurelia-auth’;

        constructor(…) {
        this.router = router;
        this.appRouterConfig = appRouterConfig;
        this.fetchConfig = fetchConfig;

        ….
        }

        activate() {
        this.fetchConfig.configure();
        this.appRouterConfig.configure();
        }

        1. Yeah… I’m not sure. I used the /ro endpoint of Auth0 because I didn’t want to use Lock or another social login. So there was no redirect, I got the token as a part of the response.

          1. by the way, this is solved now. The problem was I was configuring the router in the activate() method of app.js. I moved the configuration() call to the constructor and it works now. Arrrrg.

Leave a Reply

Your email address will not be published. Required fields are marked *