Skip to main content

Parent-Child Objects

In OpenFGA, a user's relationship with an object can affect their relationship with another object. For example, an editor of a folder can also be an editor of all documents that folder is a parent of.

When to use

Object-to-object relationships can combine with a configured authorization model to indicate that a user's relationship with one object may influence the user's relationship with another object. They can also eliminate the need to modify relationships between objects using user groups.

The follow are examples of simple object-to-object relationships:

  • managers of an employee have access to approve requests the employee has made
  • users who have a repository admin role (repo_admin) in an organization automatically have admin access to all repositories in that organization
  • users who are subscribed to a plan get access to all the features in that plan

Before you start

Familiarize yourself with basic OpenFGA Concepts:

Assume that you have the following authorization model.
You have two types:

  • folder that users can be related to as an editor
  • document that users can be related to as an editor
model
schema 1.1

type user

type folder
relations
define editor: [user]

type document
relations
define editor: [user]

In addition:

Direct access

Creating an authorization model and a relationship tuple can grant a user access to an object. To learn more, read about Direct Access

OpenFGA concepts

  • A Type: a class of objects that have similar characteristics
  • A User: an entity in the system that can be related to an object
  • A Relation: 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
  • An Object: represents an entity in the system. Users' relationships to it can be define through relationship tuples and the authorization model
  • A Relationship Tuple: a group stored in OpenFGA that consists of a user, a relation, and an object
  • Union Operator: can be used to indicate that the user has multiple ways of being related to an object

Step by step

The following walkthrough models (a) folders that contain documents and (b) that a user who has editor access to a given folder has editor access to all documents in that folder.

For editors of a folder to be editors of a containing document, you must:

  1. Update the authorization model to allow a parent relationship between folder and document
  2. Update the editor relation in the document type definition to support cascading from folder

The following three steps indicate and verify that bob is an editor of document:meeting_notes.doc because bob is an editor of folder:notes:

  1. Create a new relationship tuple to indicate that bob is a editor of folder:notes
  2. Create a new relationship tuple to indicate that folder:notes is a parent of document:meeting_notes.doc
  3. Check to see if bob is an editor of document:meeting_notes.doc

01. Update the Athorization Model to allow a parent relationship between folder and document

As documented in Modeling Concepts: Object to Object Relationships, the following update to the authorization model allows a parent relation between a folder and a document:

model
schema 1.1

type user

type folder
relations
define editor: [user]

type document
relations
define parent: [folder]
define editor: [user]
info

The document type now has a parent relation, indicating that other objects can be parents of documents

02. Update the editor relation in the document type definition to support cascading from folder

To allow cascading relations between folder and document, update the authorization model:

model
schema 1.1

type user

type folder
relations
define editor: [user]

type document
relations
define parent: [folder]
define editor: [user] or editor from parent
info

editor of a document can be the following:

  1. users that are directly assigned as editors
  2. users that are related to any parent of this document as editor (editors of the parent)

After making these changes, anyone related to a folder that is a parent of a document as an editor is also an editor of that document.

03. Create a new relationship tuple to indicate that bob is an editor of folder:notes

To leverage the new cascading relation, create a relationship tuple stating that bob is an editor of folder:notes

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
});

await fgaClient.write({
writes: [
{"user":"user:bob","relation":"editor","object":"folder:notes"}
],
}, {
authorization_model_id: "01HVMMBCMGZNT3SED4Z17ECXCA"
});
caution

Note: Use unique ids for each object and user within your application domain when creating relationship tuples for OpenFGA. We use first names and simple ids below as an easy-to-follow example.

04. Create a new relationship tuple to indicate that folder:notes is a parent of document:meeting_notes.doc

Now that bob is an editor of folder:notes, we need to indicate that folder:notes is a parent of document:meeting_notes.doc

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
});

await fgaClient.write({
writes: [
// the notes folder is a parent of the meeting notes document
{"_description":"the notes folder is a parent of the meeting notes document","user":"folder:notes","relation":"parent","object":"document:meeting_notes.doc"}
],
}, {
authorization_model_id: "01HVMMBCMGZNT3SED4Z17ECXCA"
});

05. Check if bob is an editor of document:meeting_notes.doc

After changing the authorization model and adding two new relationship tuples, verify that your configuration is correct by running the following check: is bob an editor of document:meeting_notes.doc.

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:bob',
relation: 'editor',
object: 'document:meeting_notes.doc',
}, {
authorization_model_id: '01HVMMBCMGZNT3SED4Z17ECXCA',
});

// allowed = true

Note: There are no other relationship tuples in the store that dictate a direct relation between bob and document:meeting_notes.doc. The check succeeds because of the cascading relation.

The chain of resolution is:

  • bob is an editor of folder:notes
  • folder:notes is a parent of document:meeting_notes.doc
  • editors of any parent folder of document:meeting_notes.doc are also editors of the document
  • therefore bob is an editor of document:meeting_notes.doc
caution

When searching tuples that are related to the object (the word after from, also called the tupleset), OpenFGA will not do any evaluation and only considers concrete objects (of the form <object_type>:<object_id>) that were directly assigned. OpenFGA will throw an error if it encounters any rewrites, a *, a type bound public access (<object_type>:*), or a userset (<object_type>:<object_id>#<relation>).

For more information on this topic, see Referencing Relations on Related Objects.

Modeling Concepts: Object to Object Relationships

Learn about how to model object to object relationships in OpenFGA.

Modeling Google Drive

See how to make folders parents of documents, and to make editors on the parent folders editors on documents inside them..

Modeling GitHub

See how to grant users access to all repositories owned by an organization.