Skip to main content
Attribute-Based Access Control (ABAC) extends traditional relationship-based access control by incorporating attributes into authorization decisions. While Role-Based Access Control (RBAC) answers “does this user have this role?”, ABAC answers questions like “does this user have this role AND is their email verified?” or “can this user access this resource given their current session context?”. With OpenFGA, you can model ABAC patterns using attributes that are stored in the system or attributes that are provided dynamically with each authorization request. This guide covers two main approaches:
  1. Stored attributes: Attributes persisted in OpenFGA as part of your relationship data
  2. Request-time attributes: Dynamic attributes sent with each authorization check request

Stored Attribute Data

When attributes are relatively static and can be stored alongside your relationship data, you can model them directly in OpenFGA. This approach works well for attributes like “email verified”, “SSO enabled”, or “account tier”. Consider a scenario where you want to allow users to perform an action only if their organization has SSO enabled. Below are three patterns for modeling this requirement.

Modeling Attributes as Relations

Using user:* as a Boolean Flag

The simplest approach for boolean attributes is using the Public Access pattern. By assigning user:* to a relation, you effectively create a boolean flag that applies to all users. When to use this approach:
  • You need a simple true/false flag
  • The attribute applies uniformly to all users in a context
  • You want minimal tuple overhead

Using Self-Relations

An alternative approach is to use a self-referential relation, where an object points to itself to indicate an attribute is set. This pattern makes the relationship semantics more explicit. When to use this approach:
  • You want clearer semantics about what the attribute represents
  • The attribute is a property of the object itself rather than a universal grant
  • You prefer explicit object references over wildcards

Storing Attributes in Conditional Tuple Context

For attributes that require typed values beyond simple booleans, you can store the attribute value directly in the condition context of a relationship tuple. This approach combines the relationship with its associated attribute data. When to use this approach:
  • You need typed attribute values (strings, numbers, etc.)
  • The attribute is tightly coupled to a specific relationship
  • You want to avoid additional tuples for attribute storage

Request-Time Attribute Data

Some attributes cannot be stored because they are dynamic and change with each request. Common examples include the current time, client IP address, or the user’s current session context. For these scenarios, you provide the attribute values at request time. For time-based, IP-based conditions and more, see the Conditions documentation for detailed examples.

Multi-Organization Session Context

A common use case is when users can authenticate to multiple organizations but should only access resources belonging to their currently active organization. When accessing content, you need to verify the content belongs to the organization the user is currently logged into. You can achieve this with either contextual tuples or conditional relationship tuples.

Using Contextual Tuples

With this approach, you add a relation (e.g., user_in_context) that is not stored but sent as a contextual tuple with each request. This contextual tuple represents the user’s current session context. When to use this approach:
  • Session context is determined entirely at request time
  • You want to keep stored tuples simple and context-free
  • The context applies across multiple relation checks

Using Conditional Relationship Tuples

Instead of adding contextual tuples, you can attach conditions to your stored relationship tuples and provide the context values at request time. The condition compares stored values against request-time values. When to use this approach:
  • You want to avoid sending contextual tuples with every request
  • The condition logic involves comparing stored and request-time values
  • You prefer conditions over additional relations in your model

Choosing the Right Approach

When deciding between these approaches, consider:
  • Data volatility: Use stored attributes for stable data, request-time attributes for dynamic data
  • Model complexity: Start with simpler patterns (like user:*) and evolve to more complex ones as needed
  • Attribute types: Use conditions when you need typed values beyond booleans
Check out these related resources for more information about ABAC patterns in OpenFGA

Conditions

Learn how to use conditions for time-based, IP-based, and other dynamic checks.

Contextual Tuples

Understand how to send dynamic relationship data with each request.

Public Access

Learn about the user:* pattern for granting access to everyone.

Modular Authorization Models

Learn how to break down your authorization model into modules.
Last modified on September 28, 2026