AngularJS Authorization

Sample Project

Download a sample project specific to this tutorial configured with your Auth0 API Keys.

System Requirements
  • AngularJS 1.6
Show requirements

This tutorial shows you how to control authorization in your client-side single page application.

Access Control in Single Page Applications

Access control is the control over what different users can see in your application and which routes they can access. With Auth0, you can implement access control by using scopes granted to users.

To set up access control in your application, define the following restrictions:

  • The data from an API can only be returned if the user is authorized to access it.
  • The user can access specific routes and UI elements in your application only if they have the appropriate access level.

The previous step used the read:messages scope for accessing API resources. This scope indicates that the user can only view the data. You can consider users with this scope regular users. If you want to give some users permission to edit the data, you can add the write:messages scope.

Read about naming scopes and mapping them to access levels in the Scopes documentation. To learn more about custom scope claims, follow the User profile claims and scope tutorial.

Determine a User's Scopes

You can use scopes to make decisions about the behavior of your application's interface.

You can specify which scopes you want to request at the beginning of the login process.

If a scope you requested is available to the user, their access token receives a scope claim in the payload. The value of this claim is a string with all the granted scopes, but your application must treat the access token as opaque and must not decode it. This means that you cannot read the access token to access the scopes.

To get the scopes, you can use the value of the scope parameter that comes back after authentication. This parameter is a string containing all the scopes granted to the user, separated by spaces. This parameter will be populated only if the scopes granted to the user are different than those you requested.

To see which scopes are granted to the user, check for the value of authResult.scope. If there is no value for authResult.scope, all the requested scopes were granted.

Handle Scopes in the angularAuth0 Configuration

Add a local variable to app/app.js and initialize it with all the scopes you want to request when users log in.

Use that variable to set the scopes in the angularAuth0Provider initialization.

// app/app.js

var REQUESTED_SCOPES = 'openid profile read:messages write:messages';

angularAuth0Provider.init({
  // ...
  scope: REQUESTED_SCOPES
});

Add a setSession method to save the scopes granted to the user into browser storage.

First, check for the scopes in the scope key from authResult. If it's not empty, the user was granted a different set of scopes than the one the application requested, so you need to use the ones in authResult.scope.

If it's empty, all the scopes requested were granted, so you can use the values from variable that stores the requested scopes.

// app/auth/auth.service.js

function setSession(authResult) {
  // ...
  var scopes = authResult.scope || REQUESTED_SCOPES || '';

  localStorage.setItem('scopes', JSON.stringify(scopes));
}

Add a method called userHasScopes that checks for scopes in local storage. You can use this method to conditionally hide and show UI elements to the user and to limit route access.

// app/auth/auth.service.js

// ...
function userHasScopes(scopes) {
  var grantedScopes = JSON.parse(localStorage.getItem('scopes')).split(' ');
  for (var i = 0; i < scopes.length; i++) {
    if (grantedScopes.indexOf(scopes[i]) < 0) {
      return false;
    }
  }
  return true;
}

return {
  // ...
  userHasScopes: userHasScopes
}

Conditionally Display UI Elements

You can use the userHasScopes method with the isAuthenticated method to show and hide certain UI elements.

<!-- app/navbar/navbar.html -->

<button
  class="btn btn-primary btn-margin"
  ng-if="vm.auth.isAuthenticated() && vm.auth.userHasScopes(['write:messages'])"
  ui-sref="admin">
    Admin
</button>

Protect Client-Side Routes

You may want to give access to some routes in your application only to authenticated users. If you are using UI Router v1, you can check if the user is authenticated with the onEnter hook for a specific state.

Define a function that uses the authService service to check if the user is authenticated. If the user is not authenticated, they are redirected to the home route. Use this function in the onEnter hook for any states you want to protect.

// app/app.js

$stateProvider
  // ...
  .state('ping', {
    url: '/ping',
    controller: 'PingController',
    templateUrl: 'app/ping/ping.html',
    controllerAs: 'vm',
    onEnter: checkAuthentication
  })

// ...

function checkAuthentication($transition$) {
  var $state = $transition$.router.stateService;
  var auth = $transition$.injector().get('authService');
  if (!auth.isAuthenticated()) {
    return $state.target('home');
  }
}

In this example, when an unauthenticated user tries to access the /ping route, they are redirected to the /home route.

Limit Route Access Based on Scopes

You can use the onEnter hook to prevent access to client-side routes based on scopes. Call a checkForScopes function that passes the scope you choose to the userHasScopes function from the authService service.

If the user does not have the write:messages scope, they are redirected to the main route.

// app/app.js

$stateProvider
  // ...
  .state('admin', {
    url: '/admin',
    controller: 'AdminController',
    templateUrl: 'app/admin/admin.html',
    controllerAs: 'vm',
    onEnter: checkForScopes(['write:messages'])
  })

function checkForScopes(scopes) {
  return function checkAuthentication($transition$) {
    var $state = $transition$.router.stateService;
    var auth = $transition$.injector().get('authService');
    if (!auth.isAuthenticated() || !auth.userHasScopes(scopes)) {
      return $state.target('home');
    }
  }
}

Conditionally Assign Scopes to Users

By default, when you register scopes in your API settings, all the scopes are immediately available and any user can request them. If you want to handle access control, you need to create policies for deciding which users can get which scopes.

You can use Rules to create access policies. See the Rules documentation to learn how to use Rules to create scope policies.

Considerations for Client-Side Access Control

For the access control on the client-side, the scope values that you get in local storage are only a clue that the user has those scopes. The user could manually adjust the scopes in local storage to access routes they shouldn't have access to.

On the other hand, to access data on your server, the user needs a valid access token. Any attempt to modify an access token invalidates the token. If a user tries to edit the payload of their access token to include different scopes, the token will lose its integrity and become useless.

You should not store your sensitive data client-side. Make sure you always request it from the server. Even if users manually navigate to a page they are not authorized to see, they will not get the relevant data from the server and your application will still be secure.

Previous Tutorial
3. Calling an API
Next Tutorial
5. Token Renewal
Use Auth0 for FREECreate free Account