Skip to main content

Concepts

The OpenFGA service answers authorization checks by determining whether a relationship exists between an object and a user. Checks reference your authorization model against your relationship tuples for authorization authority. Below are explanations of basic FGA concepts, like type and authorization model, and a playground to test your knowledge.

What Is A Type?

A type is a string. It defines a class of objects with similar characteristics.

The following are examples of types:

  • workspace
  • repository
  • organization
  • document

What Is A Type Definition?

A type definition defines all possible relations a user or another object can have in relation to this type.

Below is an example of a type definition:


type document
relations
define viewer: [user]
define commenter: [user]
define editor: [user]
define owner: [user]

What Is An Authorization Model?

An authorization model combines one or more type definitions. This is used to define the permission model of a system.

Below is an example of an authorization model:

model
schema 1.1

type document
relations
define viewer: [domain#member, user]
define commenter: [domain#member, user]
define editor: [domain#member, user]
define owner: [domain#member, user]

type domain
relations
define member: [user]

type user

Together with relationship tuples, the authorization model determines whether a relationship exists between a user and an object.

OpenFGA uses two different syntaxes to define the authorization model:

Click here to learn more about the OpenFGA Configuration Language.

What Is A Store?

A store is an OpenFGA entity used to organize authorization check data.

Each store contains one or more versions of an authorization model and can contain various relationship tuples. Store data cannot be shared across stores; we recommended storing all data that may be related or affect your authorization result in a single store.

Separate stores can be created for separate authorization needs or isolated environments, e.g. development/prod.

What Is An Object?

An object represents an entity in the system. Users' relationships to it are defined by relationship tuples and the authorization model.

An object is a combination of a type and an identifier.

For example:

  • workspace:fb83c013-3060-41f4-9590-d3233a67938f
  • repository:auth0/express-jwt
  • organization:org_ajUc9kJ
  • document:new-roadmap

User, relation and object are the building blocks for relationship tuples.

For an example, see Direct Access.

What Is A User?

A user is an entity in the system that can be related to an object.

A user is is a combination of a type, an identifier, and an optional relation.

For example,

  • any identifier: e.g. user:anne or user:4179af14-f0c0-4930-88fd-5570c7bf6f59
  • any object: e.g. workspace:fb83c013-3060-41f4-9590-d3233a67938f, repository:auth0/express-jwt or organization:org_ajUc9kJ
  • a group or a set of users (also called a userset): e.g. organization:org_ajUc9kJ#members, which represents the set of users related to the object organization:org_ajUc9kJ as member
  • everyone, using the special syntax: *

User, relation and object are the building blocks for relationship tuples.

For more information, see Direct Access.

What Is A Relation?

A relation is a string defined in the type definition of an authorization model. Relations define a possible relationship between an object (of the same type as the type definition) and a user in the system.

Examples of relation:

  • User can be a reader of a document
  • Team can administer a repo
  • User can be a member of a team

What Is A Relation Definition?

A relation definition lists the conditions or requirements under which a relationship is possible.

For example:

  • editor describing a possible relationship between a user and an object in the document type allows the following:
    • user identifier to object relationship: the user id anne of type user is related to the object document:roadmap as editor
    • object to object relationship: the object application:ifft is related to the object document:roadmap as editor
    • userset to object relationship: the userset organization:auth0.com#member is related to document:roadmap as editor
      • indicates that the set of users who are related to the object organization:auth0.com as member are related to the object document:roadmap as editors
      • allows for potential solutions to use-cases like sharing a document internally with all members of a company or a team
    • everyone to object relationship: everyone (*) is related to document:roadmap as editor
      • this is how one could model publicly editable documents

These would be defined in the authorization model:


type document
relations
define viewer: [user]
define commenter: [user]
define editor: [user]
define owner: [user]

type user
info

There are four relations in the document type configuration: viewer, commenter, editor and owner.

User, relation and object are the building blocks for relationship tuples.

For an example, see Direct Access.

A directly related user type is an array specified in the type definition to indicate which types of users can be directly related to that relation.

For the following model, only relationship tuples with user of type user may be assigned to document.


type document
relations
define viewer: [user]

A relationship tuple with user user:anne or user:3f7768e0-4fa7-4e93-8417-4da68ce1846c may be written for objects with type document and relation viewer, so writing {"user": "user:anne","relation":"viewer","object":"document:roadmap"} succeeds. A relationship tuple with a disallowed user type for the viewer relation on objects of type document - for example workspace:auth0 or folder:planning#editor - will be rejected, so writing {"user": "folder:product","relation":"viewer","object":"document:roadmap"} will fail. This affects only relations that are directly related and have direct relationship type restrictions in their relation definition.

What is a Condition?

A condition is a function composed of one or more parameters and an expression. Every condition evaluates to a boolean outcome, and expressions are defined using Google's Common Expression Language (CEL).

In the following snippet less_than_hundred defines a Condition that evaluates to a boolean outcome. The provided parameter x, defined as an integer type, is used in the boolean expression x < 100. The condition returns a truthy outcome if the expression returns a truthy outcome, but is otherwise false.

condition less_than_hundred(x: int) {
x < 100
}

What Is A Relationship Tuple?

A relationship tuple is a base tuple/triplet consisting of a user, relation, and object. Tuples may add an optional condition, like Conditional Relationship Tuples. Relationship tuples are written and stored in OpenFGA.

A relationship tuple consists of:

  • a user, e.g. user:anne, user:3f7768e0-4fa7-4e93-8417-4da68ce1846c, workspace:auth0 or folder:planning#editor
  • a relation, e.g. editor, member or parent_workspace
  • an object, e.g repo:auth0/express_jwt, domain:auth0.com or channel:marketing
  • a condition (optional), e.g. {"condition": "in_allowed_ip_range", "context": {...}}

An authorization model, together with relationship tuples, determinate whether a relationship exists between a user and an object.

Relationship tuples are usually shown in the following format:

[{
"user": "user:anne",
"relation": "editor",
"object": "document:new-roadmap"
}]

For more information, see Direct Access.

What Is A Conditional Relationship Tuple?

A conditional relationship tuple is a relationship tuple that represents a relationship conditioned upon the evaluation of a condition.

If a relationship tuple is conditioned, then that condition must to a truthy outcome for the relationship tuple to be permissible.

The following relationship tuple is a conditional relationship tuple because it is conditioned on less_than_hundred. If the expression for less_than_hundred is defined as x < 100, then the relationship is permissible because the expression - 20 < 100 - evaluates to a truthy outcome.

[{
"user": "user:anne",
"relation": "editor",
"object": "document:new-roadmap",
"condition": {
"name": "less_than_hundred",
"context": {
"x": 20
}
}
}]

What Is A Relationship?

A relationship is the realization of a relation between a user and an object.

An authorization model, together with relationship tuples, determine whether a relationship exists between a user and an object. Relationships may be direct or implied.

What Are Direct And Implied Relationships?

A direct relationship (R) between user X and object Y means the relationship tuple (user=X, relation=R, object=Y) exists, and the OpenFGA authorization model for that relation allows the direct relationship because of direct relationship type restrictions).

An implied (or computed) relationship (R) exists between user X and object Y if user X is related to an object Z that is in a direct or implied relationship with object Y, and the OpenFGA authorization model allows it.

  • user:anne has a direct relationship with document:new-roadmap as viewer if the type definition allows it with direct relationship type restrictions, and one of the following relationship tuples exist:

    • [// Anne of type user is directly related to the document
      {
      "_description": "Anne of type user is directly related to the document",
      "user": "user:anne",
      "relation": "viewer",
      "object": "document:new-roadmap"
      }]
    • [// Everyone (`*`) of type user is directly related to the document
      {
      "_description": "Everyone (`*`) of type user is directly related to the document",
      "user": "*",
      "relation": "viewer",
      "object": "document:new-roadmap"
      }]
    • [// The userset is directly related to this document
      {
      "_description": "The userset is directly related to this document",
      "user": "team:product#member",
      "relation": "viewer",
      "object": "document:new-roadmap"
      }// AND Anne of type user is a member of a userset (e.g. team:product#member)
      {
      "_description": "AND Anne of type user is a member of a userset (e.g. team:product#member)",
      "user": "user:anne",
      "relation": "member",
      "object": "team:product#member"
      }]
  • user:anne has an implied relationship with document:new-roadmap as viewer if the type definition allows it, and the presence of relationship tuples satisfying the relationship exist.

    For example, assume the following type definition:


    type document
    relations
    define viewer: [user] or editor
    define editor: [user]

    And assume the following relationship tuple exists in the system:

    [{
    "user": "user:anne",
    "relation": "editor",
    "object": "document:new-roadmap"
    }]

    In this case, the relationship between user:anne and document:new-roadmap as a viewer is implied from the direct editor relationship user:anne has with that same document. Thus, the following request to check whether a viewer relationship exists between user:anne and document:new-roadmap will return true.

    Initialize the SDK
    // ApiTokenIssuer, ApiAudience, ClientId and ClientSecret are optional.
    // import the SDK
    const { OpenFgaClient } = require('@openfga/sdk');

    // Initialize the SDK with no auth - see "How to setup SDK client" for more options
    const fgaClient = new OpenFgaClient({
    apiUrl: process.env.FGA_API_URL, // required, e.g. https://api.fga.example
    storeId: process.env.FGA_STORE_ID,
    authorizationModelId: process.env.FGA_MODEL_ID, // Optional, can be overridden per request
    });

    // Run a check
    const { allowed } = await fgaClient.check({
    user: 'user:anne',
    relation: 'viewer',
    object: 'document:new-roadmap',
    }, {
    authorization_model_id: '01HVMMBCMGZNT3SED4Z17ECXCA',
    });

    // allowed = true

What Is A Check Request?

A check request is a call to the OpenFGA check endpoint, returning whether the user has a certain relationship with an object.

Check requests use the check methods in the OpenFGA SDKs (JavaScript SDK/Go SDK/.NET SDK) by manually calling the check endpoint using curl or in your code. The check endpoint responds with { "allowed": true } if a relationship exists, and with { "allowed": false } if the relationship does not.

For example, the following will check whether anne of type user has a viewer relation to document:new-roadmap:

Initialize the SDK
// ApiTokenIssuer, ApiAudience, ClientId and ClientSecret are optional.
// import the SDK
const { OpenFgaClient } = require('@openfga/sdk');

// Initialize the SDK with no auth - see "How to setup SDK client" for more options
const fgaClient = new OpenFgaClient({
apiUrl: process.env.FGA_API_URL, // required, e.g. https://api.fga.example
storeId: process.env.FGA_STORE_ID,
authorizationModelId: process.env.FGA_MODEL_ID, // Optional, can be overridden per request
});

// Run a check
const { allowed } = await fgaClient.check({
user: 'user:anne',
relation: 'viewer',
object: 'document:new-roadmap',
}, {
authorization_model_id: '01HVMMBCMGZNT3SED4Z17ECXCA',
});

// allowed = true

For more information, see the Relationship Queries page and the official Check API Reference.

What Is A List Objects Request?

A list objects request is a call to the OpenFGA list objects endpoint that returns all objects of a given type that a user has a specified relationship with.

List object requests are completed using the listobjects methods in the OpenFGA SDKs (JavaScript SDK/Go SDK/.NET SDK) by manually calling the list objects endpoint using curl or in your code.

The list objects endpoint responds with a list of objects for a given type that the user has the specified relationship with.

For example, the following returns all the objects with document type for which anne of type user has a viewer relation with:

Initialize the SDK
// ApiTokenIssuer, ApiAudience, ClientId and ClientSecret are optional.
// import the SDK
const { OpenFgaClient } = require('@openfga/sdk');

// Initialize the SDK with no auth - see "How to setup SDK client" for more options
const fgaClient = new OpenFgaClient({
apiUrl: process.env.FGA_API_URL, // required, e.g. https://api.fga.example
storeId: process.env.FGA_STORE_ID,
authorizationModelId: process.env.FGA_MODEL_ID, // Optional, can be overridden per request
});
const response = await fgaClient.listObjects({
user: "user:anne",
relation: "viewer",
type: "document",
}, {
authorization_model_id: "01HVMMBCMGZNT3SED4Z17ECXCA",
});
// response.objects = ["document:otherdoc", "document:planning"]

For more information, see the Relationship Queries page and the List Objects API Reference.

What Is A List Users Request?

A list users request is a call to the OpenFGA list users endpoint that returns all users of a given type that have a specified relationship with an object.

List users requests are completed using the relevant ListUsers method in SDKs, the fga query list-users command in the CLI, or by manually calling the ListUsers endpoint using curl or in your code.

The list users endpoint responds with a list of users for a given type that have the specificed relationship with an object.

For example, the following returns all the users of type user that have the viewer relationship for document:planning:

Initialize the SDK
// ApiTokenIssuer, ApiAudience, ClientId and ClientSecret are optional.
// import the SDK
const { OpenFgaClient } = require('@openfga/sdk');

// Initialize the SDK with no auth - see "How to setup SDK client" for more options
const fgaClient = new OpenFgaClient({
apiUrl: process.env.FGA_API_URL, // required, e.g. https://api.fga.example
storeId: process.env.FGA_STORE_ID,
authorizationModelId: process.env.FGA_MODEL_ID, // Optional, can be overridden per request
});
const response = await fgaClient.listUsers({
object: {
type: "document",
id: "planning"
},
user_filters: [{
type: "user"
}],
relation: "viewer",
}, {
authorization_model_id: "01HVMMBCMGZNT3SED4Z17ECXCA",
});
// response.users = [{"object":{"type":"user","id":"anne"}},{"object":{"type":"user","id":"beth"}}]

For more information, see the the ListUsers API Reference.

What Are Contextual Tuples?

Contextual tuples are tuples that can be added to a check request and only exist within the context of that particular request.

Similar to relationship tuples, contextual tuples are composed of a user, relation and object. Unlike relationship tuples, they are not written to the store. However, if contextual tuples are sent alongside a check request in the context of a particular check request, they are treated if they had been written in the store.

For more information, see Contextual and Time-Based Authorization, Authorization Through Organization Context and Check API Request Documentation.

What Is Type Bound Public Access?

In OpenFGA, type bound public access (represented by <type>:*) is a special OpenFGA syntax meaning "every object of [type]" when invoked as a user within a relationship tuple. For example, user:* represents every object of type user , including those not currently present in the system.

For example, to indicate document:new-roadmap is publicly writable (in other words, has everyone of type user as an editor, add the following relationship tuple:

[{
"user": "user:*",
"relation": "editor",
"object": "document:new-roadmap"
}]

Note: <type>:* cannot be used in the relation or object properties. In addition, <type>:* cannot be used as part of a userset in the tuple's user field. For more information, see Modeling Public Access and Advanced Modeling: Modeling Google Drive.

Authorization Concepts

Learn about Authorization.

Configuration Language

Learning about the FGA configuration language

Direct access

Get started with modeling your permission system in OpenFGA