Best-Practices for API Authorization

https://www.permit.io/blog/api-authorization-best-practices

Introduction

APIs are crucial gateways to the information exchange process in the development world.

In this context, authorization plays an enormous role in ensuring these interactions are secure, reliable, and compliant with various privacy and data protection norms. It's not just about who can access your APIs but what they can do with them. Understanding and implementing solid authorization practices is essential for safeguarding sensitive data and maintaining the integrity of API interactions.

Know Your API Actors

Effective API authorization relies on accurately identifying and catering to the diverse "actors" that interact with your APIs. Each type of actor requires specific authorization considerations to balance security and functionality. Let’s explore some of the key actors and their unique authorization needs:

  1. End-Users: These individuals use your API through client applications, like customers accessing their bank accounts via a banking app. They typically need user-specific access, managed through Role-Based Access Control (RBAC), to ensure they can only interact with their personal data and don’t have access to broader system functionalities.
  2. Internal Systems: Your own systems that interact with APIs, such as automated processes for data synchronization. These systems generally require privileged access compared to end-users, managed through service accounts with permissions tailored to their specific operational scope.
  3. Third-Party Applications: External applications needing API access, like third-party budgeting tools using a bank's API. Access for these actors is usually controlled through OAuth tokens, allowing them to request access on behalf of a user, thereby ensuring that a user's data is accessible only with their explicit consent.
  4. Developers: Responsible for creating and testing the API, developers require broad access during the development phase. This access is typically temporary and closely monitored, often managed through access tokens with limited lifespans or scopes to ensure security during the development process.

Each of these actors plays a distinct role in the ecosystem of API interactions, necessitating tailored authorization strategies. By understanding and addressing the specific needs of these key actors, you can create a more secure, efficient, and user-friendly API environment.

API Actors

Know Your API Authorization Models

Authorization models provide the structure for managing and granting access permissions. Here are the three prominent models with their explanations and examples:

  1. Role-Based Access Control (RBAC): Managing access based on pre-defined roles, this model emphasizes roles and privileges. For example, in a company, an employee could be assigned the role of 'manager' and given specific access privileges tied to this role, such as the ability to view and approve team reports.
  2. Relationship-Based Access Control (ReBAC): This model is based on the relationships between entities. An instance of this would be a doctor in a hospital being allowed access to the medical records of a patient they are directly treating.
  3. Attribute-Based Access Control (ABAC): This model considers the attributes of users, environments, or resources. A scenario here could be a user's access to a resource being determined based on their location (user attribute), the classification of the data they're attempting to access (resource attribute), and the current time (environment attribute).

Choosing the right model or combination of models is crucial for establishing a flexible and secure API authorization strategy.

Know Your API Layers

Authorization in an API ecosystem can be enforced at various layers, each having unique control mechanisms:

  1. API Gateway: This is the entry point for API calls. Here, feature toggling can be used for control, allowing specific features to be turned on or off based on the authorization level. For example, a premium user might have access to more API features compared to a free user.
  2. Infrastructure as Code (IaC) Configurations: The scripts and configuration files automatically set up your API infrastructure. Authorization at this level can control which parts of the infrastructure a user or system can interact with. For instance, a certain IaC script might only be run by system administrators.
  3. API Code: This is the actual code of your API. Authorization here can control what operations a user can perform, like read, write, or delete operations. For example, a user might be authorized to read data from the API but not write or delete data.
  4. Backend Code: The code running on your servers processes API requests. Authorization here can control what server resources a user can access. For instance, a user might be allowed to access certain databases but not others.
  5. Data Layer: This is where your data is stored. Authorization at this layer can control what data a user can access and modify. For example, a user might be allowed to access their own data but not the data of other users.

Understanding these layers and how to enforce authorization at each one is essential for maintaining a secure and reliable API.

API Layers

Do Not Trust JWT Only (claims, scopes)

While JSON Web Tokens (JWT) and OAuth scopes are fundamental to API security, they have limitations. JWT claims and OAuth scopes lack dynamic responsiveness to policy changes and may not provide comprehensive data for nuanced authorization decisions. They should be considered starting points for authorization but not the sole decision-making authority.

Use Policy as Code

Policy as Code represents a fundamental change in how authorization policies are defined and managed. It allows for creating, testing, and deploying security policies as code, leading to better governance, transparency, and version control. Open Policy Agent (OPA) is a prime example, with its Rego language offering a powerful tool to define and manage policies for API authorization. Another example is AWS Cedar, which provides an application-centric policy language.

Here's a Cedar code example of a healthcare ABAC policy 👇🏻

permit (
    principal,
    action == HealthCareApp::Action::"createAppointment",
    resource
)
when {
    (context.referrer in HealthCareApp::Role::"doctor"  && resource.patient == principal) ||
    principal in HealthCareApp::Role::"admin"
};

Use a Test Environment for Policy Testing

Testing is critical to policy management, especially in dynamic environments where policies change frequently. Using a test environment for policy testing, especially with tools like OPAL (Open Policy Administration Layer), helps ensure policies work as intended before being deployed in production. This practice not only minimizes disruptions but also ensures compliance and security.

OPAL (Open Policy Administration Layer)

OPAL is an open-source tool that operates as a dynamic layer for policy engines like Open Policy Agent (OPA) and AWS' Cedar Agent. It detects real-time policy and data changes, ensuring policy agents are consistently up to date. This synchronization extends across various services, such as APIs, databases, and SaaS solutions.

Please consider supporting our open-source work by giving OPAL a star on GitHub.

Use the Same Decision Configuration for all API Layers

Consistency in decision-making across API layers is crucial. Policy as Code engines, which can operate at various levels (like Envoy, Kong, and application code), ensure a single source of truth for all authorization decisions. This uniformity simplifies management, reduces errors, and enhances security.

Ensuring a uniform decision-making process across all API layers is not just about simplicity; it's about creating a cohesive security environment. Whether it's enforcing policies at the gateway or within the application code, a singular decision framework minimizes discrepancies and strengthens security protocols. This approach, facilitated by advanced tools like OPA, ensures that whether a request comes through a mobile app, a web service, or an internal microservice, it's subject to the same rigorous authorization checks.

REST API Authorization Audit

The importance of a centralized audit system in API authorization cannot be overstated. It's the cornerstone of understanding not just what decisions were made but why they were made. By leveraging the capabilities of Policy as Code and tools like OPAL, organizations can gain insights into the effectiveness of their authorization strategies, identify potential security gaps, and ensure compliance with regulatory requirements. This level of oversight is crucial in a landscape where data breaches and unauthorized access can have significant repercussions.

Decentralize Enforcement and Decision, Centralize Configuration

Decoupling enforcement and decision-making in API authorization enhances security and scalability. Decentralized enforcement ensures that decisions are made close to the action point, reducing latency and load on central systems. OPAL exemplifies this approach, centralizing configuration while decentralizing decision-making and enforcement. This architecture enhances security and agility in API authorization practices.

OPAL Architecture

Conclusion

In API authorization, tools like Permit.io and OPAL represent the cutting edge. Permit.io, with its OPAL-based solution, offers a robust, scalable, and flexible framework for managing API authorization. By centralizing configuration, decentralizing enforcement, and providing comprehensive audit capabilities, these tools empower developers to implement best practices in API authorization. Engaging with the OPAL community on GitHub and exploring Permit.io's offerings are excellent starting points for those seeking to explore these advanced capabilities.