Authorization is hard! Every application is different, so it is a domain-specific problem. It’s in the critical path of every application request, so it has to be lightning-fast. And you really need to manage it centrally for consistency, and to simplify governance and administration.
Adding to the complexity, there are also many ways of implementing authorization. Some use IDP generated tokens, while others intertwine authorization logic with application code, and others still extract that logic from code and into an external authorization policy. Some use local libraries to optimize for speed, while others use an externalized authorization service for consistency and scalability.
With so many options, it’s difficult to know which is right for you, without digging into each one. In this post, we demonstrate why you should implement a purpose-built externalized authorization service over the alternatives. Read all about it below, or watch this short video:
The benefits
At Aserto, we believe in the value of externalizing authorization out of your application. Externalized authorization services offer many benefits, including:
- Cleaner code: Extracting authorization logic from application code and into a policy keeps the application code tidy, without all of the authorization logic that tends to be added patch by patch to different parts of the code.
- Better understanding of authorization logic: Now that the authorization logic has been extracted from the application and centralized in a policy it is much easier to review it, understand it, and make any necessary changes.
- Consistency and reusability: An externalized authorization service enables you to provide a consistent experience across applications and services. You can easily reuse the same policy, or parts of it across multiple endpoints.
- Separation of concerns: Decoupling policy from code also means that the policy can be handed over to IAM or security engineers who can own its evolution. Developers can focus on code and leave the authorization logic to the experts.
- Policy changes are immediate without re-deploying the app: When you use an externalized authorization system you call it for every authorization decision. That system has access to the latest policy and authorization information and pushes any changes to policy to all the connected authorizers in near real time. This means that the changes take effect immediately across every application or service that uses that policy, without a redeploy.
In this post, we demonstrate the last point using an application most people are familiar with: a corporate directory. We call this application “People Finder.”
Demonstrating the value
People Finder is a corporate directory that uses an attribute-based access control (ABAC) policy. ABAC policies let you authorize based on dynamic attributes, such as department, title, location, and more. Let’s see how this application uses ABAC to determine what users can see and do once logged in.
The PeopleFinder authorization policy implements the following authorization rules:
- Every user can view any other user’s profile. This is represented in the
peoplefinder.GET.*
rules. - Any user can update their own profile, but not anyone else's. The policy has further logic that limits the ability to edit the profile of others to employees of the Operations department. This is represented in the
peoplefinder.PUT.*
andpeoplefinder.POST.*
rules.
This is how this logic is defined in Rego within the policy:
package peoplefinder.PUT.api.users.__id
default allowed = false
default visible = true
default enabled = true
allowed {
props = input.user.properties
props.department == "Operations"
}
allowed {
input.user.key == input.resource.id
}
allowed {
input.user.id == input.resource.id
}
- Only IT Managers can delete users. There is further logic that changes the frontend experience as well. Based on this logic, anyone from the Operations department will be able to see the delete button, but it will only be enabled for IT Managers. This is represented in the
peoplefinder.DELETE.*
rule.
Here’s how this is defined in the policy:
package peoplefinder.DELETE.api.users.__id
default allowed = false
default visible = false
default enabled = false
allowed {
props = input.user.properties
props.department == "Operations"
props.title == "IT Manager"
}
visible {
props = input.user.properties
props.department == "Operations"
}
enabled {
allowed
}
Let’s look at how different users experience the application, based on the permissions they have been granted.
First, we’ll log in as a user with the least amount of permissions. We’ll use Euan Garden, a salesperson who has only been granted can-view
permission.
Like every other user, Euan can view the profiles of every user in the application. He can also update his own personal information, but not that of other users.
If he tries to update the information of another user he will get an error message. Here’s what happens when Euan tries to update Karin Lamb’s phone number:
Now let's look at the other extreme, a user that has all of the permissions. We’ll login as Kris Johnsen, an IT Manager from the Operations department.
As an IT Manager, Kris can update every record on anyone’s profile, as well as delete profiles. Where Euan only sees an enabled “Edit” button on his profile, Kris sees enabled “Edit” and “Delete” buttons on every profile.
So far, this is a pretty simple example of an ABAC policy. Permissions are determined based on user attributes like department and title. What if we want to evolve the policy to allow any manager in the organization to edit the profiles of their reports?
Aserto is an externalized authorization service, so we can simply update the policy to add that functionality to the application. Once the policy is updated, Aserto will share the new policy with every connected authorizer in near real time, causing an immediate change in behavior in the application allowing managers to update the profiles of their direct reports.
Let’s see this in action.
Adding functionality without a re-deploy
As you can see on Euan’s profile, his manager is April Stewart. Under the current policy, only employees from the Operations department can edit the profiles of other users. April is in the Sales Engagement Management department, so it comes as no surprise that when we log in as her and visit Euan’s profile we see a grayed out “Update” button.
Let's change that by changing the policy. We’re now going to introduce relationship-based access controls (ReBAC). While ABAC uses attributes, ReBAC uses relationships between subjects (users/groups) and objects (resources, fields, etc.) in the system to determine what users can do.
The Aserto directory stores all of the user properties from the identity provider (e.g. name, title, department) as well as relationships between entities.
Given than Aserto natively supports management relationships, all we have to do to allow April to update Euan’s information is to add this clause to the policy:
allowed {
directory.is_manager_of(input.user.key, input.resource.id)
}
Now we just need to rebind this policy instance to the new version and refresh.
Back in People Finder, we can see that the update button is enabled for April and she can finally give Euan his well deserved promotion to Sales Manager.
We didn’t need to redeploy the app, it just works. Just imagine how this could help with your app development. That is the true power of externalized authorization.
Conclusion
In the post, we described the benefits of externalizing authorization into a purpose built service. We then demonstrated the power of externalized authorization, namely the ability to add or change functionality based on policy change alone and without re-deploying the application.
Aserto is an externalized authorization service that comes with built in support for every popular authorization model (RBAC, ABAC, ReBAC, and combinations). With Aserto you can change much more than a policy and have it take effect without anything else than a policy change. You can seamlessly evolve your authorization model as requirements change. You don’t need to replatform or retool.
We’d love to hear what you think about what we are building. Drop us a line, or join our community Slack to share your thoughts. We look forward to it!
Related Content
Using scopes vs. permissions for application authorization
One of the earliest authorization patterns applications implement bases access on OAuth 2.0 scopes that are embedded in access tokens issued by an identity provider. While convenient, this method has significant limitations. In this post, we describe those limitations and provide alternatives for managing application permissions.
Oct 18th, 2023
It's time for authorization standards: AuthZEN
Today each authorization vendor supports its own APIs and protocols. But there's an appetite to change this. We’re in the early innings of a promising effort called AuthZEN, where the authorization community is hoping to establish a set of patterns and standards for externalized authorization. Read all about in this post.
Oct 23rd, 2023
Hard coded logic vs externalized authorization service
Most developers start building permissions by sprinkled in authorization logic to various parts of the code. While a common pattern, embedding authorization logic within the application code has several limitations compared to externalized authorization. In this post, we describe those limitations and the benefits of externalized authorization.
Nov 21st, 2023