How to handle role-based authorization in AngularJS?

I am creating a web application that will satisfy two requirements for users. Note. I am new to AngularJS as a web development platform.

Front-end - 1: its search function, in which users can search for specific documents and studies based on keyword searches and filters. This was implemented using MySQL to retrieve data and display using AngularJS.

Front-end - 2: users will have the opportunity to create an account in a web application. Account Purpose:

  • Save their searches.
  • If the administrator associates each user with a specific role, these users will have access to additional parameters, such as changing the documents present in the database, as well as loading new documents and many other pages.

My question is:

How to handle role-based authorization in AngularJS? I cannot understand how to create a structure that includes the following functions: - Users get a role associated with them - Deny users access to pages or functions that are not associated with these roles.

I read several SO articles as well as tutorials, but each tutorial ends up saying that the author says role-based authorization should be handled on the server side, and I understand why this is.

It would be great if someone could point me to tutorials or reviews that are server-based for roles on AngularJS are role-based.

Thanks!

+7
angularjs mysql authorization
source share
1 answer

I use role-based authorization on both the backend and frontend. Since I use UI-Router for routing, the best resource I found (and improved for my needs) is this article:

link expired

If you are using a UI Router, definitely check it out. Basically, you need to configure route security and intercept all route changes. The article also contains a directive to hide user interface elements if the user does not have permission to access the content located behind him.


Edit: Adding code.

First, you need user permissions to be stored somewhere, for example. on the user object serialized in localStorage:

{"id":1,"name":"user","created_at":"2016-04-17 18:58:19","gender":"m","roles":["admin"]} 

Then you have two important parts:

  • Directive
  • - determine whether the item should be visible or not based on the assigned permission.
  • service - to verify authorization

Directive

 (function() { 'use strict'; angular .module('app') .directive('access', access); /** @ngInject */ function access(authorization) { var directive = { restrict: 'A', link: linkFunc, }; return directive; /** @ngInject */ function linkFunc($scope, $element, $attrs) { var makeVisible = function () { $element.removeClass('hidden'); }; var makeHidden = function () { $element.addClass('hidden'); }; var determineVisibility = function (resetFirst) { var result; if (resetFirst) { makeVisible(); } result = authorization.authorize(true, roles, $attrs.accessPermissionType); if (result === authorization.constants.authorised) { makeVisible(); } else { makeHidden(); } }; var roles = $attrs.access.split(','); if (roles.length > 0) { determineVisibility(true); } } } })(); 

You need to set CSS so that elements with the hidden class are not visible.

Services:

 (function() { 'use strict'; angular .module('app') .factory('authorization', authorization); /** @ngInject */ function authorization($rootScope) { var service = { authorize: authorize, constants: { authorised: 0, loginRequired: 1, notAuthorised: 2 } }; return service; function authorize(loginRequired, requiredPermissions, permissionCheckType) { var result = service.constants.authorised, user = $rootScope.currentUser, loweredPermissions = [], hasPermission = true, permission; permissionCheckType = permissionCheckType || 'atLeastOne'; if (loginRequired === true && user === undefined) { result = service.constants.loginRequired; } else if ((loginRequired === true && user !== undefined) && (requiredPermissions === undefined || requiredPermissions.length === 0)) { result = service.constants.authorised; } else if (requiredPermissions) { loweredPermissions = []; angular.forEach(user.roles, function (permission) { loweredPermissions.push(permission.toLowerCase()); }); for (var i = 0; i < requiredPermissions.length; i += 1) { permission = requiredPermissions[i].toLowerCase(); if (permissionCheckType === 'combinationRequired') { hasPermission = hasPermission && loweredPermissions.indexOf(permission) > -1; // if all the permissions are required and hasPermission is false there is no point carrying on if (hasPermission === false) { break; } } else if (permissionCheckType === 'atLeastOne') { hasPermission = loweredPermissions.indexOf(permission) > -1; // if we only need one of the permissions and we have it there is no point carrying on if (hasPermission) { break; } } } result = hasPermission ? service.constants.authorised : service.constants.notAuthorised; } return result; } } })(); 

Now you can use the directive to show / hide the element:

 <a ui-sref="app.administration" class="btn btn-primary pull-right" access="admin">Administration</a> 

Of course, this only hides the item in the DOM, so you should also perform an authorization check on the server.

This first part is solved for showing / hiding elements in the user interface, but you can also protect application routes.

Route Definition:

 (function() { 'use strict'; angular .module('app') .config(routeConfig); /** @ngInject */ function routeConfig($stateProvider) { $stateProvider .state('app.dashboard', { url: '/dashboard', data: { access: { loginRequired: true } }, templateUrl: 'template_path', controller: 'DashboardController as vm' } } })(); 

and now just check the resolution in the $stateChangeStart event

 (function() { 'use strict'; angular .module('app') .run(runBlock); /** @ngInject */ function runBlock($rootScope, $state, authorization) { $rootScope.$on('$stateChangeStart', function(event, toState) { // route authorization check if (toState.data !== undefined && toState.data.access !== undefined) { authorised = authorization.authorize(toState.data.access.loginRequired, toState.data.access.requiredPermissions, toState.data.access.permissionCheckType); if (authorised === authorization.constants.loginRequired) { event.preventDefault(); $state.go('app.login'); } else if (authorised === authorization.constants.notAuthorised) { event.preventDefault(); $state.go('app.dashboard'); } } }); } })(); 
+10
source share

All Articles