Skip to main content

Managing Group Access

OpenFGA allows you to grant a group of users access to a particular object.

When to use

Relationship tuples are helpful when you want to specify that a group of users all have the same relation to an object. For example, OpenFGA allows you to:

  • Grant a group of engineers viewer access to roadmap.doc
  • Create a block_list of members who can't access a document
  • Share a document with a team
  • Grant viewer access to a photo to followers only
  • Make a file viewable for all users within an organization
  • Manage access to a database for users in a certain locale

Before you start

Familiarize yourself with basic OpenFGA Concepts before you continue.

In the example below, you have the following authorization model with two types:

  • company that can have an employee relation
  • document that can have a reader relation.
model
schema 1.1

type user

type company
relations
define employee: [user]

type document
relations
define reader: [company#employee]

In addition, the following concepts are important to group access management:

Modeling user groups

OpenFGA allows you to add users to groups and grant groups access to an object. For more information, see User Groups.

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 grouping consisting of a user, a relation and an object stored in OpenFGA

Step by step

01. Adding company to the document

The following Relationship Tuple assigns ever employee of a type company a reader relationship with a particular object of type document, in this case document:planning):

[// Every employee in the company can read document:planning
{
"_description": "Every employee in the company can read document:planning",
"user": "company:xyz#employee",
"relation": "reader",
"object": "document:planning"
}]

02. Add an employee to the company

Below is a relationship tuple specifying that Anne is an employee of company:xyz:

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:anne","relation":"employee","object":"company:xyz"}
],
}, {
authorization_model_id: "01HVMMBCMGZNT3SED4Z17ECXCA"
});

03. Checking an individual member's access to an object

Call the Check API to verify that Anne can read document:planning returns 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: 'reader',
object: 'document:planning',
}, {
authorization_model_id: '01HVMMBCMGZNT3SED4Z17ECXCA',
});

// allowed = true

The same check for Becky, a different user, returns false, because Becky does not have an employee relationship with company:xyz:

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:becky',
relation: 'reader',
object: 'document:planning',
}, {
authorization_model_id: '01HVMMBCMGZNT3SED4Z17ECXCA',
});

// allowed = false
Modeling User Groups

Learn about how to model users and groups.

Managing Group Membership

Learn about managing group membership.