Migrating Angular 1.x Applications from Lock v9 to v11

This guide will help you migrating your Angular 1.x application from Lock 9 to Lock v11.

Update Lock

Update the Lock library using npm or yarn.

# installation with npm
npm install --save auth0-lock

# installation with yarn
yarn add auth0-lock

Once updated, you can add it to your build system or bring it in to your project with a script tag.

<script type="text/javascript" src="node_modules/auth0-lock/build/lock.js"></script>

If you do not want to use a package manager, you can retrieve Lock from Auth0's CDN.

<script src="https://cdn.auth0.com/js/lock/11.0.1/lock.min.js"></script>

2. Adding Angular Lock Library

Most Angular 1.x apps used the auth0-angular which is currently deprecated. This guide will use auth0-lock 3.0 to simplify using Lock v11.

Use npm to uninstall the old library and install the new one.

npm uninstall auth0-angular --save
npm install angular-lock --save

Then include it in your index.html file:

<!-- index.html -->
<script src="node_modules/angular-lock/dist/angular-lock.min.js"></script>

3. Updating App File

In your app.js file:

  • Add auth0.lock to your Angular module
  • Inject lockProvider in your configuration
  • Initialize a Lock instance in config()
  • Inject your authentication service in run() and call the method that listens for authentication events (we will implement changes in the authentication service next)
// app.js
(function() {
  'use strict';

  angular
    .module('app', ['ngRoute', 
//   'auth0' 
     'auth0.lock']) // Add auth0.lock
      .config(config)
      .run(run);

  config.$inject = [
    '$locationProvider',
    '$routeProvider',
 // 'authProvider',
    'lockProvider' // Inject lockProvider
  ];

  function config(
    $locationProvider,
    $routeProvider,
//  authProvider
    lockProvider // Provide lockProvider
  ) {
    $routeProvider
      .when('/', {
        controller: 'HomeController',
        templateUrl: 'app/home/home.html',
        controllerAs: 'vm'
      })
      .otherwise({
        redirectTo: '/'
  });

  $locationProvider.hashPrefix('');
  $locationProvider.html5Mode(true);

  // Configure Auth0 Lock instance
  // Read more about configuration here:
  // https://auth0.com/docs/libraries/lock/v11
  lockProvider.init({
     domain: 'YOUR_AUTH0_DOMAIN'),
     clientID: 'YOUR_CLIENT_ID',
     options: {
       autoclose: true,
       auth: {
         responseType: 'token id_token',
         audience: 'https://' + 'YOUR_AUTH0_DOMAIN' + '/userinfo',
         params: {
           scope: 'openid profile email'
         }
       }
     }
   });
  }

  // Inject authentication service and
  // run method to handle authentication
  run.$inject = ['authService'];

  function run(authService) {
    authService.handleAuthentication();
  }

}());

4. Updating Authentication Service

If you are using an authentication service, you will need to make a few minor changes there as well. Lock v11 provides events so you can execute functionality when the user is authenticated, when there is an authentication error, etc. You can read more at the Lock v11 documentation.

// auth.service.js
(function() {
  'use strict';

  angular.module('app').service('authService', authService);

  // Inject 'lock'
  authService.$inject = ['lock', '$location'];

  function authService(lock, $location) {
 
    function login() {
      // Display the Lock widget using the
      // instance initialized in the app.js config
      lock.show();
    }

    function logout() {
      // Remove tokens and expiry time from localStorage
      localStorage.removeItem('access_token');
      localStorage.removeItem('id_token');
      localStorage.removeItem('expires_at');
      $location.path('/');
    }

    function handleAuthentication() {
      // Uncomment if you are not using HTML5Mode
      // lock.interceptHash();

      lock.on('authenticated', function(authResult) {
        if (authResult && authResult.accessToken && authResult.idToken) {
          console.log('Authenticated!', authResult);
          _setSession(authResult);
        }
      });
      lock.on('authorization_error', function(err) {
        console.log(err);
        alert(
          'Error: ' + err.error + '. Check the console for further details.'
        );
      });
    }

    function _setSession(authResult) {
      // Set the time that the access token will expire
      var expiresAt = JSON.stringify(
        authResult.expiresIn * 1000 + new Date().getTime()
      );
      // Save tokens and expiration to localStorage
      localStorage.setItem('access_token', authResult.accessToken);
      localStorage.setItem('id_token', authResult.idToken);
      localStorage.setItem('expires_at', expiresAt);
    }

    function isAuthenticated() {
      // Check whether the current time is
      // past the access token's expiry time
      var expiresAt = JSON.parse(localStorage.getItem('expires_at'));
        return new Date().getTime() < expiresAt;
    }

    return {
      login: login,
      logout: logout,
      handleAuthentication: handleAuthentication,
      isAuthenticated: isAuthenticated
    };
  }
})();

If you are not using a service, you can implement the handleAuthentication() method's functionality in your app's run() method, and implement the login(), logout(), and _setSession() functionality in the controller where your login is located.

Configure Your Auth0 Client for Embedded Login

When implementing embedded login, Lock v11 will use cross-origin calls inside hidden iframes to perform authentication. To make sure this can be done securely, Auth0 needs to know the domains where you will be hosting your applications.

Add the domain to the Allowed Web Origins field. You can find this field in the Client Settings area of your Dashboard.

Allowed Web Origins

If you enable Custom Domain Names and the top level domain for your website is the same as the custom domain for the Auth0 tenant, Lock will work without any further configuration. Otherwise, you will need to configure your Auth0 client to use Cross-Origin Authentication.

Change calls to getProfile()

The deprecated getProfile() function was reimplemented in Auth0.js v9. The previous implementation received an ID Token as a parameter and returned the user profile.

The new implementation requires an Access Token parameter.

Behavioral Changes in Lock v11

Hosted Login Pages

Auth0.js 9 and Lock v11 are designed for embedded login scenarios and cannot be used when customizing the Hosted Login Page.

If you have customized the Hosted Login Page keep using Auth0.js v8 / Lock v10.

Usage in Popup Mode

When using Popup Mode in previous versions of Lock, a new browser window was opened and immediately closed in order to complete the authentication transaction. In Lock 11 that window is opened on a hidden iframe, providing a better user experience.

Last Time you Logged in With window with Authorization Code Flow

Lock 11 will never show the Last time you logged in with window when using the Authorization Code Flow (i.e. specifying response_type='code'). It will always prompt for credentials.

If you want to avoid showing the Lock dialog when there's an existing session in the server, you can use Auth0.js's checkSession() function.

Single Sign On Using IP Ranges

In earlier versions of Lock, you could configure an IP range in an Active Directory/LDAP connection. You could then use that range to allow integrated Windows Authentication if the user's IP was within the range. When this was true, Lock would display a button enabling SSO for that user as shown below.

SSO With Lock 10 and Windows IP Ranges

This functionality has been removed from Lock 11. There is no IP detection and the user will get redirected to the Active Directory login page where they will have to type in their credentials. It will still be available when using centralized login.

Default Values

Lock 11 will default the scope parameter to 'openid profile email'. This is to make the Last time you logged in with window work correctly.

If you don't specify that scope when initializing Lock, and you are running your website from http://localhost or http://127.0.0.1, you will get the following error in the browser console:

Consent required. When using `getSSOData`, the user has to be authenticated with the following scope: `openid profile email`

That will not happen when you run your application in production or if you specify the required scope. You can read more about this in the User consent and third-party clients document.

Was this article helpful?