I am creating a web app which will satisfy two requirements for the users. Note: I am new to AngularJS as a web development platform.
Front-end - 1: Its a search functionality where users can search for specific documents and studies based on keyword search and filters. This has been implemented using MySQL for fetching data and display using AngularJS.
Front-end - 2: Users will have the option to create a account on the web app. Purpose of the account is:
My question:
How to handle role based authorization in AngularJS? I am not able to figure out how to create a framework which involves following functionalities: - Users get a role associated to them - Prevent users from accessing pages or functionalities which are not associated with those roles
I have read up on few SO articles as well as tutorials but every tutorial ends with author saying that role based authorization should be handled on the server side and I understand why this is true.
It would be great if anyone can point me to tutorials or write-ups which has role-based authorization implemented on server side for AngularJS.
Thanks!
The auth guard uses the authentication service to visualize if the user is logged in, if they're logged in, it checks if their role is permitted to access the requested route. If they're logged in and licensed the canActivate() method returns true, otherwise, it returns false and redirects the user to the login page.
Each group has a set of permissions. For role-based authorization, the customer is responsible for providing the user ID, any optional attributes, and all mandatory user attributes necessary to define the user to Payment Feature Services. The customer must also define the roles that are assigned to the user.
Open command prompt and go to project root folder. Start the application. Create a new service, AuthService to authenticate the user. Open AuthService and include below code.
I use role based authorization on backend as well as on frontend. Since I am using UI-Router for routing, the best resource I found (and improved to my needs) is this article:
link expired
If you use UI Router, definitely check it out. Basically you need to set up your routes security and intercept all route changes. The article also includes a directive for hiding user interface elements, if the user doesn't have permission to access the content behind it.
Edit: Adding some code.
First, you need to have user's permissions stored somewhere, e.g. on 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:
(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 your CSS so that elements with class hidden
are not visible.
Service:
(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 element:
<a ui-sref="app.administration" class="btn btn-primary pull-right" access="admin">Administration</a>
Of course this will only hide the element in DOM, so you must do the authorization check on the server too.
This first part solved to showing/hiding elements in user interface but you can also protect app 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 for permission in $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');
}
}
});
}
})();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With