Skip to main content
Oso can make decisions based on data stored in your own database, which is known as Local Authorization. Oso does not read your data. Oso only needs to understand the schema. By understanding the schema of your database, Oso can produce complete or partial SQL queries to be run against your database. These expressions reflect the authorization decisions defined in your policy, such as:
  • Evaluating to a boolean value to express authorization
  • Filtering out rows representing unauthorized resources
Local Authorization currently supports PostgreSQL.

Support for other databases

Support for other databases is under active development, including MySQL and MongoDB. If you use a different database and want to leverage Local Authorization, share your use case to help us prioritize integrations.

When to use Local Authorization

  • Your service uses a PostgreSQL database
  • All data needed to make authorization decisions is available: In a microservice architecture, services that introduce their own roles on resources might use Local Authorization. For example, a service with resource-level roles (e.g. a file sharing service with reader and writer roles) can use Local Authorization once the tenant-level roles for users (managed by another service) are synchronized to Oso as centralized data.
  • Your database can handle the additional query load of making authorization checks.
  • Your authorization logic does not rely on any of these currently unsupported features:
    • Logic that grants access to all resources based on database data
    • Inequality comparisons between Oso Cloud data and database data
    • Recursive logic that mixes centralized facts with database facts
      • For example:
        has_permission(user: User, "read", parent: Parent) if
          has_relation(child, "parent", parent) and
          has_permission(user, "read", child);
        
        This rule can be evaluated if both has_relation and has_permission facts are kept entirely local or entirely in Oso Cloud. It cannot be evaluated if one is local and the other is centralized.
In other cases, use centralized authorization data.

Overview

At a high level, to use Local Authorization:
  1. Configure how facts in your policy correlate to tables in your database using a Local Authorization config file.
  2. Call the local check API in your application’s authorization enforcement code. This API returns a SQL expression –– either a full query or a fragment to use in another query’s WHERE clause.
  3. Use the returned SQL query fragment when querying the database stores your authorization data.
For details of using Local Authorization, see the guide on filtering lists with local data.

Config

When Oso evaluates authorization requests, it aggregates sets of facts that, if true, satisfy the request. With Local Authorization, Oso needs to translate facts into expressions your database can evaluate. For example, has_role(User{"alice"}, "admin", Organization{"acme"}) You provide this translation in a YAML configuration file:
# One entry per fact signature in your database
facts:
  # Ex:
  # has_relation(Issue:_, parent, Repository:_):
  <predicate> ([<type>:]{_, <id>} )*:
    # Ex:
    # query: SELECT id, repository FROM issues
    query: <sql_query>

# Optional map of resource <type>s to their data type in your application database
sql_types:
  # Ex:
  # Issue: UUID
  <type>: <sql_data_type>

facts

The facts section is required and is where the majority of your configuration logic lives. It contains one key per fact signature stored in your database. A fact signature consistes of:
  • A predicate (e.g. has_role, has_relation).
  • A parenthesized list of comma-separated arguments (e.g. User:_, String:admin)
Each signature must have a query value that returns rows matching the signature. The _ symbol in a fact signature indicates that the <id> of the entity is a variable returned by the query. For example, the signature
has_relation(Issue:_, String:parent, Repository:_):
means: “this SQL query returns one row for every Issue that has a parent Repository”. The query value for a signature must return the same number of columns as there are wildcards in the signature. For example:
-- invalid: too many columns
SELECT issue.id, 'parent', issue.parent_repo
-- valid: matches number of wildcards
SELECT issue.id, issue.parent_repo
FROM issue

Additional restrictions

  • Fact signatures must be referenced in rules in your policy.
  • Fact signatures also must not overlap. For example:
Valid (no overlap):
facts:
  is_protected (Repository:_, Boolean:true):
    query: |-
      select id
      from repository
      where is_protected

  is_protected (Repository:_, Boolean:false):
    query: |-
      select id
      from repository
      where !is_protected
Invalid (overlap):
facts:
  is_protected (Repository:_, Boolean:_):
    query: |-
      select id, is_protected
      from repository

  is_protected (Repository:_, Boolean:false):
    query: |-
      select id
      from repository
      where !is_protected
  • Each query must be a SELECT statement (Technically a <query specification> per SQl-92). Common table expressions (CTEs), subqueries, and set expressions like UNION are allowed, but they must also be a SELECT. The following is not valid, because the CTE is an UPDATE statement:
    WITH inserted as (
        UPDATE issue
        SET parent_repo = 1
        RETURNING id, parent_repo
    )
    SELECT id, parent_repo
    FROM inserted
    

sql_types

sql_types maps resource types in Oso Cloud (e.g. Issue, Repository) to their database column types. This helps Oso generate queries that use indices effectively. This section is optional, but strongly recommended.

Example

facts:
  has_relation(Issue:_, parent, Repository:_):
    query: SELECT id, repository FROM issues

sql_types:
  Issue: UUID
  Repository: UUID
This configuration tells Oso how to resolve has_relation facts that associate issues with their parent repositories.

Validate Local Authorization configuration

You can validate the configuration using the oso-cloud CLI. Include this check as part of your CI/CD pipeline. For more guidance, see CI and Testing.

Guides

Local Check API

After configuring Local Authorization for your application, the local check API performs authorization using data distributed across Oso Cloud and your own database. The methods are documented under the appropriate Client SDK. Note that centralized facts still affects Local Authorization decisions.