Best Practices for Enforcing Authorization
When integrating Oso Cloud into your application, we recommend this series of best practices. We put them at the top of the section to ensure that you see them, but you will likely need to deal with other content from our docs before fully understanding these recommendations.
For more platform-agnostic guidance on best practices for authorization, see our Authorization Academy (opens in a new tab).
Initial adoption
When you are first moving Oso Cloud into your app, we recommend:
-
Incrementally introducing Oso Cloud's authorization into your application. For example, starting with enforcement of a single endpoint.
-
Determining your authorization data strategy based on the initial endpoint you want to enforce authorization on.
To make getting started simpler, you might be able to use local authorization, which lets you enforce authorization with your locally available data.
In cases where local authorization isn't available, you can either:
-
Send relevant authorization data along with [requests as context facts]. We have a detailed guide on adopting local authorization, which includes details on this strategy.
Note that this is recommended only as a temporary solution and isn't recommended for complex production applications. However, it is a useful strategy for initial development.
-
Introducing Oso's authorization piecemeal into your application behind feature flags.
This gives you the option of running Oso and any pre-existing authorization services side by side in specific environments, giving you the chance to monitor and reconcile any differences before deploying Oso Cloud more widely.
-
Auditing authorization coverage of your application using middleware.
For example, you can use request-local state to track how many endpoints a request contacts that enforce authorization. If a request is fulfilled without having contacted any endpoints with authorization enforcement, you can produce an error log to notify your team that some authorization still needs to be done.
Enforcement strategy
There are many different authorization strategies you can use to secure your application. We suggest taking a holistic approach based on the layer of application you are working in, as well as what you need to accomplish.
These best practices are meant to be illustrative and not exhaustive. For example, you might use multiple strategies to enforce authorization in the same endpoint.
Service layer + request-level authorization
The service layer deals with HTTP requests, and authorization at this level is referred to as "request-level."
What to authorize
At this level, you should perform coarse-grained authorization, such as ensuring:
- Administrative endpoints are accessible only by admins
- Users cannot access other tenant's data
How to implement authorization
Implement this kind of enforcement via middleware because it can scale as you add new routes.
If your platform doesn't support middleware, you might consider treating this kind of authorization more like resource-level authorization.
Business logic + resource-level authorization
Business logic deals with the actual manipulation of your application's resources. Because of that, authorization at this level is referred to as "resource-level."
What to authorize
When dealing with specific resources, you often want to perform tightly focused
authorization. For example, ensuring that a user editing a resource has the
"edit"
permission on it explicitly.
How to implement authorization
Because these checks will be pervasive throughout your application (we recommend at least one authorization check per endpoint), providing reusable code patterns can help your team successfully secure your application.
What this strategy looks like depends on the programming language your application's built in, but we find teams have success with language features that allow you to modify the endpoint functions themselves (i.e. higher-order functions), such as Python decorators.
In your Oso Cloud SDK, these requests often use explicit authorization.
Data access + query-level authorization
Data access describes reading your application's state (typically from a database). You can perform authorization at this level by modifying a query to ensure it only returns authorized data.
What to authorize
Similar to resource-level authorization, data access authorization often relies on tightly focused permissions.
However, instead of authorizing whether the action is permissible, these rely on
filtering out data where the action is not permissible. A heuristic for
understanding this style of authorization is that the query should only return
data that meets criteria specified in a WHERE
clause.
How to implement authorization
This style of authorization explicitly requires modifying the queries you use to
access data, such as adding WHERE
clauses to SQL queries to omit unauthorized
data.
Oso's list API is meant to perform this style of filtering.
Presentation + client-side authorization
When rendering a UI, you often want to modulate its appearance based on a user's permissions. For example, not rendering elements the user cannot access, or greying them out.
What to authorize
You need to know what actions the current user can take on objects visible in the UI.
How to implement authorization
You should never perform authorization requests in your application's front end. Because the end user has a large degree of control over code that runs in their browser, you can never fully trust its requests.
Instead, you should always create server endpoints to retrieve this authorization data.
To make these kinds of requests easier to manage, Oso SDKs offer an actions API.
For more detail, see Frontend (UI) Authorization.