e-Zest members share technology ideas to foster digital transformation.

User authentication & access privilege checking in AngularJS application

Written by Ashwini Eksambekar | Jan 30, 2017 8:22:23 AM

Introduction:

In this article, an approach is suggested for effective and secured user authentication in angular application.

Authentication as well as authorization are important aspects of any application. Application should not expose all of its data and functionality to just any user. Application users should authenticate themselves to see, access certain portions of application, or to perform certain action on application. To identify user and user’s permissions, we would require application user to be logged in. There is a difference in the way user management is implemented in different applications. Here one approach is suggested, for user authentication in angular application, using AngularUI Router as routing framework.

For large application, consisting of many modules, further comprising many tabs, sub-tabs etc. effective and secured user access management becomes a challenging task. Thus to simplify this, state based routing, provided by ui-router can be used. For using, approach suggested here, application structure must be considered, as depending upon the application structure, such as modules and tabs, nested views, multiple views, way in which views are rendered, user access permissions regarding views etc. many things vary from one application to other.

Following are the key steps with which effective and secured user access management can be achieved:

  • We can associate our each application URL with a state and add parameters to that state such as module ID, tab ID, sub-tab ID etc. as per the application structure.
  • (Here for an URL, its module ID represents the module it belongs to. Parameter tab ID represents tab, this URL represents itself or the tab, whose sub-tab is represented by the URL.)
  • Finally, we will be having each URL with specific module ID, tab ID, and sub-tab ID.
  • (Here, if a user has access to a particular tab and thus, if it means like user also has access to its sub-tabs, then we can specify same tab ID for main tab URL and its sub-tabs URLs. (Even in such case there is no need to specify specific sub-tab ID for it.)
  • For URLs such as login, logout, and other application specific URLs which are accessible to any user, irrespective of its roles and permissions, we need to specify same module ID, tab ID, sub-tab ID or simply keep all of them blank.
  • After this set-up, we need to identify User’s access permissions as user logs into the application. Based on the user’s access permissions, we need to create a list of modules accessible to user. (This list must contain module ID), list of tabs accessible to user (This list must contain tab ID) and list of sub-tabs accessible to user (This list must contain sub-tab ID).
  • Now, we just need to monitor every URL change. For this we can use, state change events provided by the UI-Router.
  • In such state change event, we get, both the state from which we expect navigating (Let’s call it source) and the state to which we want to navigate. (Let’s call it as destination). Here both source and destination states are now having module ID, tab ID and sub-tab ID it belongs to or it represents. Also, we have the list of accessible modules, tabs and sub-tabs ready.
  • Thus, we need to check the access to destination state is allowed or not using destination state parameters. Like check module ID of destination state is present in list of accessible modules, tab ID of destination state is present in list of accessible tabs and sub-tab ID of destination state is present in list of accessible sub tabs.
  • If all these checks are successfully passed then allow navigating to the destination URL. Otherwise, prevent the navigation and prompt the user about access denial.

Example:

(Assigning state parameters to states)

 // app.js
app = angular.module(‘myUiRoutingApp’, ['ui.router'])
.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
$stateProvider
.state(login, {
url: "/login",
templateUrl: "modules/main/views/login.html",
params: {
moduleID: "",
tabID: ""
}
})
.state('user', {
url: "/user",
templateUrl: "modules/user/views/createuser.html",
params: {
moduleID: "UserModule",
tabID: "User"
}
})
.state('user.profile', {
url: "/userProfile'",
templateUrl: "modules/user/views/userProfile.html",
params: {
moduleID: "UserModule",
tabID: "User"
}
})
.state('rolesPermissions', {
url: "/rolesPermissions",
templateUrl: "modules/admin/views/rolesPermissions.html",
params: {
moduleID: "AdminModule",
tabID: "rolesPermissions"
}
})
.state('assignUsers', {
url: "/assignUsers",
templateUrl: "modules/admin/views/'assignUsers'.html",
params: {
moduleID: "AdminModule",
tabID: "UserAssignment"
}
})
}
]);

(Note : In above example, it is assumed that, if a user has access to a particular tab then he/she also has access to its sub-tabs, and thus, have kept tabID same for the states ‘user’,’user.profile’. Also have not added sub-tabID for the same purpose.)

(Getting user info like access permissions after successful user login and preparing lists as below)

  • $rootScope.accessibleModules: This is list of modules accessible to User. For our example, $rootScope.accessibleModules should contain ‘AdminModule’,’ UserModule’ etc.moduleIDs. when user logs in as admin user and should contain only ’UserModule’ if logs in as an ordinary user.
  • $rootScope.accessibleTabs: This is list of tabs accessible to User. For our example,$rootScope.accessibleTabs should contain‘rolesPermissions,’ ‘UserAssignment’ etc.tabIDs. based on permissions.For example there are two admin users. Admin 1 is allowed to access ‘rolesPermissions’ state and Admin 2 is allowed to access 'assignUsers' state.In such case when Admin1 logs in $rootScope.accessibleTabs should contain ‘rolesPermissions ’tabID and for Admin 2 it should be ‘UserAssignment’tabID.
  • $rootScope.accessibleSubTabs: This is list of sub-tabs accessible to User. As per application requirements, in similar manner above populate this list.

(Checking user is authenticated and is allowed to access the application data (URL) or not.)

 $rootScope.$on('$stateChangeStart',
function(event, destination, destParams, source, sourceParams) {
var isAccessAllowed = true;
if (destination.params.moduleId != "" && destination.params.tabId != "") {
if ($.inArray(destination.params.moduleId, $rootScope.accessibleModules) === -1) {
isAccessAllowed = false;
} else if ($.inArray(destination.params.moduleId, $rootScope.accessibleModules) == 0 && $.inArray(destination.params.tabId, $rootScope.accessibleTabs) === -1) {
isAccessAllowed = false;
} else {
isAccessAllowed = true;
}
} else {
isAccessAllowed = true;
}
if (!isAccessAllowed) {
notify ("warning", "Access Denied .!!");
event.preventDefault ();
}
});

Benefits:

Benefits of the URL/state based, user access privilege authentication approach are mentioned below:

It helps to achieve secured user access to application data and to handle impact of user roles and permissions to data considering changes in user management implementation.

It prevents unauthenticated users to access application data which they are not supposed to access or use. As it considers every URL change, thus covers almost max possible ways such as browser back/forward actions, keyboard based back/forward key press like events, cut-copy-paste of URLs etc. any of actions under current session.

It is easy to implement and has a flexible and maintainable approach.

State parameter does not directly provide any information related to users access and permissions. Thus, it plays safe.

Summary:

Based on application structure and requirements, we can perform URL based user access authentication. We can also use an angular factory/service, (e.g.myAuthService etc.) where we can store user info and authentication logic for the same.

If you have any suggestions regarding this article, please comment below. Thank you for reading. Hope this can help you perform, secured user authentication in Angular JS application in an easy manner.