Lock based authentication setup

While I may eventually use the answer for this more elaborate situation than mine, I would appreciate some help on Authentication Setup. My application is written in Aurelia and spans many modules (in ES6 terms). So, my options to instantiate the Auth0Lock object are defined as

        let options = {
            rememberLastLogin: true,
            auth: {
                redirectUrl: 'http://localhost:9000/#/auth0-service',
                responseType: 'token',
                sso: true
            },
            theme: {
                labeledSubmitButton: true
            },
            allowForgotPassword: true,
            allowSignUp: false,
            allowedConnections: 'Username-Password-Authentication'],
            prefill: {
                email: "auth0test@aureliatools.com",
                username: "auth0test"
            }
        };

The “event handler” for “authenticated” event is in ‘auth0-service’ module and the correct data is received from Auth0 as the consequence to a successful authentication.

My problem is that my app is being reset (losing its state) when my callback http://localhost:9000/#/auth0-service/ is invoked - so I clearly need to change this part of the setup

            auth: {
                redirectUrl: 'http://localhost:9000/#/auth0-service',
                responseType: 'token',
                sso: true
            },

The flow is as follows

  • the user clicks on the Github Users menu item, which requires authentication. Then login route is invoked behind the scenes, which in turn uses the lock.show to prompt for authentication.
  • List item

This screenshot proves that the application is being reset when processing the response from Auth0:

What is the correct setup (or what is my problem)?

Hey @nik, good question.

This is a challenge with all single page app frameworks. Authenticating with Auth0 necessitates a redirect back to your application and, as you’ve pointed out, doing so means you lose your app’s state.

Generally the best approach is to plan out the various paths that a user might take before initiating a login and persist any relevant state to browser storage where it can be picked up again once the redirect is complete. For example, if the user is a few layers deep into a dynamic route in the app, you can keep note of that route in local storage when they click the login button. Or if they have a form filled out, you can store an object with the form values. Then after authentication is complete you can rehydrate the app with the appropriate state. Here’s some pseudo code:

login() {
  localStorage.setItem('last_known_route', window.location.url);
  lock.show();
}

lock.on('authenticated', (authResult) => {
  let lastRoute = localStorage.getItem('last_known_route');
  // redirect to lastRoute

  // deal with authResult
  localStorage.setItem('access_token', authResult.accessToken);
  localStorage.setItem('id_token', authResult.idToken);
});

The downside is that this can get unwieldy if you need to manage a lot of state and if you have a lot of possible paths that the user can take before they log in. With that in mind, it’s probably best to limit what the user can do before they log in if you don’t want to manage all that state. For example, before they start filling out a form, tell them they need to be logged in. Don’t let them enter data at all until they have authenticated.

Does that address what you were wondering about?

Not completely - as I would like to believe that there is a better approach possible. Can we discuss this before “accepting a defeat”. If you have the time to do that, I will create the next post, that will focus on that detail only.

Since authentication using Auth0 requires a redirect, ultimately there needs to be something that allows your state to survive. This means keeping some reference to it such that it can be picked up again after authentication. This could be local storage, session storage, or even a cookie.

Unfortunately there isn’t anything built directly into Lock to allow your app’s state to survive, as that is something which is highly contextual and unique between apps.