Strengthen API Access Control with Attribute-Based Authorization
There are many aspects to securing digital services. This can include everything from authenticating users, to arming your software supply chain, protecting against malicious code injection, and more. One critical area is your API authorization. When you look at OWASP’s top 10 API security vulnerabilities, broken authorization is not only listed as number one but also appears a few times (as different flavors of broken authorization, such as BOLA, BOPLA, and BFLA).
Developers usually remember to protect access to APIs. They secure it with an API key or (even better) with OAuth access tokens. But, even when they use the most mature option, there is often too technical a focus. In this article, I will explain how attribute-based authorization provides a business-focused and scalable approach.
Approaches to Access Control
We sometimes call authorization access control. When you authorize a request, you ensure (control) that the requester can access the resources. Different models for implementing access control in a system exist, but the two most popular ones are role-based access control (RBAC) and attribute-based access control (ABAC).
Role-based access control authorizes requests based on the user’s assigned role. You first assign roles to the users in your system, such as customer, VIP customer, admin, vendor, anonymous, or others. You then assign the required roles to your API endpoints. This system is powerful (that’s why it is popular) in simpler setups. In a complex system, however, it doesn’t allow you to implement fine-grained permissions, as all you can use for the authorization policy is the user’s role.
Attribute-based access control uses all available attributes (usually about the user) to authorize access. For example, a system that uses ABAC can make authorization decisions based not only on the user’s role, but also on whether the user is assigned to a concrete department or region or even if they try to access the API during office hours or from an expected location. In essence, the attributes used for authorization do not have to describe solely the user.
ABAC is a more powerful way to perform fine-grained authorization. However, you must be aware of where your APIs take the attributes from to perform authorization decisions. The attributes must come from a reputable source, and the API must be sure that no one has tampered with them. This makes an OAuth access token and its claims an excellent source of attributes for ABAC.
Utilize Claims-Based Authorization
The authorization server asserts claims in an access token, which is signed to protect the attributes’ integrity. Your APIs should rely on the token’s attributes as much as possible, but that might not be enough for complex authorization decisions. Your APIs can complement the token attributes with others needed to create an authorization decision, but you should ensure these attributes have the aforementioned traits. Ideally, they should come from your service’s own database or a similar safe source. You should never rely on attributes sent in headers, query strings, or the request body, as they can be easily spoofed.
ABAC is Not Just About the Subject
When you apply ABAC, you can use any attributes to perform authorization decisions, not just user (subject) attributes. For example, you can have API endpoints that you want only your internal applications to access. Thus, you can ensure that the API validates the client_id claim and authorizes only requests made with tokens issued to your internal clients.
When you apply authorization policies, you shouldn’t assume that you are authorizing the actual user identified by the credentials sent to your API. Consider this scenario. You have read and write access to resources A, B, and C. You then open an application that uses OAuth to gain access to your resources. During an OAuth authorization flow you give the application read access to resource B. The application will receive an access token in which you are identified as the subject. When the client sends that token to an API, the API has to make sure that with this token only read access to resource B is allowed, even if you, as a user, have write access to more resources. The API uses all the information from the access token to perform fine-grained authorization. The token can contain a claim that lists which resources the client can access, or it can only identify the client, and your API could read a database or query a configuration service to get the client’s permissions.
Managing Access Control at Scale
RBAC is powerful and much simpler to reason about than ABAC, but it doesn’t offer the fine-grained authorization opportunities you get with ABAC. However, as your APIs grow, it can become a burden to manage and govern all the policies, especially with that level of fine-tuning. If this happens, you should consider externalizing policy and authorization management to an external tool — an Entitlement Management System. A good example is the open-source project Open Policy Agent which allows you to centralize management of your authorization policies easily.
An API access control architecture with OAuth and EMS
Summary
Proper authorization constitutes an important part of your API security, as the OWASP list of API vulnerabilities shows. OAuth provides your APIs with API credentials created according to standards and ones well-suited for the ABAC model, which is superior to RBAC in most cases. You should use the token’s claims to implement fine-grained authorization policies to counter authorization-related threats. Remember to use all the attributes available to you, not only the ones describing the user, and you will be able to enhance your API security greatly.