> ## Documentation Index
> Fetch the complete documentation index at: https://www.osohq.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Local Authorization

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.

```mermaid theme={null}
sequenceDiagram
    accTitle: Authorization Data Flow with Oso Local Authorization
    accDescr: A diagram showing how Oso local authorization works
    participant O as  🐻‍❄️Oso
    participant A as 💻 Your App
    participant D as 📇 Your Database
    A->>O: Can Alice add an item?
    O->>A: Is Alice an admin?
    A->>D: Is Alice an admin?
    D->>A: Yes
```

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 supports PostgreSQL and MySQL.

### Support for Other Databases

We also provide a version of Local Authorization that works with non-relational, document-based data stores such as MongoDB, Pinecone, and Elasticsearch. This version returns a datastore-agnostic response that can be translated into a native query for your specific data store. Local Authorization for document-based data stores is currently in beta.

If you are interested in trying this feature, or need support for a different database, contact us. Sharing your use case helps us prioritize future integrations.

<Feedback title={false} defaultMessage="I'm interested in learning more about database options for Local Authorization." />

## When to Use Local Authorization

* Your service uses a PostgreSQL or MySQL database

* All data needed to make authorization decisions is available:

  * In the PostgreSQL or MySQL database
  * Through [centralized authorization data](/develop/facts/overview)

  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:

      ```polar theme={null}
      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](/develop/facts/overview).

## 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](#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](/develop/enforce/list-filtering#local-list-filtering).

## 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:

```yaml theme={null}
# 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>
```

For MySQL, add `engine: mysql` and `version: 1` at the top of the config file. See the [example](#example) below.

### `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

```yaml theme={null}
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:

```sql theme={null}
-- invalid: too many columns
SELECT issue.id, 'parent', issue.parent_repo
```

```sql theme={null}
-- 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):

```yaml theme={null}
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):

```yaml theme={null}
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](https://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt)). 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:

  ```sql theme={null}
  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

<Tabs>
  <Tab title="PostgreSQL">
    ```yaml theme={null}
    facts:
      has_relation(Issue:_, parent, Repository:_):
        query: SELECT id, repository FROM issues

    sql_types:
      Issue: UUID
      Repository: UUID
    ```
  </Tab>

  <Tab title="MySQL">
    ```yaml theme={null}
    engine: mysql
    version: 1

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

    sql_types:
      Issue: UUID
      Repository: UUID
    ```
  </Tab>
</Tabs>

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](/reference/sdks/install).

Include this check as part of your CI/CD pipeline. For more
guidance, see [CI and Testing](/deploy/ci-cd).

## Local Check API

After configuring Local Authorization, your application can ask Oso Cloud to generate SQL that applies authorization logic using both:

* **Centralized facts** stored in Oso Cloud, and
* **Local data** stored in your application’s database.

Each Local Check API method returns SQL that you execute directly against your database. All methods are available through the [Client SDK](/reference/sdks/overview).

1. **actionsLocal** — Query available actions

Generates SQL that returns the set of actions an actor is allowed to perform on a resource.

OpenAPI: [POST /actions\_query](https://www.osohq.com/docs/reference/api/local-check-api/post-actions_query)

2. **authorizeLocal** — Check a specific permission

Generates SQL that returns a boolean indicating whether an actor can perform an action on a resource.

OpenAPI: [POST /authorize\_query](https://www.osohq.com/docs/reference/api/local-check-api/post-authorize_query)

3. **evaluateLocal** — Evaluate an arbitrary authorization query

Generates SQL for a Query API expression (e.g., field-level checks, custom predicates).

OpenAPI: [POST /evaluate\_query\_local](https://www.osohq.com/docs/reference/api/local-check-api/post-evaluate_query_local)

4. **listLocal** — Filter a resource list

Generates a SQL condition that filters a database query to only resources the actor is allowed to access.

OpenAPI: [POST /list\_query](https://www.osohq.com/docs/reference/api/local-check-api/post-list_query)

### Centralized Facts Still Apply

Local Authorization incorporates any [centralized facts](/develop/facts/overview) stored in Oso Cloud. These facts are merged with local data when producing SQL and affect all Local Check API results.

## Guides

* [List filtering](/develop/enforce/list-filtering)

## Related Content

* For a comprehensive example of Local Authorization, see [Ruby on Rails list filtering sample app](https://github.com/osohq/rails_list_filtering_sample_app)
* [Facts: The Oso Cloud Data Model](/develop/facts/overview)
* [Reference Documentation](/reference/sdks/local-authorization)
* [Local Authorization Guide](/reference/sdks/local-authorization)
