Skip to main content

Auth0 Fine Grained Authorization (FGA) Concepts

note
Auth0 Fine Grained Authorization (FGA) is the early-stage product we are building at Auth0 to solve fine-grained authorization at scale. Sign up for the Developer Community Preview to try it out, and join our Discord community if you are interested in learning more about our plans.

Please note that at this point in time, it is not considered production-ready and does not come with any SLAs; availability and uptime are not guaranteed. Limitations of Auth0 FGA during the Developer Community Preview can be found here.

The Auth0 FGA service answers authorization checks by determining whether a relationship exists between an object and a user. Checks takes into consideration the authorization model of the system and the relationship tuples present in the system at that time in order to make a decision.

In this guide you will learn about the most relevant FGA concepts, such as a type or an authorization model, and you will be able to explore them using the FGA playground.

The Playground

Try this guide out on the Auth0 Playground

What Is A Type?

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

Examples of types:

  • workspace
  • repository
  • organization
  • document

What Is A Type Definition?

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

Code snippet 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 is a combination of one or more type definitions. This is used to define the permission model of a system.

Code snippet 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

Authorization model, together with relationship tuples, allow determination of whether a relationship exists between a user and an object.

The Auth0 Fine Grained Authorization (FGA) service has two different syntaxes to define the authorization model:

  • A JSON syntax accepted by the Auth0 FGA API that follows closely the original syntax discussed in the Zanzibar Paper. See Equivalent Zanzibar Concepts.
  • A DSL that we believe is easier to use and is used in the Auth0 FGA Playground to help with modeling. This is translated to the API-supported syntax before being sent to the API.

Learn more about the Auth0 FGA Configuration Language.

What Is A Store?

A "store" is a Auth0 Fine Grained Authorization (FGA) entity used for organizing data needed to answer authorization checks.

Each store contains one or more versions of an authorization model and may contain various relationship tuples.

Store data such as the authorization model and relationship tuples cannot be shared across stores, so it is highly recommended to store all data that may be related and may affect your authorization result in a single store.

For completely separate authorization needs or isolated environments where data from one should not affect another (e.g. development/prod), you may want to create separate stores.

What Is An Object?

An object represents an entity in the system. We can define how various users have a relationship to it through 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 more information, please 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, please see Direct Access.

What Is A Relation?

A relation is a string defined in the type definition of an authorization model that defines the possibility of a 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 this relationship would be 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
      • indicating 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
      • this 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 as such:

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

In the configuration of the document type, we have four relations: viewer, commenter, editor and owner.

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

For more information, please see Direct Access.

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

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

type document
relations
define viewer: [user]

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"} will succeed. Relationship tuple writes with user type that is not allowed 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 will affect only relations that are directly related and have the direct relationship type restrictions in their relation definition.

What Is A Relationship Tuple?

A relationship tuple is a tuple consisting of a user, relation and object stored in Auth0 FGA.

A relationship tuple consists of a:

  • user, e.g. user:anne, user:3f7768e0-4fa7-4e93-8417-4da68ce1846c, workspace:auth0 or folder:planning#editor
  • relation, e.g. editor, member or parent_workspace
  • object, e.g repo:auth0/express_jwt, domain:auth0.com or channel:marketing

An authorization model, together with relationship tuples, allow the determination of whether a relationship exists between a user and an object.

Throughout the documentation, you will encounter relationship tuples represented as:

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

