What is List Filtering?
Beyond making simple yes/no authorization decisions, apps regularly need to generate lists of authorized data. Imagine you're building a dashboard for GitCloud users. When an authenticated user accesses the page, they should see a high-level overview of the repositories they have "read" access for. This is an example of a list (all repositories) of authorized data (they have "read" access for).
How to Filter Lists
A naive way to generate that list would be to fetch all repositories from the database and then filter them in-memory by asking if the current user is allowed to view each repository in turn. If GitCloud has millions of repositories, that might get pretty darn slow, not to mention creating a lot of network requests.
When dealing with large sets of data, it's more efficient to operate in bulk. Authorization as a service products typically achieve this by centralizing your authorization data in the service. This works, but if your users have access to millions of resources, it may be inefficient to fetch all of those IDs from the authorization service.
Because of this, Oso Cloud also supports a decentralized approach to list filtering, which allows you to keep some of your application data in your application database. This reduces the amount of data that you have to fetch from Oso Cloud to filter lists. It also makes it easier to manage your data, since less of it has to be synchronized to Oso Cloud.
You can use whichever approach best fits your application and your organization. Read the following docs for detailed instructions:
List Filtering With Centralized Data
Oso Cloud's list
API can efficiently perform authorization checks over
collections of data that is stored in Oso Cloud. The list
API flattens the
naive iterative approach into a single request: "What is the set of repositories
that the user is allowed to see?" The response is a list of IDs of authorized
resources (repositories, in this case) that can then be loaded from the database
in one fell swoop. Once you have fetched the list of authorized IDs from Oso
Cloud, you can plug them into a SQL query in your application code to return the
filtered data you ultimately want to display to your user.
async function authorizedRepositories(oso: Oso, currentUser: User): Promise<Repository[]> { const repositoryIds = await oso.list( {type: "User", id: currentUser.id.toString()}, "view", "Repository" ); return getRepositoriesByIds(repositoryIds);}
For more details, consult the API
docs
for the list
endpoint.
List Filtering with Decentralized Data
Oso Cloud's list_local
API can generate lists of authorized data by combining
data in Oso Cloud with data from your application database.
If your users have access to millions of resources, it may be inefficient to
fetch all of those IDs directly with the list
API. Consider building an
"Issues" microservice for GitCloud, which provides users with a paginated list
of issues they have access to. The policy says that users can access issues that
belong to repositories they have access to. If repositories have lots of issues,
it could be slow to fetch the list of all authorized issue IDs from Oso Cloud,
plug them into a SQL query, and get back the result.
With Oso List Filtering, you can tell Oso to look in your own database for information about which issue belongs to which repository. This way, the size of the API response Oso Cloud sends your application is proportional to the number of repositories the user has access to, rather than the (much larger) number of issues the user has access to.
List filtering is powered by "local authorization", which is the term Oso uses to describe cases where your local database might perform the final steps of authorization (e.g. actually filtering out unauthorized resources).
Configuration
For details about getting started with list filtering, see Local Authorization.
Usage
When you initialize the Oso Cloud client, provide the YAML configuration:
oso = OsoCloud::new( ... data_bindings: "path/to/data_bindings.yaml")
Then, use the list_local
method to partially evaluate authorization with the
data stored in your Oso Cloud environment (for example, has_role
facts
granting users access to repositories), and get back a filter that finishes
authorization with the data stored in your database. In addition to passing in
the user, action, and resource type as in the regular list
method, you'll pass
in a fourth argument with the name of the column that corresponds to the
resources' IDs. The list_local
method returns a SQL WHERE
clause that you
can combine with other things such as ordering and pagination:
results = Issue.where(oso.list_local(user, "read", "Issue", "id")) .order(:created_at) .limit(25) .offset(50)
For a more full-fledged example of List Filtering with Decentralized Data, check out our Ruby on Rails sample app (opens in a new tab)
Talk to an Oso Engineer
If you'd like to learm more about how to filter lists in your app or have any questions about this guide, schedule a 1x1 with an Oso engineer. We're happy to help.