Protection of information in applications and systems has become increasingly important as a result of the rapid development and widespread deployment of computer systems in our daily life. The most common protection measures used in computer systems are:
- Prevention – applied to prevent information from unauthorized access, theft or damage.
- Detection – refers to discovery when information has been damaged, how it has been damaged, and who has caused the damage.
- Recovery – allows restoring the information that has been damaged or assessing and repairing any damage to the information.
Due to the fact that any browser-based code and session can be always compromised, we should never rely solely on front-end security and always combine it with much stricter back-end policies. So front-end security policies can be treated only as an additional layer of prevention mechanisms. In the classical security context, prevention usually attempts to achieve three security goals: confidentiality, integrity, and availability.
- Confidentiality – applied to prevent unauthorized disclosure of information.
- Integrity – prevents unauthorized modification of information,
- Availability – unauthorized withholding of information.
Having that in mind, we can help enforce availability in the browser and we can also provide a basis confidentiality and integrity by implementing one of the multiple access control patterns. So, generally speaking, access control in browsers is concerned with limiting users’ access to protected resources.
At first, it is required to include in one of your modules – probably top-most – dependency to permission module:
angular.module('app', [..., 'permission']);
Setting up permissions
The permission library in order to set permissions requires two values to be provided: permission name and validation function, where the first one is used to represent the identification name of the permission and the second one is used when checking if a set identifier is still valid. Validation can be checked either browser-side or server-side.
Locally validated permissions
So, let’s create a simple local (browser-side) permission:
The above code is pretty straightforward. It returns permission USER as valid only when property user is defined in root-scope. Easy.
Server-side validated permissions
However, quite often you will want to check in real time while a user is using our application if the permissions are valid. Let’s assume that we have a session mechanism implemented by PermissionService that returns a promise from hasPermission method checking via $http or $resource whether the permission is valid for the user. Internals of this method are not so important, so let’s just rely on the interface signature of this method. To create a server validated permission, we can use the same method setPermission.
Having in mind that making a request for the server every time when the state of application changes may be very inefficient and cause a user to wait for some time for the server to handle permission requests, most commonly we receive a set of permissions along with authentication response of the user. In this case, the method setManyPermissions comes in handy.
Angular-permission allows checking permissions on every level of application stack: in services, views, and states.
Permission allows you to provide permissions object in data property in every angular UI-router’s state definition on the config phase of the application. If you want to make sure that only ADMIN users can access the dashboard state, we just need to add the only property that restricts access to users that have valid ADMIN permission set. Permission library will intercept state resolving to check those permissions first, disabling accessing state for non-authorized users and redirecting them to a state provided in redirectTo property.
Alternatively, you can add except key that will specify the list of permissions that are not allowed to be authorized for the state.
Analogously to state, the permission library provides a directive permission that allows checking permission level inside the view. The directive accepts two arguments only and except that can be either a string or an array of limiting permissions. In the internals, the directive will hide all non-authorized elements adding ng-hide class to them.
In order to check the permissions inside factories and services, the Permission service exposes the authorize method allowing to pass the object with a map of permissions returning promise with authorization result.
Cleaning up session
When user session revokes, we usually want to clean up all our previously set permission definitions. Angular-permission exposes helper method clearPermssions allowing to remove all defined validation methods.
Managing security prevention policies using the angular-permission library is an easy and quite efficient task. The overhead of code is minimal and restricted to the scope of the problem covering all levels of angular infrastructure.
The current limitation is the lack of roles that could be used of as aliases for sets of permissions. This feature may be required from the business point of view, but also add complexity to evaluating authorization of the user. Basing on ACL implementation cost of authorization is equal n*(log(m))complexity where n is a number of checking permissions on state eg. in views and m is the length of the defined permissions list. The cost of adding roles and implementing RBAC will be exponential algorithmic complexity resulting in large application performance issues.