For more information, please see Direct Access.

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, allow the determination of whether a relationship exists between a user and an object. Relationships may be classified as 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 Auth0 FGA authorization model for that relation allows this direct relationship (by use 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 Auth0 FGA authorization model allows it.

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

    • [
      // 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
      {
      "user": "*",
      "relation": "viewer",
      "object": "document:new-roadmap",
      },
      ]
    • [
      // 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)
      {
      "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, assuming the following type definition:

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

    And assuming 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
    // Checkout the "How to Setup the SDK Client" page for more details.
    const { CredentialsMethod, OpenFgaClient } = require('@openfga/sdk'); // OR import { CredentialsMethod, OpenFgaClient } from '@openfga/sdk';

    // Ensure the environment variables are set
    // FGA_API_SCHEME = 'https'
    // FGA_API_HOST = 'api.us1.fga.dev' for Dev Preview and Early Access / 'api.playground.fga.dev' for the FGA Playground
    // FGA_STORE_ID = 'YOUR_STORE_ID' - Get this from your store settings in the dashboard, refer to the "How to get your API Keys" page
    // FGA_MODEL_ID = 'YOUR_MODEL_ID' - optional, can be overridden per request, helps reduce latency
    // FGA_API_TOKEN_ISSUER = 'fga.us.auth0.com' for Dev Preview and Early Access / not needed for the FGA Playground
    // FGA_API_AUDIENCE = 'https://api.us1.fga.dev/' for Dev Preview and Early Access / not needed for the FGA Playground
    // FGA_CLIENT_ID = 'YOUR_CLIENT_ID' - Get this from your store settings in the dashboard, refer to the "How to get your API Keys" page / not needed for the FGA Playground
    // FGA_CLIENT_SECRET = 'YOUR_CLIENT_SECRET' - Get this from your store settings in the dashboard, refer to the "How to get your API Keys" page / not needed for the FGA Playground

    const fgaClient = new OpenFgaClient({
    apiScheme: process.env.FGA_API_SCHEME,
    apiHost: process.env.FGA_API_HOST,
    storeId: process.env.FGA_STORE_ID,
    authorizationModelId: process.env.FGA_MODEL_ID,
    credentials: { // Credentials are not needed if connecting to the Playground API
    method: CredentialsMethod.ClientCredentials,
    config: {
    apiTokenIssuer: process.env.FGA_API_TOKEN_ISSUER,
    apiAudience: process.env.FGA_API_AUDIENCE,
    clientId: process.env.FGA_CLIENT_ID,
    clientSecret: process.env.FGA_CLIENT_SECRET,
    },
    },
    });

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

    // allowed = true

What Is A Check Request?

A check request is a call to the Auth0 Fine Grained Authorization (FGA) check endpoint that returns whether the user has a certain relationship with an object.

This can be done using the check methods in the Auth0 FGA 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
// Checkout the "How to Setup the SDK Client" page for more details.
const { CredentialsMethod, OpenFgaClient } = require('@openfga/sdk'); // OR import { CredentialsMethod, OpenFgaClient } from '@openfga/sdk';

// Ensure the environment variables are set
// FGA_API_SCHEME = 'https'
// FGA_API_HOST = 'api.us1.fga.dev' for Dev Preview and Early Access / 'api.playground.fga.dev' for the FGA Playground
// FGA_STORE_ID = 'YOUR_STORE_ID' - Get this from your store settings in the dashboard, refer to the "How to get your API Keys" page
// FGA_MODEL_ID = 'YOUR_MODEL_ID' - optional, can be overridden per request, helps reduce latency
// FGA_API_TOKEN_ISSUER = 'fga.us.auth0.com' for Dev Preview and Early Access / not needed for the FGA Playground
// FGA_API_AUDIENCE = 'https://api.us1.fga.dev/' for Dev Preview and Early Access / not needed for the FGA Playground
// FGA_CLIENT_ID = 'YOUR_CLIENT_ID' - Get this from your store settings in the dashboard, refer to the "How to get your API Keys" page / not needed for the FGA Playground
// FGA_CLIENT_SECRET = 'YOUR_CLIENT_SECRET' - Get this from your store settings in the dashboard, refer to the "How to get your API Keys" page / not needed for the FGA Playground

const fgaClient = new OpenFgaClient({
apiScheme: process.env.FGA_API_SCHEME,
apiHost: process.env.FGA_API_HOST,
storeId: process.env.FGA_STORE_ID,
authorizationModelId: process.env.FGA_MODEL_ID,
credentials: { // Credentials are not needed if connecting to the Playground API
method: CredentialsMethod.ClientCredentials,
config: {
apiTokenIssuer: process.env.FGA_API_TOKEN_ISSUER,
apiAudience: process.env.FGA_API_AUDIENCE,
clientId: process.env.FGA_CLIENT_ID,
clientSecret: process.env.FGA_CLIENT_SECRET,
},
},
});

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

// allowed = true

For more information, please 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 Auth0 Fine Grained Authorization (FGA) list objects endpoint that returns all the objects of a given type that a user has a specified relationship with.

This can be done using the listobjects methods in the Auth0 FGA 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 will return all the objects with document type for which anne of type user has a viewer relation with:

Initialize the SDK
// Checkout the "How to Setup the SDK Client" page for more details.
const { CredentialsMethod, OpenFgaClient } = require('@openfga/sdk'); // OR import { CredentialsMethod, OpenFgaClient } from '@openfga/sdk';

// Ensure the environment variables are set
// FGA_API_SCHEME = 'https'
// FGA_API_HOST = 'api.us1.fga.dev' for Dev Preview and Early Access / 'api.playground.fga.dev' for the FGA Playground
// FGA_STORE_ID = 'YOUR_STORE_ID' - Get this from your store settings in the dashboard, refer to the "How to get your API Keys" page
// FGA_MODEL_ID = 'YOUR_MODEL_ID' - optional, can be overridden per request, helps reduce latency
// FGA_API_TOKEN_ISSUER = 'fga.us.auth0.com' for Dev Preview and Early Access / not needed for the FGA Playground
// FGA_API_AUDIENCE = 'https://api.us1.fga.dev/' for Dev Preview and Early Access / not needed for the FGA Playground
// FGA_CLIENT_ID = 'YOUR_CLIENT_ID' - Get this from your store settings in the dashboard, refer to the "How to get your API Keys" page / not needed for the FGA Playground
// FGA_CLIENT_SECRET = 'YOUR_CLIENT_SECRET' - Get this from your store settings in the dashboard, refer to the "How to get your API Keys" page / not needed for the FGA Playground

const fgaClient = new OpenFgaClient({
apiScheme: process.env.FGA_API_SCHEME,
apiHost: process.env.FGA_API_HOST,
storeId: process.env.FGA_STORE_ID,
authorizationModelId: process.env.FGA_MODEL_ID,
credentials: { // Credentials are not needed if connecting to the Playground API
method: CredentialsMethod.ClientCredentials,
config: {
apiTokenIssuer: process.env.FGA_API_TOKEN_ISSUER,
apiAudience: process.env.FGA_API_AUDIENCE,
clientId: process.env.FGA_CLIENT_ID,
clientSecret: process.env.FGA_CLIENT_SECRET,
},
},
});
const response = await fgaClient.listObjects({
user: "user:anne",
relation: "viewer",
type: "document",
}, {
authorization_model_id: "1uHxCSuTP0VKPYSnkq1pbb1jeZw",
});
// response.objects = ["document:otherdoc", "document:planning"]

For more information, please see the Relationship Queries page and the official Check 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 this particular check request, they are treated if they had been written in the store.

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

What Is Type Bound Public Access?

In Auth0 Fine Grained Authorization (FGA), type bound public access (represented by <type>:*) is a special Auth0 FGA syntax meaning every object of that type when used 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, in a case where you would like to indicate a certain document document:new-roadmap is publicly writable (i.e. has everyone of type user as an editor), you can add the following relationship tuple:

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

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

Auth0 FGA Concepts

Learn about the Auth0 FGA Concepts

Direct access

Get started with modeling your permission system in Auth0 FGA

Have Feedback?

Join us on the Discord community if you have any questions or suggestions.