Skip to main content

Parent-Child Objects

note
OpenFGA is an open source Fine-Grained Authorization solution based on Google's Zanzibar. We welcome community contribution to this project.

In this guide you will learn how to indicate relationships between objects, and how users relationships to one object can affect their relationship with another. For example: how a editor of a folder can be an editor of all documents the folder is a parent of.

When to use

Object-to-Object relationships, combined with a configured authorization model can be used to indicate that a user's relation with one object can influence their relationship with another object. This can also be used in some cases to remove the need to modify relations between objects using user groups.

Object-to-object relationships can be used:

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

Before You Start

In order to understand this guide correctly you must be familiar with some OpenFGA Concepts and know how to develop the things that we will list below.

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
type folder
relations
define editor as self
type document
relations
define editor as self

In addition, you will need to know the following:

Direct Access

You need to know how to create an authorization model and create a relationship tuple to grant a user access to an object. Learn more →

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: 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
  • 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 grouping consisting of a user, a relation and an object stored in OpenFGA
  • Union Operator: the union operator can be used to indicate that the user has multiple ways of being related to an object

Step By Step

We would like to model folders that contain documents and that a user having editor access to the folder, has editor access to all documents in that folder.

For editors of a folder to be editors of a containing document, we need to:

  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

and then to indicate and verify that bob is an editor of document:meeting_notes.doc because bob is an editor of folder:notes, we then need to:

  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 Authorization Model To Allow A Parent Relationship Between Folder And Document

To allow a parent relation between a folder and a document, we need to update the authorization model to be the following (this is to allow creating relationship tuples that can indicate a relationship between folder and document. Refer to Modeling Concepts: Object to Object Relationships to understand why):

type folder
relations
define editor as self
type document
relations
define parent as self
define editor as self
info

Notice that 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, we can update our authorization model as the following:

type folder
relations
define editor as self
type document
relations
define parent as self
define editor as self or editor from parent
info

editor of a document are any of:

  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)

So with this change, anyone related to a folder that is a parent of a document as an editor is also an editor of said document.

03. Create A New Relationship Tuple To Indicate That bob Is An Editor Of folder:notes

To leverage our cascading relation, we need to create a relationship tuple that states: bob is an editor of folder:notes

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

// Initialize the SDK with no auth - see "How to setup SDK client" for more options
const fgaClient = new OpenFgaApi({
apiScheme: process.env.FGA_API_SCHEME, // Either "http" or "https", defaults to "https"
apiHost: process.env.FGA_API_HOST, // required, define without the scheme (e.g. api.openfga.example instead of https://api.openfga.example)
storeId: process.env.FGA_STORE_ID, // Either "http" or "https", defaults to "https"
});

await fgaClient.write({
writes: {
tuple_keys: [
{ user: 'bob', relation: 'editor', object: 'folder:notes'}
]
}
});

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 { OpenFgaApi } = require('@openfga/sdk');

// Initialize the SDK with no auth - see "How to setup SDK client" for more options
const fgaClient = new OpenFgaApi({
apiScheme: process.env.FGA_API_SCHEME, // Either "http" or "https", defaults to "https"
apiHost: process.env.FGA_API_HOST, // required, define without the scheme (e.g. api.openfga.example instead of https://api.openfga.example)
storeId: process.env.FGA_STORE_ID, // Either "http" or "https", defaults to "https"
});

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

05. Check To See If bob Is An Editor Of document:meeting_notes.doc

Now that we have done the changes to the authorization model and the addition of the two new relationship tuples, we can verify if our 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 { OpenFgaApi } = require('@openfga/sdk');

// Initialize the SDK with no auth - see "How to setup SDK client" for more options
const fgaClient = new OpenFgaApi({
apiScheme: process.env.FGA_API_SCHEME, // Either "http" or "https", defaults to "https"
apiHost: process.env.FGA_API_HOST, // required, define without the scheme (e.g. api.openfga.example instead of https://api.openfga.example)
storeId: process.env.FGA_STORE_ID, // Either "http" or "https", defaults to "https"
});

// Run a check
const { allowed } = await fgaClient.check({
tuple_key: {
user: 'bob',
relation: 'editor',
object: 'document:meeting_notes.doc',
},});

// allowed = true

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

The chain of resolution becomes:

  • 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

Note: When creating relationship tuples for OpenFGA make sure to use unique ids for each object and user within your application domain. We are using first names and simple ids to just illustrate an easy-to-follow example.

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.