OpenFGA Documentation

repository·main·Indexed 26 days ago

https://github.com/openfga/openfga

A high-performance authorization engine inspired by Google Zanzibar for modeling and enforcing fine-grained access control. OpenFGA provides HTTP and gRPC APIs and supports PostgreSQL, MySQL, and SQLite storage backends. It includes an experimental implementation of the Authorization API 1.0 (AuthZEN) for integration with Identity Providers and Gateways, as well as a Check API for relationship queries using directed graph traversal and model rewrites.

Tokens
31K
Snippets
42
Records
177
Agent score
90%

What's inside OpenFGA

  1. Overview of OpenFGA Caching Types

    main

    OpenFGA uses several complementary in-memory caching mechanisms to improve performance and reduce database load:

    1. Check Query Cache: Caches results of sub-problems within Check API requests to avoid recomputation.
    2. Check Iterator Cache: Caches database query results (iterators) used during Check operations.
    3. List Objects Iterator Cache: Caches database query results (iterators) used during List Objects requests.
    4. Cache Controller: A background process that periodically invalidates cache entries based on recent writes to the store.
    5. Authorization Model & Typesystem Cache: Always-on caches for authorization models and their compiled typesystems.

    Important Considerations:

    • Consistency Bypass: If a request specifies the HIGHER_CONSISTENCY consistency preference, all caches are bypassed except for the Authorization Model and Typesystem caches.
    • Replica Isolation: Caches are in-memory and not shared between service replicas. Effectiveness depends on request patterns hitting the same replica.
  2. Understand OpenFGA's AuthZEN Implementation

    main

    OpenFGA provides an experimental implementation of the Authorization API 1.0. This implementation is designed to allow easy integration with products that natively support the AuthZen protocol, such as Identity Providers and Gateways.

    To validate the implementation, you can use the AuthZen Interop Examples for OpenFGA repository, which contains interop scenarios for testing Policy Decision Points (PDPs).

  3. Understand OpenFGA Check Implementation Behavior

    main

    The OpenFGA Check API uses a layered resolution strategy to evaluate permissions. The system includes built-in protections and optimizations:

    Cycle Detection

    To prevent stack overflows caused by cyclical evaluation paths (e.g., a group being a member of itself), OpenFGA tracks visited subproblems. If a subproblem is encountered that is already present in the current evaluation callstack, the system avoids re-dispatching it.

    Layered Resolver Composition

    OpenFGA uses a CheckResolver interface to layer different resolution behaviors. When a Check request is received, it typically passes through these layers in order:

    1. CachedCheckResolver: Checks a local cache for recently evaluated subproblems. If a match is found, it returns the result immediately.
    2. DispatchThrottledCheckResolver: Throttles requests if the number of dispatches for subproblems exceeds a configured threshold, preventing a single request from saturating system resources.
    3. LocalChecker: The core engine. It implements the primary algorithm, follows relationship rewrite rules, performs database lookups, and expands subproblems. If new subproblems are found, it delegates back through the layers (loopback mechanism).
  4. Understand Check Iterator Cache Entry Types

    main

    The Check Iterator Cache uses three specific types of entries to cache database query results:

    1. Read (IC + "READ"): Caches direct tuple lookups for a specific object and relation, optionally filtered by user.
    2. Read Starting With User (IC + "RSWU"): Caches reverse lookups that find all tuples where a specific user appears as the subject.
    3. Read Userset Tuples (IC + "RUT"): Caches tuples where the user field is a userset (e.g., organization:acme#member), used for resolving relations that accept usersets as assignable types.
  5. Understand the Check API behavior

    main

    The Check API determines if a specific user/subject has a particular relationship with a given object.

    Internally, the Check algorithm performs a traversal on a directed graph (often a tree). It starts at a specified object#relation and expands relationships according to the FGA model's rewrite rules until the target user/subject is found or all possible paths have been exhausted.

    Rewrites allow you to model complex semantics, such as:

    • Hierarchical relationships: A user's permission on a parent object (e.g., a folder) can grant them permissions on a child object (e.g., a document).
    • Set operations: Using or (union), and (intersection), or exclusion to combine multiple relationship paths.
  6. Quickstart: Run OpenFGA with in-memory storage

    main

    For quick local evaluation, you can run OpenFGA using Docker with the default in-memory storage engine.

    Warning: In-memory storage is ephemeral; all data will be lost when the service stops. This is not for production use.

    1. Run the Docker container:
    docker run -p 8080:8080 -p 3000:3000 openfga/openfga run
    1. Create a new store using curl:
    curl -X POST 'localhost:8080/stores' \
      --header 'Content-Type: application/json' \
      --data-raw '{"name": "openfga-demo"}'
    docker run -p 8080:8080 -p 3000:3000 openfga/openfga run
    
    curl -X POST 'localhost:8080/stores' \
      --header 'Content-Type: application/json' \
      --data-raw '{"name": "openfga-demo"}'
  7. Understand the ListObjects API execution phases

    main

    The ListObjects API operates in two distinct phases to resolve authorization models represented as directed graphs:

    1. Phase 1 (Graph Traversal/Expansion): The engine performs a process similar to a Breadth-First Search (BFS) starting from the source node to reach the target object type and relation. It explores paths by reading tuples and identifying objects of the target type. Objects found during this expansion that require further validation are marked as "candidates".
    2. Phase 2 (Candidate Validation): For every candidate object identified in Phase 1, the engine performs a Check call. If Check returns allowed=true, the object is included in the final response.

    Note: During Phase 1, if a relation is defined as an intersection or exclusion, the engine prunes the graph by removing incoming edges (except for the primary edge defining the intersection/exclusion) before traversing.

  8. Specify Authorization Model ID via HTTP header

    main

    Because the AuthZen specification does not include model versioning, OpenFGA uses a custom HTTP header to allow pinning a specific authorization model. When making requests, include the following header:

    Openfga-Authorization-Model-Id: <MODEL_ID>

    This approach ensures the request body remains compliant with the AuthZen spec while providing model-specific context.

  9. Handle properties in AuthZEN requests

    main

    AuthZEN allows properties objects on subject, resource, and action. Since OpenFGA only has a single context object for ABAC conditions, these properties are automatically merged into the OpenFGA context using namespaced keys with an underscore (_) as the separator.

    Mapping Convention:

    • subject.properties.department $\rightarrow$ subject_department
    • resource.properties.classification $\rightarrow$ resource_classification
    • action.properties.severity $\rightarrow$ action_severity

    Important Notes:

    • Model Requirement: Authorization models must reference these properties using the namespaced key (e.g., context["subject_department"]) rather than the original property name.
    • Precedence: If a key conflict occurs between properties and the request-level context, the request-level context takes precedence.
  10. Configure and Use the OpenFGA Playground

    main

    The Playground allows you to model, visualize, and test authorization setups locally. It is available by default at http://localhost:3000/playground.

    Note: The Playground is for local development only and is configured to connect to an OpenFGA server running on localhost.

    Common Playground Commands

    Disable the Playground:

    ./openfga run --playground-enabled=false

    Change the Playground Port:

    ./openfga run --playground-enabled --playground-port 3001

    Configure Playground Connection via Environment Variables: If your OpenFGA server is running on a different address (e.g., in Docker), use OPENFGA_HTTP_ADDR to tell the Playground where to find the server.

    Example starting OpenFGA on port 4000 and configuring the Playground to find it:

    docker run -e OPENFGA_PLAYGROUND_ENABLED=true \
    -e OPENFGA_HTTP_ADDR=0.0.0.0:4000 \
    -p 4000:4000 -p 3000:3000 openfga/openfga run
    # Disable playground
    ./openfga run --playground-enabled=false
    
    # Change port
    ./openfga run --playground-enabled --playground-port 3001
    
    # Configure connection address for Docker
    docker run -e OPENFGA_PLAYGROUND_ENABLED=true \
    -e OPENFGA_HTTP_ADDR=0.0.0.0:4000 \
    -p 4000:4000 -p 3000:3000 openfga/openfga run
  11. Run the release PR script

    main

    Before running the script, ensure you are authenticated with GitHub. You can check your status with gh auth status. To log in using SSH via a browser, use:

    gh auth login --hostname github.com --git-protocol ssh --skip-ssh-key --web

    To create a release pull request, execute the script and pass the target version using the -t flag:

    ./scripts/create-release-pr.sh -t <version>

    Note: If the tag already exists or the branch has already been used, the script will cancel and require manual intervention.

    ./scripts/create-release-pr.sh -t 1.9.2