7/17/16
AngularJS SPA Isolate Scope Directive Claims Authorization
OverviewIn a previous article, we discussed the use of directives to enable claims based authorization on some the user interface elements. For some scenarios, a directive is the ideal approach, but because of the fact that a directive is called every time is declared on the mark-up, it is not ideal for cases where an item lists can have many items, and we just need to validate one or two claims.CodeProject
Directive ImplementationWhen looking at our previous implementation, we can see on the console windows the number of times that the directive is called. We want to optimize the approach by just calling the directive one time and validate the claims for the user. A way to do this on AngularJS is by using an Isolate Scope Directive. This means that the directive does not share the same scope as the controller, but it also provides the advantages that we can pass object references and functions which can be used to indicate what claims need to be validated all at once thus eliminating the additional calls.New Approach Isolate ScopeNow that we understand our optimization approach, we can refactor our code by first removing the authorize directive from the button markup which is what causes the multiple directive calls. We can now define our new directive with isolate scope and restrict it to “E” which means that it can be used as an element only. The idea here is that we want to declare it only one time on the mark-up outside the ngRepeat scope. We also want to add two attributes to our element. These attributes are assigned to functions within the controller. We should notice that in order to pass evaluating expressions to our directive, the attributes need to be declare with “&”.
scope: { authorizeMapping: '&', authorizeCallback: '&', },//isolate scope
The function assign to the authorize-mapping attribute returns a JSON with all the claims that need to be validated on behalf of that controller. The function assign to the authorize-callback attribute is called by the directive to return the status of each claim (true when found). Let’s take a look at our new implementation:
Controller Kicks InOnce the controller has received the status of each claim, we can leverage the power of AngularJS by mapping claims to controller variables. At this point, we just need to add an ng-show directive and assign a controller variable to evaluate if the user is authorized to see that element. Yes, we are still using a directive for each element, but that is just evaluating a true or false expression, and it is not calling the authorization service to validate the claim.We can now compare the console output with the isolate scope, and we should see that we no longer have multiple calls to our directive. The result should be just one entry.
Does It Work?To check that this is working properly we can run a simple test. Run JSFiddle and set the app.edit claim value to an empty string or just click the delete icon. This should remove the permission on the rest of the list items as shown below.Areas of ImprovementAs usual, we should ask ourselves if there ways of improving this approach. Since we can now notice that this solution uses controller variables, do we really need a directive? If the concern is reusability, the directive approach is preferred over a controller only implementation as this can create code duplication. To show this, we can review the controller only solution on another article.
scope: { authorizeMapping: '&', authorizeCallback: '&', },//isolate scope |
Originally published by ozkary.com
7/10/16
AngularJS SPA Directive Claims Authorization
CodeProject
OverviewWhen we talk about authorization of the elements on a web application, we make reference to the ability to hide or show some areas of the application based on the permissions that are granted to the logged on user. These permissions are usually delivered to the application via claims on a security token like a JSON Web Token (JWT).Security ServiceFor now, we assume that the claims have been populated in our security service. This service has a simple implementation in which it checks if a particular claim already exists for the current user by managing the claims information as a property. The purpose for this service is to be used by all controllers, directives and other services that require authorization services.SpecificationsWe want to be able to create a simple user interface that contains a list of items with two action item buttons. The delete button allows us to remove the item from the list. The edit button is used to edit the item information. In order to understand what claim controls the access to what element, we must have some information that indicates what needs to be done. The table below provides the information that we need. If the user has the respective claim, we display the element. Otherwise, we remove it from the DOM.
Element Claim Action
Delete Button app.delete Display the element
Edit button app.edit Display the element
ImplementationNow that we understand what claim and elements we need to look for, we can take a look at our app. The image below shows a simple list with items. Each item has a delete and edit button. This maps well with what has was been defined on our specifications.When using AngularJS, the recommended approach to change element behavior is by using directives. With that in mind, we can implement an Authorize directive which takes a tag value. This tag is the actual claim value that can be used by the directive and the authorization service to verify that the user has the required claim. Let’s take a look at our implementation next:
On the HTML tab, we have added the authorize directive with the respective claim tag for each of the call to action buttons (delete, edit). On the JavaScript tab, we can see our directive implementation (dirAuth) . We read the claim tag from the element attributes and pass it as an argument to the auth service ($svcAuth). If the claim is found on the claims collection, the result is set to true, and we show the element. Otherwise, we hide it.Does It Work?To check that this is working properly we can run a simple test. Run the JSFiddle and click on the delete icon for either the delete or edit claim. We should see how all the icons for the remaining rows are no longer available. In the image below, the app.delete claim was removed. We could also just empty the claim value as this would evaluate as false and would remove the permission on the control.Areas of ImprovementsThat was fairly easy to secure, but there is something there that bothers me a bit. If we take a closer look, we can see that this list has multiple items, and each item has a delete and edit call to action buttons. As we can image, the directive will be called each time it is declared in the mark-up. In this example, there are five items with two buttons. This means that our directive will be called 5X2 times (n x 2 for any list). We can see this by adding a trace call on the code and looking at the console window:As suspected, our directive is called too many times, but we just need to check for two claim values. Clearly for this scenario, we need a better approach. We can address this concern by using a directive with isolate scope, but we can leave that for another article.
Overview
When we talk about authorization of the elements on a web application, we make reference to the ability to hide or show some areas of the application based on the permissions that are granted to the logged on user. These permissions are usually delivered to the application via claims on a security token like a JSON Web Token (JWT).
Security Service
For now, we assume that the claims have been populated in our security service. This service has a simple implementation in which it checks if a particular claim already exists for the current user by managing the claims information as a property. The purpose for this service is to be used by all controllers, directives and other services that require authorization services.
Specifications
We want to be able to create a simple user interface that contains a list of items with two action item buttons. The delete button allows us to remove the item from the list. The edit button is used to edit the item information. In order to understand what claim controls the access to what element, we must have some information that indicates what needs to be done. The table below provides the information that we need. If the user has the respective claim, we display the element. Otherwise, we remove it from the DOM.
Element | Claim | Action |
Delete Button | app.delete | Display the element |
Edit button | app.edit | Display the element |
Implementation
Now that we understand what claim and elements we need to look for, we can take a look at our app. The image below shows a simple list with items. Each item has a delete and edit button. This maps well with what has was been defined on our specifications.
When using AngularJS, the recommended approach to change element behavior is by using directives. With that in mind, we can implement an Authorize directive which takes a tag value. This tag is the actual claim value that can be used by the directive and the authorization service to verify that the user has the required claim. Let’s take a look at our implementation next:
On the HTML tab, we have added the authorize directive with the respective claim tag for each of the call to action buttons (delete, edit). On the JavaScript tab, we can see our directive implementation (dirAuth) . We read the claim tag from the element attributes and pass it as an argument to the auth service ($svcAuth). If the claim is found on the claims collection, the result is set to true, and we show the element. Otherwise, we hide it.
Does It Work?
To check that this is working properly we can run a simple test. Run the JSFiddle and click on the delete icon for either the delete or edit claim. We should see how all the icons for the remaining rows are no longer available. In the image below, the app.delete claim was removed. We could also just empty the claim value as this would evaluate as false and would remove the permission on the control.
Areas of Improvements
That was fairly easy to secure, but there is something there that bothers me a bit. If we take a closer look, we can see that this list has multiple items, and each item has a delete and edit call to action buttons. As we can image, the directive will be called each time it is declared in the mark-up. In this example, there are five items with two buttons. This means that our directive will be called 5X2 times (n x 2 for any list). We can see this by adding a trace call on the code and looking at the console window:
As suspected, our directive is called too many times, but we just need to check for two claim values. Clearly for this scenario, we need a better approach. We can address this concern by using a directive with isolate scope, but we can leave that for another article.