Kevin
Kevin

Reputation: 182

Authorization of UI Controls Based On Multiple Factors (User Role, Location, etc)

I have a workflow process where I am sending an object (Order in this case) through multiple departments (locations).

The same form is used for every process stage, but different elements of the UI are enabled or made visible based on certain criteria:

Currently my method is fairly straightforward, but it is difficult to maintain, is very specific to the class I'm working with, and requires the code to be compiled each time the permissions change (which is often):

Class code:

Public Class Order

    Public ReadOnly Property CanEditHeader
        If Me.Location = "Sales" AndAlso Me.UserRole = "Salesman" AndAlso Me.CreatorID = Me.UserID AndAlso Me.Revision = 0 Then
            Return True
        Else
            Return False
        End If
    End Property

    ...

End Class

UI Code:

Public Class OrderUI

    Public ThisOrder As Order        

    Public Sub UpdateUI()

        If ThisOrder.CanEditHeader Then
            Me.HeaderPanel.Enabled = True
        End If
        ...
    End Sub

    ...

End Class

It feels like this code is too explicit for this class, and can become very verbose as more complex permissions are added:

Public ReadOnly Property CanEditHeader
    If Me.UserRole = "SuperUser" Then
        Return True
    ElseIf Me.OrderType = "SalesOrder" AndAlso Me.UserRole = "Salesman" AndAlso Me.CreatorID = Me.UserID AndAlso Me.Revision = 0 Then
        Return True
    ElseIf Me.OrderType = "DevelopmentOrder" AndAlso Me.UserRole = "Developer" AndAlso Me.CreatorID = Me.UserID AndAlso Me.Revision = 0 Then
        Return True
    Else
        Return False
    End If
End Property

One thought I had was to give permissions to both the User and the Class, and allow where they intersect, but this doesn't seem much better and now I have to maintain my permissions in two places:

If ThisUser.CanEditHeader AndAlso ThisOrder.CanEditHeader Then
     Me.HeaderPanel.Enabled = True
End If

I have been trying to research examples of Attribute-Based Access Control (ABAC), and this seems like a method that would work for me, but I'm having trouble finding good examples that I can wrap my head around.

Can someone provide an example of a more elegant solution (ABAC or otherwise) on a better way to handle this?

Upvotes: 3

Views: 304

Answers (1)

Michael C Good
Michael C Good

Reputation: 597

Based on what you've said, for example this:

[...] but it is difficult to maintain, is very specific to the class I'm working with, and requires the code to be compiled each time the permissions change (which is often)

It sounds like you need a way to externalize your authorization from your application, which attribute-based access control is exactly meant for. So, you are on the right path! :-)

First off, full-disclosure, I'm an employee of Axiomatics, a company that provides attribute-based access control solutions, which is sometimes known as dynamic authorization. However, I'm going to try to tell you how to achieve what you need in what will be a vendor agnostic way.

A Brief Overview of Attribute-Based Access Control and eXtensible Access Control Markup Language

eXtensible Access Control Markup Language is a standards based language used for attribute-based access control. It defines an architecture and a processing model describing how to evaluate access requests.

ABAC architecture

The architecture contains the following components:

the Policy Enforcement Point (PEP): this is the component that secures the API / application you want to protect. The PEP intercepts the flow, analyzes it, and send an authorization request to the PDP (see below). It then receives a decision (Permit/Deny) which it enforces.

the Policy Decision Point (PDP) receives an authorization request (e.g. can Alice view record #123?) and evaluates it against the set of policies it has been configured with. It eventually reaches a decision which it sends back to the PEP. During the evaluation process, the PDP may need additional metadata e.g. a user's job title. To that effect, it can turn to policy information points (PIP)

the Policy Information Point (PIP) is the interface between the PDP and underlying data sources e.g. an LDAP, a database, a REST service which contain metadata about users, resources, or other. You can use PIPs to retrieve information the PDP may need at runtime e.g. a risk score, a record’s location, or other.

Treating Your Application Like An Enforcement Point

To be more efficient in managing your authorization, as mentioned we need a solution that handles decision making externally from the application logic of the requesting application. The requesting application is commonly known as a Policy Enforcement Point because the authorization policy is enforced at this point (makes sense, right?).

So, in your application, you will need methods to communicate with an external authorization server. For instance, you may call a method to approve a purchase order that looks like:

    XacmlAuthorizationDecision d = PDPUtil.PurchaseOrderAuthorization(User.Identity.Name, "approve", 
po.Identifier.ToString(), "purchase order",Request);

The contents of this method must add in the necessary attributes of the requestor (the subject - i.e. what is the user's job title, department, training that qualifies him or her for access), as well as any attributes regarding the resource. The attributes regarding the resource may be as simple as an identifier for the resource (i.e. resource-id = 12345).

More can be done to implement even finer grain access control with environmental attributes, like time of day.

Behind the scenes, in the content of the method that you are calling, of course there has to be of course an HTTP to your decision making server (called the Policy Decision Point). The attributes in the request we just discussed are passed through to this Policy Decision Point.

The Decision Maker - The Policy Decision Point (PDP)

The Policy Decision Point provides the decision the Policy Enforcement Point (PEP) is responsible for implementing.

The XACML language has a standards based response to promote interoperability and common terminology. This means whether you purchase an ABAC product (such as Axiomatics) or write your own ABAC sotware, if you follow the standard the software can be replaced without affecting your authorization.

A sample response in JSON from a XACML engine looks like this:

  {
  "Response" : {
    "Decision" : "Permit",
    "Status" : {
      "StatusCode" : {
        "Value" : "urn:oasis:names:tc:xacml:1.0:status:ok"
      }
    }
  }
 }

A sample response if SOAP is used looks like this:

<xacml-ctx:Response xmlns:xacml-ctx="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17">
  <xacml-ctx:Result>
    <xacml-ctx:Decision>Deny</xacml-ctx:Decision>
    <xacml-ctx:Status>
      <xacml-ctx:StatusCode Value="urn:oasis:names:tc:xacml:1.0:status:ok"/>
    </xacml-ctx:Status>
  </xacml-ctx:Result>
</xacml-ctx:Response>

Your PEP will receive this response and it will need application logic to process it. For example, on DENY you may want to choose not to display particular UI components. On PERMIT, you would show the UI components. You can easily make these decisions for web pages without affecting performance.

If you are considering purchasing an ABAC product rather than building your own, please be sure to check what XACML profiles are supported. Not all profiles (like JSON or multiple-decision) are supported by all vendors.

Lastly, a little plug for Axiomatics - we are fully XACML compliant and have a .NET SDK.

If you have any questions about anything I've covered, please let me know.

Upvotes: 4

Related Questions