Concepts
The OpenFGA 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.
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:
- DSL
- JSON
type document
relations
define viewer: [user]
define commenter: [user]
define editor: [user]
define owner: [user]
{
"type": "document",
"relations": {
"viewer": {
"this": {}
},
"commenter": {
"this": {}
},
"editor": {
"this": {}
},
"owner": {
"this": {}
}
},
"metadata": {
"relations": {
"viewer": {
"directly_related_user_types": [
{
"type": "user"
}
]
},
"commenter": {
"directly_related_user_types": [
{
"type": "user"
}
]
},
"editor": {
"directly_related_user_types": [
{
"type": "user"
}
]
},
"owner": {
"directly_related_user_types": [
{
"type": "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:
- DSL
- JSON
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
{
"schema_version": "1.1",
"type_definitions": [
{
"type": "document",
"relations": {
"viewer": {
"this": {}
},
"commenter": {
"this": {}
},
"editor": {
"this": {}
},
"owner": {
"this": {}
}
},
"metadata": {
"relations": {
"viewer": {
"directly_related_user_types": [
{
"type": "domain",
"relation": "member"
},
{
"type": "user"
}
]
},
"commenter": {
"directly_related_user_types": [
{
"type": "domain",
"relation": "member"
},
{
"type": "user"
}
]
},
"editor": {
"directly_related_user_types": [
{
"type": "domain",
"relation": "member"
},
{
"type": "user"
}
]
},
"owner": {
"directly_related_user_types": [
{
"type": "domain",
"relation": "member"
},
{
"type": "user"
}
]
}
}
}
},
{
"type": "domain",
"relations": {
"member": {
"this": {}
}
},
"metadata": {
"relations": {
"member": {
"directly_related_user_types": [
{
"type": "user"
}
]
}
}
}
},
{
"type": "user"
}
]
}
Authorization model, together with relationship tuples, allow determination of whether a relationship exists between a user and an object.
The OpenFGA service has two different syntaxes to define the authorization model:
- A JSON syntax accepted by the OpenFGA 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 Okta FGA Playground to help with modeling. This is translated to the API-supported syntax before being sent to the API.
Learn more about the OpenFGA Configuration Language.
What Is A Store?
A "store" is a OpenFGA 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
oruser:4179af14-f0c0-4930-88fd-5570c7bf6f59
- any object: e.g.
workspace:fb83c013-3060-41f4-9590-d3233a67938f
,repository:auth0/express-jwt
ororganization: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 objectorganization:org_ajUc9kJ
asmember
- 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 thedocument
type allows the following:- user identifier to object relationship: the user id
anne
of typeuser
is related to the objectdocument:roadmap
aseditor
- object to object relationship: the object
application:ifft
is related to the objectdocument:roadmap
aseditor
- userset to object relationship: the userset
organization:auth0.com#member
is related todocument:roadmap
aseditor
- indicating that the set of users who are related to the object
organization:auth0.com
asmember
are related to the objectdocument:roadmap
aseditor
s - this allows for potential solutions to use-cases like sharing a document internally with all members of a company or a team
- indicating that the set of users who are related to the object
- everyone to object relationship: everyone (
*
) is related todocument:roadmap
aseditor
- this is how one could model publicly editable documents
- user identifier to object relationship: the user id
These would be defined in the authorization model as such:
- DSL
- JSON
type document
relations
define viewer: [user]
define commenter: [user]
define editor: [user]
define owner: [user]
type user
{
"type_definitions": [
{
"type": "document",
"relations": {
"viewer": {
"this": {}
},
"commenter": {
"this": {}
},
"editor": {
"this": {}
},
"owner": {
"this": {}
}
},
"metadata": {
"relations": {
"viewer": {
"directly_related_user_types": [
{
"type": "user"
}
]
},
"commenter": {
"directly_related_user_types": [
{
"type": "user"
}
]
},
"editor": {
"directly_related_user_types": [
{
"type": "user"
}
]
},
"owner": {
"directly_related_user_types": [
{
"type": "user"
}
]
}
}
}
},
{
"type": "user"
}
]
}
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.
What Is A Directly Related User Type?
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.
- DSL
- JSON
type document
relations
define viewer: [user]
{
"type_definitions": [
{
"type": "document",
"relations": {
"viewer": {
"this": {}
}
},
"metadata": {
"relations": {
"viewer": {
"directly_related_user_types": [
{
"type": "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 OpenFGA.
A relationship tuple consists of a:
- user, e.g.
user:anne
,user:3f7768e0-4fa7-4e93-8417-4da68ce1846c
,workspace:auth0
orfolder:planning#editor
- relation, e.g.
editor
,member
orparent_workspace
- object, e.g
repo:auth0/express_jwt
,domain:auth0.com
orchannel: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 OpenFGA 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 OpenFGA authorization model allows it.
-
user:anne
has a direct relationship withdocument:new-roadmap
asviewer
if the type definition allows it (allowsdirect 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 withdocument:new-roadmap
asviewer
if the type definition allows it, and the presence of relationship tuples satisfying the relationship exist.For example, assuming the following type definition:
- DSL
- JSON
type document
relations
define viewer: [user] or editor
define editor: [user]{
"type_definitions": [
{
"type": "document",
"relations": {
"viewer": {
"union": {
"child": [
{
"this": {}
},
{
"computedUserset": {
"relation": "editor"
}
}
]
}
},
"editor": {
"this": {}
}
},
"metadata": {
"relations": {
"editor": {
"directly_related_user_types": [
{
"type": "user"
}
]
},
"viewer": {
"directly_related_user_types": [
{
"type": "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
anddocument:new-roadmap
as aviewer
is implied from the directeditor
relationshipuser:anne
has with that same document. Thus, the following request to check whether a viewer relationship exists betweenuser:anne
anddocument:new-roadmap
will returntrue
.- Node.js
- Go
- .NET
- Python
- CLI
- curl
- Pseudocode
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({
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.fga.example instead of 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: '1uHxCSuTP0VKPYSnkq1pbb1jeZw',
});
// allowed = trueInitialize the SDK
// ApiTokenIssuer, ApiAudience, ClientId and ClientSecret are optional.
import (
. "github.com/openfga/go-sdk/client"
"os"
)
func main() {
// Initialize the SDK with no auth - see "How to setup SDK client" for more options
fgaClient, err := NewSdkClient(&ClientConfiguration{
ApiScheme: os.Getenv("FGA_SCHEME"), // Either "http" or "https", defaults to "https"
ApiHost: os.Getenv("FGA_API_HOST"), // required, define without the scheme (e.g. api.fga.example instead of https://api.fga.example)
StoreId: os.Getenv("FGA_STORE_ID"), // optional, not needed for `CreateStore` and `ListStores`, required before calling for all other methods
AuthorizationModelId: openfga.PtrString(os.Getenv("FGA_MODEL_ID")), // Optional, can be overridden per request
})
if err != nil {
// .. Handle error
}
}
options := ClientCheckOptions{
AuthorizationModelId: openfga.PtrString("1uHxCSuTP0VKPYSnkq1pbb1jeZw"),
}
body := ClientCheckRequest{
User: "user:anne",
Relation: "viewer",
Object: "document:new-roadmap",
}
data, err := fgaClient.Check(context.Background()).Body(body).Options(options).Execute()
// data = { allowed: true }Initialize the SDK
// ApiTokenIssuer, ApiAudience, ClientId and ClientSecret are optional.
// import the SDK
using OpenFga.Sdk.Client;
using OpenFga.Sdk.Client.Model;
using OpenFga.Sdk.Model;
using Environment = System.Environment;
namespace Example;
class Example {
public static async Task Main() {
// Initialize the SDK with no auth - see "How to setup SDK client" for more options
var configuration = new ClientConfiguration() {
ApiScheme = Environment.GetEnvironmentVariable("FGA_API_SCHEME"), // Either "http" or "https", defaults to "https"
ApiHost = Environment.GetEnvironmentVariable("FGA_API_HOST"), // required, define without the scheme (e.g. api.fga.example instead of https://api.fga.example)
StoreId = Environment.GetEnvironmentVariable("FGA_STORE_ID"), // optional, not needed for `CreateStore` and `ListStores`, required before calling for all other methods
AuthorizationModelId = Environment.GetEnvironmentVariable("FGA_MODEL_ID"), // Optional, can be overridden per request
};
var fgaClient = new OpenFgaClient(configuration);
}
}
var options = new ClientCheckOptions {
AuthorizationModelId = "1uHxCSuTP0VKPYSnkq1pbb1jeZw",
};
var body = new ClientCheckRequest {
User = "user:anne",
Relation = "viewer",
Object = "document:new-roadmap",
};
var response = await fgaClient.Check(body, options);
// response.Allowed = trueInitialize the SDK
# ApiTokenIssuer, ApiAudience, ClientId and ClientSecret are optional.
import os
import json
from openfga_sdk.client import ClientConfiguration
from openfga_sdk.client import OpenFgaClient
configuration = ClientConfiguration(
api_scheme = os.environ.get('FGA_API_SCHEME'), # Either "http" or "https", defaults to "https"
api_host = os.environ.get('FGA_API_HOST'), # required, define without the scheme (e.g. api.fga.example instead of https://api.fga.example)
store_id = os.environ.get('FGA_STORE_ID') # optional, not needed for `CreateStore` and `ListStores`, required before calling for all other methods
authorization_model_id = os.environ.get('FGA_MODEL_ID'), # Optional, can be overridden per request
)
# Enter a context with an instance of the OpenFgaClient
async with OpenFgaClient(configuration) as fga_client:
api_response = await fga_client.read_authorization_models()
await fga_client.close()options = {
"authorization_model_id": "1uHxCSuTP0VKPYSnkq1pbb1jeZw"
}
body = ClientCheckRequest(
user="user:anne",
relation="viewer",
object="document:new-roadmap",
)
response = await fga_client.check(body, options)
# response.allowed = trueSet FGA_SERVER_URL according to the service you are using (e.g. https://api.fga.example)
Set FGA_SERVER_URL according to the service you are using (e.g. https://api.fga.example)
fga query check --store-id=$FGA_STORE_ID --model-id=1uHxCSuTP0VKPYSnkq1pbb1jeZw user:anne viewer document:new-roadmap
# Response: {"allowed":true}Set FGA_SERVER_URL according to the service you are using (e.g. https://api.fga.example)
Set FGA_SERVER_URL according to the service you are using (e.g. https://api.fga.example)
curl -X POST $FGA_SERVER_URL/stores/$FGA_STORE_ID/check \
-H "Authorization: Bearer $FGA_API_TOKEN" \ # Not needed if service does not require authorization
-H "content-type: application/json" \
-d '{"authorization_model_id": "1uHxCSuTP0VKPYSnkq1pbb1jeZw", "tuple_key":{"user":"user:anne","relation":"viewer","object":"document:new-roadmap"}}'
# Response: {"allowed":true}check(
user = "user:anne", // check if the user `user:anne`
relation = "viewer", // has an `viewer` relation
object = "document:new-roadmap", // with the object `document:new-roadmap`
authorization_id = "1uHxCSuTP0VKPYSnkq1pbb1jeZw"
);
Reply: true
What Is A Check Request?
A check request is a call to the OpenFGA check endpoint that returns whether the user has a certain relationship with an object.
This can be done using 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
:
- Node.js
- Go
- .NET
- Python
- CLI
- curl
- Pseudocode
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({
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.fga.example instead of 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: '1uHxCSuTP0VKPYSnkq1pbb1jeZw',
});
// allowed = true
Initialize the SDK
// ApiTokenIssuer, ApiAudience, ClientId and ClientSecret are optional.
import (
. "github.com/openfga/go-sdk/client"
"os"
)
func main() {
// Initialize the SDK with no auth - see "How to setup SDK client" for more options
fgaClient, err := NewSdkClient(&ClientConfiguration{
ApiScheme: os.Getenv("FGA_SCHEME"), // Either "http" or "https", defaults to "https"
ApiHost: os.Getenv("FGA_API_HOST"), // required, define without the scheme (e.g. api.fga.example instead of https://api.fga.example)
StoreId: os.Getenv("FGA_STORE_ID"), // optional, not needed for `CreateStore` and `ListStores`, required before calling for all other methods
AuthorizationModelId: openfga.PtrString(os.Getenv("FGA_MODEL_ID")), // Optional, can be overridden per request
})
if err != nil {
// .. Handle error
}
}
options := ClientCheckOptions{
AuthorizationModelId: openfga.PtrString("1uHxCSuTP0VKPYSnkq1pbb1jeZw"),
}
body := ClientCheckRequest{
User: "user:anne",
Relation: "viewer",
Object: "document:new-roadmap",
}
data, err := fgaClient.Check(context.Background()).Body(body).Options(options).Execute()
// data = { allowed: true }
Initialize the SDK
// ApiTokenIssuer, ApiAudience, ClientId and ClientSecret are optional.
// import the SDK
using OpenFga.Sdk.Client;
using OpenFga.Sdk.Client.Model;
using OpenFga.Sdk.Model;
using Environment = System.Environment;
namespace Example;
class Example {
public static async Task Main() {
// Initialize the SDK with no auth - see "How to setup SDK client" for more options
var configuration = new ClientConfiguration() {
ApiScheme = Environment.GetEnvironmentVariable("FGA_API_SCHEME"), // Either "http" or "https", defaults to "https"
ApiHost = Environment.GetEnvironmentVariable("FGA_API_HOST"), // required, define without the scheme (e.g. api.fga.example instead of https://api.fga.example)
StoreId = Environment.GetEnvironmentVariable("FGA_STORE_ID"), // optional, not needed for `CreateStore` and `ListStores`, required before calling for all other methods
AuthorizationModelId = Environment.GetEnvironmentVariable("FGA_MODEL_ID"), // Optional, can be overridden per request
};
var fgaClient = new OpenFgaClient(configuration);
}
}
var options = new ClientCheckOptions {
AuthorizationModelId = "1uHxCSuTP0VKPYSnkq1pbb1jeZw",
};
var body = new ClientCheckRequest {
User = "user:anne",
Relation = "viewer",
Object = "document:new-roadmap",
};
var response = await fgaClient.Check(body, options);
// response.Allowed = true
Initialize the SDK
# ApiTokenIssuer, ApiAudience, ClientId and ClientSecret are optional.
import os
import json
from openfga_sdk.client import ClientConfiguration
from openfga_sdk.client import OpenFgaClient
configuration = ClientConfiguration(
api_scheme = os.environ.get('FGA_API_SCHEME'), # Either "http" or "https", defaults to "https"
api_host = os.environ.get('FGA_API_HOST'), # required, define without the scheme (e.g. api.fga.example instead of https://api.fga.example)
store_id = os.environ.get('FGA_STORE_ID') # optional, not needed for `CreateStore` and `ListStores`, required before calling for all other methods
authorization_model_id = os.environ.get('FGA_MODEL_ID'), # Optional, can be overridden per request
)
# Enter a context with an instance of the OpenFgaClient
async with OpenFgaClient(configuration) as fga_client:
api_response = await fga_client.read_authorization_models()
await fga_client.close()
options = {
"authorization_model_id": "1uHxCSuTP0VKPYSnkq1pbb1jeZw"
}
body = ClientCheckRequest(
user="user:anne",
relation="viewer",
object="document:new-roadmap",
)
response = await fga_client.check(body, options)
# response.allowed = true
Set FGA_SERVER_URL according to the service you are using (e.g. https://api.fga.example)
Set FGA_SERVER_URL according to the service you are using (e.g. https://api.fga.example)
fga query check --store-id=$FGA_STORE_ID --model-id=1uHxCSuTP0VKPYSnkq1pbb1jeZw user:anne viewer document:new-roadmap
# Response: {"allowed":true}
Set FGA_SERVER_URL according to the service you are using (e.g. https://api.fga.example)
Set FGA_SERVER_URL according to the service you are using (e.g. https://api.fga.example)
curl -X POST $FGA_SERVER_URL/stores/$FGA_STORE_ID/check \
-H "Authorization: Bearer $FGA_API_TOKEN" \ # Not needed if service does not require authorization
-H "content-type: application/json" \
-d '{"authorization_model_id": "1uHxCSuTP0VKPYSnkq1pbb1jeZw", "tuple_key":{"user":"user:anne","relation":"viewer","object":"document:new-roadmap"}}'
# Response: {"allowed":true}
check(
user = "user:anne", // check if the user `user:anne`
relation = "viewer", // has an `viewer` relation
object = "document:new-roadmap", // with the object `document:new-roadmap`
authorization_id = "1uHxCSuTP0VKPYSnkq1pbb1jeZw"
);
Reply: 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 OpenFGA 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 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 will return all the objects with document type for which anne
of type user has a viewer
relation with:
- Node.js
- Go
- .NET
- Python
- CLI
- curl
- Pseudocode
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({
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.fga.example instead of 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: "1uHxCSuTP0VKPYSnkq1pbb1jeZw",
});
// response.objects = ["document:otherdoc", "document:planning"]
Initialize the SDK
// ApiTokenIssuer, ApiAudience, ClientId and ClientSecret are optional.
import (
. "github.com/openfga/go-sdk/client"
"os"
)
func main() {
// Initialize the SDK with no auth - see "How to setup SDK client" for more options
fgaClient, err := NewSdkClient(&ClientConfiguration{
ApiScheme: os.Getenv("FGA_SCHEME"), // Either "http" or "https", defaults to "https"
ApiHost: os.Getenv("FGA_API_HOST"), // required, define without the scheme (e.g. api.fga.example instead of https://api.fga.example)
StoreId: os.Getenv("FGA_STORE_ID"), // optional, not needed for `CreateStore` and `ListStores`, required before calling for all other methods
AuthorizationModelId: openfga.PtrString(os.Getenv("FGA_MODEL_ID")), // Optional, can be overridden per request
})
if err != nil {
// .. Handle error
}
}
options := ClientListObjectsOptions{
AuthorizationModelId: openfga.PtrString("1uHxCSuTP0VKPYSnkq1pbb1jeZw"),
}
body := ClientListObjectsRequest{
User: "user:anne",
Relation: "viewer",
Type: "document",
}
data, err := fgaClient.ListObjects(context.Background()).
Body(requestBody).
Options(options).
Execute()
// data = { "objects": ["document:otherdoc", "document:planning"] }
Initialize the SDK
// ApiTokenIssuer, ApiAudience, ClientId and ClientSecret are optional.
// import the SDK
using OpenFga.Sdk.Client;
using OpenFga.Sdk.Client.Model;
using OpenFga.Sdk.Model;
using Environment = System.Environment;
namespace Example;
class Example {
public static async Task Main() {
// Initialize the SDK with no auth - see "How to setup SDK client" for more options
var configuration = new ClientConfiguration() {
ApiScheme = Environment.GetEnvironmentVariable("FGA_API_SCHEME"), // Either "http" or "https", defaults to "https"
ApiHost = Environment.GetEnvironmentVariable("FGA_API_HOST"), // required, define without the scheme (e.g. api.fga.example instead of https://api.fga.example)
StoreId = Environment.GetEnvironmentVariable("FGA_STORE_ID"), // optional, not needed for `CreateStore` and `ListStores`, required before calling for all other methods
AuthorizationModelId = Environment.GetEnvironmentVariable("FGA_MODEL_ID"), // Optional, can be overridden per request
};
var fgaClient = new OpenFgaClient(configuration);
}
}
var options = new ClientListObjectsOptions {
AuthorizationModelId = "1uHxCSuTP0VKPYSnkq1pbb1jeZw",
};
var body = new ClientListObjectsRequest {
User = "user:anne",
Relation = "viewer",
Type = "document",
};
var response = await fgaClient.ListObjects(body, options);
// response.Objects = ["document:otherdoc", "document:planning"]
Initialize the SDK
# ApiTokenIssuer, ApiAudience, ClientId and ClientSecret are optional.
import os
import json
from openfga_sdk.client import ClientConfiguration
from openfga_sdk.client import OpenFgaClient
configuration = ClientConfiguration(
api_scheme = os.environ.get('FGA_API_SCHEME'), # Either "http" or "https", defaults to "https"
api_host = os.environ.get('FGA_API_HOST'), # required, define without the scheme (e.g. api.fga.example instead of https://api.fga.example)
store_id = os.environ.get('FGA_STORE_ID') # optional, not needed for `CreateStore` and `ListStores`, required before calling for all other methods
authorization_model_id = os.environ.get('FGA_MODEL_ID'), # Optional, can be overridden per request
)
# Enter a context with an instance of the OpenFgaClient
async with OpenFgaClient(configuration) as fga_client:
api_response = await fga_client.read_authorization_models()
await fga_client.close()
options = {
"authorization_model_id": "1uHxCSuTP0VKPYSnkq1pbb1jeZw"
}
body = ClientListObjectsRequest(
user="user:anne",
relation="viewer",
type="document",
)
response = await fga_client.list_objects(body, options)
# response.objects = ["document:otherdoc", "document:planning"]
Set FGA_SERVER_URL according to the service you are using (e.g. https://api.fga.example)
Set FGA_SERVER_URL according to the service you are using (e.g. https://api.fga.example)
fga query list-objects --store-id=${FGA_STORE_ID} --model-id=1uHxCSuTP0VKPYSnkq1pbb1jeZw user:anne viewer document
# Response: {"objects": ["document:otherdoc", "document:planning"]}
Set FGA_SERVER_URL according to the service you are using (e.g. https://api.fga.example)
Set FGA_SERVER_URL according to the service you are using (e.g. https://api.fga.example)
curl -X POST $FGA_SERVER_URL/stores/$FGA_STORE_ID/list-objects \
-H "Authorization: Bearer $FGA_API_TOKEN" \ # Not needed if service does not require authorization
-H "content-type: application/json" \
-d '{ "authorization_model_id": "1uHxCSuTP0VKPYSnkq1pbb1jeZw",
"type": "document",
"relation": "viewer",
"user":"user:anne"
}'
# Response: {"objects": ["document:otherdoc", "document:planning"]}
listObjects(
"user:anne", // list the objects that the user `user:anne`
"viewer", // has an `viewer` relation
"document", // and that are of type `document`
authorization_model_id = "1uHxCSuTP0VKPYSnkq1pbb1jeZw", // for this particular authorization model id
);
Reply: ["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 OpenFGA, type bound public access (represented by <type>:*
) is a special OpenFGA 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).
<type>:*
) is a special OpenFGA 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.