Direct Relationships
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 Okta FGA during the Developer Community Preview can be found here.
In this guide you'll learn how to model relationships that may or may not be assigned directly to individual users.
Disabling direct relationships for a certain relation on an objects are useful especially in cases where you are trying to model some permissions that are not usually granted individually to a user.
This is useful when:
- For security reason, not permitting permissions assigned directly to individuals without associating roles
Before You Start
To better understand this guide, you should be familiar with some Okta FGA Concepts and know how to develop the things listed below.
You will need to know the following:
- Direct Access
- Okta FGA Concepts
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 →
Okta FGA 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 Okta FGA
- Direct Relationship Type Restrictions: used in the context of the relation definition can be used to allow direct relationships to the objects of this type
What Are Direct Relationships?
Direct relationships are relationships where a user has a relationship to an object that is not dependent on any other relationship they have with that object.
When checking for a relationship, a direct relationship exists if a relationship tuple is present in the system with the exact same object and relation that were in the query and where the user is one of:
- the same user ID as that in the query
- type bound public access (
<type>:*
) - a set of users that contains the user ID present in the query
Enable Or Disable Direct Relationships
Direct relationships can be enabled for a specific relation on an object type by adding direct relationship type restrictions from that relation's definition. Likewise, they can be disabled by removing the direct relationship type restrictions.
- DSL
- JSON
model
schema 1.1
type user
type document
relations
define viewer: [user, user:*, team#member] or editor
define editor: [user, team#member]
type team
relations
define member: [user]
{
"schema_version": "1.1",
"type_definitions": [
{
"type": "user"
},
{
"type": "document",
"relations": {
"viewer": {
"union": {
"child": [
{
"this": {}
},
{
"computedUserset": {
"relation": "editor"
}
}
]
}
},
"editor": {
"this": {}
}
},
"metadata": {
"relations": {
"viewer": {
"directly_related_user_types": [
{
"type": "user"
},
{
"type": "user",
"wildcard": {}
},
{
"type": "team",
"relation": "member"
}
]
},
"editor": {
"directly_related_user_types": [
{
"type": "user"
},
{
"type": "team",
"relation": "member"
}
]
}
}
}
},
{
"type": "team",
"relations": {
"member": {
"this": {}
}
},
"metadata": {
"relations": {
"member": {
"directly_related_user_types": [
{
"type": "user"
}
]
}
}
}
}
]
}
The authorization model describes two object types: document
and team
.
The document
type definition has two relations, editor
and viewer
. Both relations allow a direct relationship; viewer
also allows an indirect relationship through editor
.
In the team
type definition, there is a single member
relation that only allows direct relationships.
How It Affects Your System
To illustrate the effect enabling or disabling direct relationships on a specific relation has, we'll investigate several situations.
1. With Direct Relationships Enabled
Let us start with the authorization model we had above:
- DSL
- JSON
model
schema 1.1
type user
type document
relations
define viewer: [user, user:*, team#member] or editor
define editor: [user, team#member]
type team
relations
define member: [user]
{
"schema_version": "1.1",
"type_definitions": [
{
"type": "user"
},
{
"type": "document",
"relations": {
"viewer": {
"union": {
"child": [
{
"this": {}
},
{
"computedUserset": {
"relation": "editor"
}
}
]
}
},
"editor": {
"this": {}
}
},
"metadata": {
"relations": {
"viewer": {
"directly_related_user_types": [
{
"type": "user"
},
{
"type": "user",
"wildcard": {}
},
{
"type": "team",
"relation": "member"
}
]
},
"editor": {
"directly_related_user_types": [
{
"type": "user"
},
{
"type": "team",
"relation": "member"
}
]
}
}
}
},
{
"type": "team",
"relations": {
"member": {
"this": {}
}
},
"metadata": {
"relations": {
"member": {
"directly_related_user_types": [
{
"type": "user"
}
]
}
}
}
}
]
}
Now choose the type of relation to see how it affects your system:
- Direct User
- Type Bound Public Access
- Userset
- Indirect Relationship
Assume you have a tuple that states that Anne is a viewer
of document:planning
[
{
"user": "user:anne",
"relation": "viewer",
"object": "document:planning",
},
]
Now if we do a check request to see if Anne can view the planning document, we will get a response of {"allowed": true}
.
- Node.js
- Go
- .NET
- Python
- CLI
- curl
- Pseudocode
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:planning',
}, {
authorization_model_id: '1uHxCSuTP0VKPYSnkq1pbb1jeZw',
});
// allowed = true
Initialize the SDK
// Checkout the "How to Setup the SDK Client" page for more details.
import (
"os"
openfga "github.com/openfga/go-sdk"
. "github.com/openfga/go-sdk/client"
"github.com/openfga/go-sdk/credentials"
)
// 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
func main() {
fgaClient, err := NewSdkClient(&ClientConfiguration{
ApiScheme: os.Getenv("FGA_API_SCHEME")
ApiHost: os.Getenv("FGA_API_HOST"),
StoreId: os.Getenv("FGA_STORE_ID"),
AuthorizationModelId: openfga.PtrString(os.Getenv("FGA_MODEL_ID")),
Credentials: &credentials.Credentials{ // Credentials are not needed if connecting to the Playground API
Method: credentials.CredentialsMethodClientCredentials,
Config: &credentials.Config{
ClientCredentialsClientId: os.Getenv("FGA_CLIENT_ID"),
ClientCredentialsClientSecret: os.Getenv("FGA_CLIENT_SECRET"),
ClientCredentialsApiAudience: os.Getenv("FGA_API_AUDIENCE"),
ClientCredentialsApiTokenIssuer: os.Getenv("FGA_API_TOKEN_ISSUER"),
},
},
})
if err != nil {
// .. Handle error
}
}
options := ClientCheckOptions{
AuthorizationModelId: openfga.PtrString("1uHxCSuTP0VKPYSnkq1pbb1jeZw"),
}
body := ClientCheckRequest{
User: "user:anne",
Relation: "viewer",
Object: "document:planning",
}
data, err := fgaClient.Check(context.Background()).Body(body).Options(options).Execute()
// data = { allowed: true }
Initialize the SDK
// Checkout the "How to Setup the SDK Client" page for more details.
using OpenFga.Sdk.Client;
using OpenFga.Sdk.Client.Model;
using OpenFga.Sdk.Model;
using Environment = System.Environment;
namespace Example;
// 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
class MyProgram {
static async Task Main() {
var configuration = new ClientConfiguration() {
ApiScheme = Environment.GetEnvironmentVariable("FGA_API_SCHEME"),
ApiHost = Environment.GetEnvironmentVariable("FGA_API_HOST"),
StoreId = Environment.GetEnvironmentVariable("FGA_STORE_ID"),
AuthorizationModelId = Environment.GetEnvironmentVariable("FGA_MODEL_ID"),
Credentials = new Credentials() { // Credentials are not needed if connecting to the Playground API
Method = CredentialsMethod.ClientCredentials,
Config = new CredentialsConfig() {
ApiTokenIssuer = Environment.GetEnvironmentVariable("FGA_API_TOKEN_ISSUER"),
ApiAudience = Environment.GetEnvironmentVariable("FGA_API_AUDIENCE"),
ClientId = Environment.GetEnvironmentVariable("FGA_CLIENT_ID"),
ClientSecret = Environment.GetEnvironmentVariable("FGA_CLIENT_SECRET"),
}
}
};
var fgaClient = new OpenFgaClient(configuration);
}
}
var options = new ClientCheckOptions {
AuthorizationModelId = "1uHxCSuTP0VKPYSnkq1pbb1jeZw",
};
var body = new ClientCheckRequest {
User = "user:anne",
Relation = "viewer",
Object = "document:planning",
};
var response = await fgaClient.Check(body, options);
// response.Allowed = true
Initialize the SDK
# Checkout the "How to Setup the SDK Client" page for more details.
import os
import openfga_sdk
from openfga_sdk.client import OpenFgaClient, ClientConfiguration
from openfga_sdk.credentials import Credentials, CredentialConfiguration
# 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
credentials = Credentials(
method='client_credentials',
configuration=CredentialConfiguration(
api_issuer= os.environ.get('FGA_API_TOKEN_ISSUER'),
api_audience= os.environ.get('FGA_API_AUDIENCE'),
client_id= os.environ.get('FGA_CLIENT_ID'),
client_secret= os.environ.get('FGA_CLIENT_SECRET'),
)
)
configuration = ClientConfiguration(
api_scheme = os.environ.get('FGA_API_SCHEME'),
api_host = os.environ.get('FGA_API_HOST'),
store_id = os.environ.get('FGA_STORE_ID'),
model_id = os.environ.get('FGA_MODEL_ID'),
credentials = credentials, # Credentials are not needed if connecting to the Playground API
)
async with OpenFgaClient(configuration) as fga_client:
api_response = await fga_client.read_authorization_models() # call requests
await fga_client.close() # close when done
options = {
"authorization_model_id": "1uHxCSuTP0VKPYSnkq1pbb1jeZw"
}
body = ClientCheckRequest(
user="user:anne",
relation="viewer",
object="document:planning",
)
response = await fga_client.check(body, options)
# response.allowed = true
Set the required environment variables
# Not needed when calling the Playground API
curl -X POST \
https://fga.us.auth0.com/oauth/token \
-H 'content-type: application/json' \
-d '{"client_id":"'$FGA_CLIENT_ID'","client_secret":"'$FGA_CLIENT_SECRET'","audience":"https://api.us1.fga.dev/","grant_type":"client_credentials"}'
# The response will be returned in the form
# {
# "access_token": "eyJ...Ggg",
# "expires_in": 86400,
# "scope": "read:tuples write:tuples check:tuples ... write:authorization-models",
# "token_type": "Bearer"
# }
# Store this `access_token` value in environment variable `FGA_BEARER_TOKEN`
# For non-playground environment
FGA_SERVER_URL='https://api.us1.fga.dev'
# For playground environment
# FGA_SERVER_URL='https://api.playground.fga.dev'
fga query check --store-id=$FGA_STORE_ID --model-id=1uHxCSuTP0VKPYSnkq1pbb1jeZw user:anne viewer document:planning
# Response: {"allowed":true}
Set the required environment variables
# Not needed when calling the Playground API
curl -X POST \
https://fga.us.auth0.com/oauth/token \
-H 'content-type: application/json' \
-d '{"client_id":"'$FGA_CLIENT_ID'","client_secret":"'$FGA_CLIENT_SECRET'","audience":"https://api.us1.fga.dev/","grant_type":"client_credentials"}'
# The response will be returned in the form
# {
# "access_token": "eyJ...Ggg",
# "expires_in": 86400,
# "scope": "read:tuples write:tuples check:tuples ... write:authorization-models",
# "token_type": "Bearer"
# }
# Store this `access_token` value in environment variable `FGA_BEARER_TOKEN`
# For non-playground environment
FGA_SERVER_URL='https://api.us1.fga.dev'
# For playground environment
# FGA_SERVER_URL='https://api.playground.fga.dev'
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:planning"}}'
# Response: {"allowed":true}
check(
user = "user:anne", // check if the user `user:anne`
relation = "viewer", // has an `viewer` relation
object = "document:planning", // with the object `document:planning`
authorization_id = "1uHxCSuTP0VKPYSnkq1pbb1jeZw"
);
Reply: true
This is because:
- There is a relationship tuple specifying that Anne has a
viewer
relationship withdocument:planning
. - Direct relationships are allowed in the
viewer
relation definition in thedocument
type definition.
Assume you have a type bound public access tuple where everyone of type user
is a viewer
of document:planning
(In other words, the document is public)
[
{
"user": "user:*",
"relation": "viewer",
"object": "document:planning",
},
]
Now if we do a check request to see if Beth can view the planning document, we will get a response of {"allowed": true}
.
- Node.js
- Go
- .NET
- Python
- CLI
- curl
- Pseudocode
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:beth',
relation: 'viewer',
object: 'document:planning',
}, {
authorization_model_id: '1uHxCSuTP0VKPYSnkq1pbb1jeZw',
});
// allowed = true
Initialize the SDK
// Checkout the "How to Setup the SDK Client" page for more details.
import (
"os"
openfga "github.com/openfga/go-sdk"
. "github.com/openfga/go-sdk/client"
"github.com/openfga/go-sdk/credentials"
)
// 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
func main() {
fgaClient, err := NewSdkClient(&ClientConfiguration{
ApiScheme: os.Getenv("FGA_API_SCHEME")
ApiHost: os.Getenv("FGA_API_HOST"),
StoreId: os.Getenv("FGA_STORE_ID"),
AuthorizationModelId: openfga.PtrString(os.Getenv("FGA_MODEL_ID")),
Credentials: &credentials.Credentials{ // Credentials are not needed if connecting to the Playground API
Method: credentials.CredentialsMethodClientCredentials,
Config: &credentials.Config{
ClientCredentialsClientId: os.Getenv("FGA_CLIENT_ID"),
ClientCredentialsClientSecret: os.Getenv("FGA_CLIENT_SECRET"),
ClientCredentialsApiAudience: os.Getenv("FGA_API_AUDIENCE"),
ClientCredentialsApiTokenIssuer: os.Getenv("FGA_API_TOKEN_ISSUER"),
},
},
})
if err != nil {
// .. Handle error
}
}
options := ClientCheckOptions{
AuthorizationModelId: openfga.PtrString("1uHxCSuTP0VKPYSnkq1pbb1jeZw"),
}
body := ClientCheckRequest{
User: "user:beth",
Relation: "viewer",
Object: "document:planning",
}
data, err := fgaClient.Check(context.Background()).Body(body).Options(options).Execute()
// data = { allowed: true }
Initialize the SDK
// Checkout the "How to Setup the SDK Client" page for more details.
using OpenFga.Sdk.Client;
using OpenFga.Sdk.Client.Model;
using OpenFga.Sdk.Model;
using Environment = System.Environment;
namespace Example;
// 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
class MyProgram {
static async Task Main() {
var configuration = new ClientConfiguration() {
ApiScheme = Environment.GetEnvironmentVariable("FGA_API_SCHEME"),
ApiHost = Environment.GetEnvironmentVariable("FGA_API_HOST"),
StoreId = Environment.GetEnvironmentVariable("FGA_STORE_ID"),
AuthorizationModelId = Environment.GetEnvironmentVariable("FGA_MODEL_ID"),
Credentials = new Credentials() { // Credentials are not needed if connecting to the Playground API
Method = CredentialsMethod.ClientCredentials,
Config = new CredentialsConfig() {
ApiTokenIssuer = Environment.GetEnvironmentVariable("FGA_API_TOKEN_ISSUER"),
ApiAudience = Environment.GetEnvironmentVariable("FGA_API_AUDIENCE"),
ClientId = Environment.GetEnvironmentVariable("FGA_CLIENT_ID"),
ClientSecret = Environment.GetEnvironmentVariable("FGA_CLIENT_SECRET"),
}
}
};
var fgaClient = new OpenFgaClient(configuration);
}
}
var options = new ClientCheckOptions {
AuthorizationModelId = "1uHxCSuTP0VKPYSnkq1pbb1jeZw",
};
var body = new ClientCheckRequest {
User = "user:beth",
Relation = "viewer",
Object = "document:planning",
};
var response = await fgaClient.Check(body, options);
// response.Allowed = true
Initialize the SDK
# Checkout the "How to Setup the SDK Client" page for more details.
import os
import openfga_sdk
from openfga_sdk.client import OpenFgaClient, ClientConfiguration
from openfga_sdk.credentials import Credentials, CredentialConfiguration
# 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
credentials = Credentials(
method='client_credentials',
configuration=CredentialConfiguration(
api_issuer= os.environ.get('FGA_API_TOKEN_ISSUER'),
api_audience= os.environ.get('FGA_API_AUDIENCE'),
client_id= os.environ.get('FGA_CLIENT_ID'),
client_secret= os.environ.get('FGA_CLIENT_SECRET'),
)
)
configuration = ClientConfiguration(
api_scheme = os.environ.get('FGA_API_SCHEME'),
api_host = os.environ.get('FGA_API_HOST'),
store_id = os.environ.get('FGA_STORE_ID'),
model_id = os.environ.get('FGA_MODEL_ID'),
credentials = credentials, # Credentials are not needed if connecting to the Playground API
)
async with OpenFgaClient(configuration) as fga_client:
api_response = await fga_client.read_authorization_models() # call requests
await fga_client.close() # close when done
options = {
"authorization_model_id": "1uHxCSuTP0VKPYSnkq1pbb1jeZw"
}
body = ClientCheckRequest(
user="user:beth",
relation="viewer",
object="document:planning",
)
response = await fga_client.check(body, options)
# response.allowed = true
Set the required environment variables
# Not needed when calling the Playground API
curl -X POST \
https://fga.us.auth0.com/oauth/token \
-H 'content-type: application/json' \
-d '{"client_id":"'$FGA_CLIENT_ID'","client_secret":"'$FGA_CLIENT_SECRET'","audience":"https://api.us1.fga.dev/","grant_type":"client_credentials"}'
# The response will be returned in the form
# {
# "access_token": "eyJ...Ggg",
# "expires_in": 86400,
# "scope": "read:tuples write:tuples check:tuples ... write:authorization-models",
# "token_type": "Bearer"
# }
# Store this `access_token` value in environment variable `FGA_BEARER_TOKEN`
# For non-playground environment
FGA_SERVER_URL='https://api.us1.fga.dev'
# For playground environment
# FGA_SERVER_URL='https://api.playground.fga.dev'
fga query check --store-id=$FGA_STORE_ID --model-id=1uHxCSuTP0VKPYSnkq1pbb1jeZw user:beth viewer document:planning
# Response: {"allowed":true}
Set the required environment variables
# Not needed when calling the Playground API
curl -X POST \
https://fga.us.auth0.com/oauth/token \
-H 'content-type: application/json' \
-d '{"client_id":"'$FGA_CLIENT_ID'","client_secret":"'$FGA_CLIENT_SECRET'","audience":"https://api.us1.fga.dev/","grant_type":"client_credentials"}'
# The response will be returned in the form
# {
# "access_token": "eyJ...Ggg",
# "expires_in": 86400,
# "scope": "read:tuples write:tuples check:tuples ... write:authorization-models",
# "token_type": "Bearer"
# }
# Store this `access_token` value in environment variable `FGA_BEARER_TOKEN`
# For non-playground environment
FGA_SERVER_URL='https://api.us1.fga.dev'
# For playground environment
# FGA_SERVER_URL='https://api.playground.fga.dev'
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:beth","relation":"viewer","object":"document:planning"}}'
# Response: {"allowed":true}
check(
user = "user:beth", // check if the user `user:beth`
relation = "viewer", // has an `viewer` relation
object = "document:planning", // with the object `document:planning`
authorization_id = "1uHxCSuTP0VKPYSnkq1pbb1jeZw"
);
Reply: true
This is because:
- There is a relationship tuple specifying that everyone of type
user
has aviewer
relationship withdocument:planning
. - Direct relationships are allowed in the
viewer
relation definition in thedocument
type definition.
Note: Even though the relationship tuple stored in the system does not specify the user (beth
), this is still considered a direct relationship.
Usersets are the third way direct relationships apply, we will see how in this section.
Assume you have two relationship tuples:
- Charlie is a member of the product team.
- Members of the product team are viewers of the planning document.
[
{
"user": "user:charlie",
"relation": "member",
"object": "team:product",
},
{
"user": "team:product#member",
"relation": "viewer",
"object": "document:planning",
},
]
Note that these two relationship tuples are specifying that:
user:charlie
is amember
ofteam:product
.- any
member
ofteam:product
is aviewer
ofdocument:planning
.- Note that this second relationship tuple is specifying that the members of the team have viewer access, and not the team object itself.
Now if we do a check request to see if charlie can view the planning document, we will get a response of {"allowed": true}
.
- Node.js
- Go
- .NET
- Python
- CLI
- curl
- Pseudocode
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:charlie',
relation: 'viewer',
object: 'document:planning',
}, {
authorization_model_id: '1uHxCSuTP0VKPYSnkq1pbb1jeZw',
});
// allowed = true
Initialize the SDK
// Checkout the "How to Setup the SDK Client" page for more details.
import (
"os"
openfga "github.com/openfga/go-sdk"
. "github.com/openfga/go-sdk/client"
"github.com/openfga/go-sdk/credentials"
)
// 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
func main() {
fgaClient, err := NewSdkClient(&ClientConfiguration{
ApiScheme: os.Getenv("FGA_API_SCHEME")
ApiHost: os.Getenv("FGA_API_HOST"),
StoreId: os.Getenv("FGA_STORE_ID"),
AuthorizationModelId: openfga.PtrString(os.Getenv("FGA_MODEL_ID")),
Credentials: &credentials.Credentials{ // Credentials are not needed if connecting to the Playground API
Method: credentials.CredentialsMethodClientCredentials,
Config: &credentials.Config{
ClientCredentialsClientId: os.Getenv("FGA_CLIENT_ID"),
ClientCredentialsClientSecret: os.Getenv("FGA_CLIENT_SECRET"),
ClientCredentialsApiAudience: os.Getenv("FGA_API_AUDIENCE"),
ClientCredentialsApiTokenIssuer: os.Getenv("FGA_API_TOKEN_ISSUER"),
},
},
})
if err != nil {
// .. Handle error
}
}
options := ClientCheckOptions{
AuthorizationModelId: openfga.PtrString("1uHxCSuTP0VKPYSnkq1pbb1jeZw"),
}
body := ClientCheckRequest{
User: "user:charlie",
Relation: "viewer",
Object: "document:planning",
}
data, err := fgaClient.Check(context.Background()).Body(body).Options(options).Execute()
// data = { allowed: true }
Initialize the SDK
// Checkout the "How to Setup the SDK Client" page for more details.
using OpenFga.Sdk.Client;
using OpenFga.Sdk.Client.Model;
using OpenFga.Sdk.Model;
using Environment = System.Environment;
namespace Example;
// 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
class MyProgram {
static async Task Main() {
var configuration = new ClientConfiguration() {
ApiScheme = Environment.GetEnvironmentVariable("FGA_API_SCHEME"),
ApiHost = Environment.GetEnvironmentVariable("FGA_API_HOST"),
StoreId = Environment.GetEnvironmentVariable("FGA_STORE_ID"),
AuthorizationModelId = Environment.GetEnvironmentVariable("FGA_MODEL_ID"),
Credentials = new Credentials() { // Credentials are not needed if connecting to the Playground API
Method = CredentialsMethod.ClientCredentials,
Config = new CredentialsConfig() {
ApiTokenIssuer = Environment.GetEnvironmentVariable("FGA_API_TOKEN_ISSUER"),
ApiAudience = Environment.GetEnvironmentVariable("FGA_API_AUDIENCE"),
ClientId = Environment.GetEnvironmentVariable("FGA_CLIENT_ID"),
ClientSecret = Environment.GetEnvironmentVariable("FGA_CLIENT_SECRET"),
}
}
};
var fgaClient = new OpenFgaClient(configuration);
}
}
var options = new ClientCheckOptions {
AuthorizationModelId = "1uHxCSuTP0VKPYSnkq1pbb1jeZw",
};
var body = new ClientCheckRequest {
User = "user:charlie",
Relation = "viewer",
Object = "document:planning",
};
var response = await fgaClient.Check(body, options);
// response.Allowed = true
Initialize the SDK
# Checkout the "How to Setup the SDK Client" page for more details.
import os
import openfga_sdk
from openfga_sdk.client import OpenFgaClient, ClientConfiguration
from openfga_sdk.credentials import Credentials, CredentialConfiguration
# 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
credentials = Credentials(
method='client_credentials',
configuration=CredentialConfiguration(
api_issuer= os.environ.get('FGA_API_TOKEN_ISSUER'),
api_audience= os.environ.get('FGA_API_AUDIENCE'),
client_id= os.environ.get('FGA_CLIENT_ID'),
client_secret= os.environ.get('FGA_CLIENT_SECRET'),
)
)
configuration = ClientConfiguration(
api_scheme = os.environ.get('FGA_API_SCHEME'),
api_host = os.environ.get('FGA_API_HOST'),
store_id = os.environ.get('FGA_STORE_ID'),
model_id = os.environ.get('FGA_MODEL_ID'),
credentials = credentials, # Credentials are not needed if connecting to the Playground API
)
async with OpenFgaClient(configuration) as fga_client:
api_response = await fga_client.read_authorization_models() # call requests
await fga_client.close() # close when done
options = {
"authorization_model_id": "1uHxCSuTP0VKPYSnkq1pbb1jeZw"
}
body = ClientCheckRequest(
user="user:charlie",
relation="viewer",
object="document:planning",
)
response = await fga_client.check(body, options)
# response.allowed = true
Set the required environment variables
# Not needed when calling the Playground API
curl -X POST \
https://fga.us.auth0.com/oauth/token \
-H 'content-type: application/json' \
-d '{"client_id":"'$FGA_CLIENT_ID'","client_secret":"'$FGA_CLIENT_SECRET'","audience":"https://api.us1.fga.dev/","grant_type":"client_credentials"}'
# The response will be returned in the form
# {
# "access_token": "eyJ...Ggg",
# "expires_in": 86400,
# "scope": "read:tuples write:tuples check:tuples ... write:authorization-models",
# "token_type": "Bearer"
# }
# Store this `access_token` value in environment variable `FGA_BEARER_TOKEN`
# For non-playground environment
FGA_SERVER_URL='https://api.us1.fga.dev'
# For playground environment
# FGA_SERVER_URL='https://api.playground.fga.dev'
fga query check --store-id=$FGA_STORE_ID --model-id=1uHxCSuTP0VKPYSnkq1pbb1jeZw user:charlie viewer document:planning
# Response: {"allowed":true}
Set the required environment variables
# Not needed when calling the Playground API
curl -X POST \
https://fga.us.auth0.com/oauth/token \
-H 'content-type: application/json' \
-d '{"client_id":"'$FGA_CLIENT_ID'","client_secret":"'$FGA_CLIENT_SECRET'","audience":"https://api.us1.fga.dev/","grant_type":"client_credentials"}'
# The response will be returned in the form
# {
# "access_token": "eyJ...Ggg",
# "expires_in": 86400,
# "scope": "read:tuples write:tuples check:tuples ... write:authorization-models",
# "token_type": "Bearer"
# }
# Store this `access_token` value in environment variable `FGA_BEARER_TOKEN`
# For non-playground environment
FGA_SERVER_URL='https://api.us1.fga.dev'
# For playground environment
# FGA_SERVER_URL='https://api.playground.fga.dev'
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:charlie","relation":"viewer","object":"document:planning"}}'
# Response: {"allowed":true}
check(
user = "user:charlie", // check if the user `user:charlie`
relation = "viewer", // has an `viewer` relation
object = "document:planning", // with the object `document:planning`
authorization_id = "1uHxCSuTP0VKPYSnkq1pbb1jeZw"
);
Reply: true
This is because:
- Charlie is a member of the product team.
- There is a relationship tuple specifying that all members of the product team have a
viewer
relationship withdocument:planning
. - Direct relationships are allowed in the
viewer
relation definition in thedocument
type definition.
Note that this is still considered a direct relationship no matter how many resolutions occur on the usersets until the user is found.
For example, if our relationship tuples were the following relationship tuples:
- Dany is a member of the product leads team.
- Members of the product leads team are members of the product team.
- Members of the product team are members of the contoso team.
- Members of the contoso team are viewers of the planning document.
[
{
"user": "user:dany",
"relation": "member",
"object": "team:product-leads",
},
{
"user": "team:product-leads#member",
"relation": "member",
"object": "team:product",
},
{
"user": "team:product#member",
"relation": "member",
"object": "team:contoso",
},
{
"user": "team:contoso#member",
"relation": "viewer",
"object": "document:planning",
},
]
A subsequent check request to see if Dany can view the planning document will still return a response of {"allowed": true}
.
- Node.js
- Go
- .NET
- Python
- CLI
- curl
- Pseudocode
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:dany',
relation: 'viewer',
object: 'document:planning',
}, {
authorization_model_id: '1uHxCSuTP0VKPYSnkq1pbb1jeZw',
});
// allowed = true
Initialize the SDK
// Checkout the "How to Setup the SDK Client" page for more details.
import (
"os"
openfga "github.com/openfga/go-sdk"
. "github.com/openfga/go-sdk/client"
"github.com/openfga/go-sdk/credentials"
)
// 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
func main() {
fgaClient, err := NewSdkClient(&ClientConfiguration{
ApiScheme: os.Getenv("FGA_API_SCHEME")
ApiHost: os.Getenv("FGA_API_HOST"),
StoreId: os.Getenv("FGA_STORE_ID"),
AuthorizationModelId: openfga.PtrString(os.Getenv("FGA_MODEL_ID")),
Credentials: &credentials.Credentials{ // Credentials are not needed if connecting to the Playground API
Method: credentials.CredentialsMethodClientCredentials,
Config: &credentials.Config{
ClientCredentialsClientId: os.Getenv("FGA_CLIENT_ID"),
ClientCredentialsClientSecret: os.Getenv("FGA_CLIENT_SECRET"),
ClientCredentialsApiAudience: os.Getenv("FGA_API_AUDIENCE"),
ClientCredentialsApiTokenIssuer: os.Getenv("FGA_API_TOKEN_ISSUER"),
},
},
})
if err != nil {
// .. Handle error
}
}
options := ClientCheckOptions{
AuthorizationModelId: openfga.PtrString("1uHxCSuTP0VKPYSnkq1pbb1jeZw"),
}
body := ClientCheckRequest{
User: "user:dany",
Relation: "viewer",
Object: "document:planning",
}
data, err := fgaClient.Check(context.Background()).Body(body).Options(options).Execute()
// data = { allowed: true }
Initialize the SDK
// Checkout the "How to Setup the SDK Client" page for more details.
using OpenFga.Sdk.Client;
using OpenFga.Sdk.Client.Model;
using OpenFga.Sdk.Model;
using Environment = System.Environment;
namespace Example;
// 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
class MyProgram {
static async Task Main() {
var configuration = new ClientConfiguration() {
ApiScheme = Environment.GetEnvironmentVariable("FGA_API_SCHEME"),
ApiHost = Environment.GetEnvironmentVariable("FGA_API_HOST"),
StoreId = Environment.GetEnvironmentVariable("FGA_STORE_ID"),
AuthorizationModelId = Environment.GetEnvironmentVariable("FGA_MODEL_ID"),
Credentials = new Credentials() { // Credentials are not needed if connecting to the Playground API
Method = CredentialsMethod.ClientCredentials,
Config = new CredentialsConfig() {
ApiTokenIssuer = Environment.GetEnvironmentVariable("FGA_API_TOKEN_ISSUER"),
ApiAudience = Environment.GetEnvironmentVariable("FGA_API_AUDIENCE"),
ClientId = Environment.GetEnvironmentVariable("FGA_CLIENT_ID"),
ClientSecret = Environment.GetEnvironmentVariable("FGA_CLIENT_SECRET"),
}
}
};
var fgaClient = new OpenFgaClient(configuration);
}
}
var options = new ClientCheckOptions {
AuthorizationModelId = "1uHxCSuTP0VKPYSnkq1pbb1jeZw",
};
var body = new ClientCheckRequest {
User = "user:dany",
Relation = "viewer",
Object = "document:planning",
};
var response = await fgaClient.Check(body, options);
// response.Allowed = true
Initialize the SDK
# Checkout the "How to Setup the SDK Client" page for more details.
import os
import openfga_sdk
from openfga_sdk.client import OpenFgaClient, ClientConfiguration
from openfga_sdk.credentials import Credentials, CredentialConfiguration
# 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
credentials = Credentials(
method='client_credentials',
configuration=CredentialConfiguration(
api_issuer= os.environ.get('FGA_API_TOKEN_ISSUER'),
api_audience= os.environ.get('FGA_API_AUDIENCE'),
client_id= os.environ.get('FGA_CLIENT_ID'),
client_secret= os.environ.get('FGA_CLIENT_SECRET'),
)
)
configuration = ClientConfiguration(
api_scheme = os.environ.get('FGA_API_SCHEME'),
api_host = os.environ.get('FGA_API_HOST'),
store_id = os.environ.get('FGA_STORE_ID'),
model_id = os.environ.get('FGA_MODEL_ID'),
credentials = credentials, # Credentials are not needed if connecting to the Playground API
)
async with OpenFgaClient(configuration) as fga_client:
api_response = await fga_client.read_authorization_models() # call requests
await fga_client.close() # close when done
options = {
"authorization_model_id": "1uHxCSuTP0VKPYSnkq1pbb1jeZw"
}
body = ClientCheckRequest(
user="user:dany",
relation="viewer",
object="document:planning",
)
response = await fga_client.check(body, options)
# response.allowed = true
Set the required environment variables
# Not needed when calling the Playground API
curl -X POST \
https://fga.us.auth0.com/oauth/token \
-H 'content-type: application/json' \
-d '{"client_id":"'$FGA_CLIENT_ID'","client_secret":"'$FGA_CLIENT_SECRET'","audience":"https://api.us1.fga.dev/","grant_type":"client_credentials"}'
# The response will be returned in the form
# {
# "access_token": "eyJ...Ggg",
# "expires_in": 86400,
# "scope": "read:tuples write:tuples check:tuples ... write:authorization-models",
# "token_type": "Bearer"
# }
# Store this `access_token` value in environment variable `FGA_BEARER_TOKEN`
# For non-playground environment
FGA_SERVER_URL='https://api.us1.fga.dev'
# For playground environment
# FGA_SERVER_URL='https://api.playground.fga.dev'
fga query check --store-id=$FGA_STORE_ID --model-id=1uHxCSuTP0VKPYSnkq1pbb1jeZw user:dany viewer document:planning
# Response: {"allowed":true}
Set the required environment variables
# Not needed when calling the Playground API
curl -X POST \
https://fga.us.auth0.com/oauth/token \
-H 'content-type: application/json' \
-d '{"client_id":"'$FGA_CLIENT_ID'","client_secret":"'$FGA_CLIENT_SECRET'","audience":"https://api.us1.fga.dev/","grant_type":"client_credentials"}'
# The response will be returned in the form
# {
# "access_token": "eyJ...Ggg",
# "expires_in": 86400,
# "scope": "read:tuples write:tuples check:tuples ... write:authorization-models",
# "token_type": "Bearer"
# }
# Store this `access_token` value in environment variable `FGA_BEARER_TOKEN`
# For non-playground environment
FGA_SERVER_URL='https://api.us1.fga.dev'
# For playground environment
# FGA_SERVER_URL='https://api.playground.fga.dev'
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:dany","relation":"viewer","object":"document:planning"}}'
# Response: {"allowed":true}
check(
user = "user:dany", // check if the user `user:dany`
relation = "viewer", // has an `viewer` relation
object = "document:planning", // with the object `document:planning`
authorization_id = "1uHxCSuTP0VKPYSnkq1pbb1jeZw"
);
Reply: true
Note: Even though the relationship tuple stored in the system does not specify the user (charlie
or dany
), this is still considered a direct relationship.
Here we will cover one example of an indirect relationship in order to see how they differ from direct relationships.
With the same authorization model we have above, assume there is a relationship tuple that specifies that Emily is an editor
of document:planning
.
[
{
"user": "user:emily",
"relation": "editor",
"object": "document:planning",
},
]
A subsequent check request to see if emily can view the planning document will still return a response of {"allowed": true}
.
- Node.js
- Go
- .NET
- Python
- CLI
- curl
- Pseudocode
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:emily',
relation: 'viewer',
object: 'document:planning',
}, {
authorization_model_id: '1uHxCSuTP0VKPYSnkq1pbb1jeZw',
});
// allowed = true
Initialize the SDK
// Checkout the "How to Setup the SDK Client" page for more details.
import (
"os"
openfga "github.com/openfga/go-sdk"
. "github.com/openfga/go-sdk/client"
"github.com/openfga/go-sdk/credentials"
)
// 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
func main() {
fgaClient, err := NewSdkClient(&ClientConfiguration{
ApiScheme: os.Getenv("FGA_API_SCHEME")
ApiHost: os.Getenv("FGA_API_HOST"),
StoreId: os.Getenv("FGA_STORE_ID"),
AuthorizationModelId: openfga.PtrString(os.Getenv("FGA_MODEL_ID")),
Credentials: &credentials.Credentials{ // Credentials are not needed if connecting to the Playground API
Method: credentials.CredentialsMethodClientCredentials,
Config: &credentials.Config{
ClientCredentialsClientId: os.Getenv("FGA_CLIENT_ID"),
ClientCredentialsClientSecret: os.Getenv("FGA_CLIENT_SECRET"),
ClientCredentialsApiAudience: os.Getenv("FGA_API_AUDIENCE"),
ClientCredentialsApiTokenIssuer: os.Getenv("FGA_API_TOKEN_ISSUER"),
},
},
})
if err != nil {
// .. Handle error
}
}
options := ClientCheckOptions{
AuthorizationModelId: openfga.PtrString("1uHxCSuTP0VKPYSnkq1pbb1jeZw"),
}
body := ClientCheckRequest{
User: "user:emily",
Relation: "viewer",
Object: "document:planning",
}
data, err := fgaClient.Check(context.Background()).Body(body).Options(options).Execute()
// data = { allowed: true }
Initialize the SDK
// Checkout the "How to Setup the SDK Client" page for more details.
using OpenFga.Sdk.Client;
using OpenFga.Sdk.Client.Model;
using OpenFga.Sdk.Model;
using Environment = System.Environment;
namespace Example;
// 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
class MyProgram {
static async Task Main() {
var configuration = new ClientConfiguration() {
ApiScheme = Environment.GetEnvironmentVariable("FGA_API_SCHEME"),
ApiHost = Environment.GetEnvironmentVariable("FGA_API_HOST"),
StoreId = Environment.GetEnvironmentVariable("FGA_STORE_ID"),
AuthorizationModelId = Environment.GetEnvironmentVariable("FGA_MODEL_ID"),
Credentials = new Credentials() { // Credentials are not needed if connecting to the Playground API
Method = CredentialsMethod.ClientCredentials,
Config = new CredentialsConfig() {
ApiTokenIssuer = Environment.GetEnvironmentVariable("FGA_API_TOKEN_ISSUER"),
ApiAudience = Environment.GetEnvironmentVariable("FGA_API_AUDIENCE"),
ClientId = Environment.GetEnvironmentVariable("FGA_CLIENT_ID"),
ClientSecret = Environment.GetEnvironmentVariable("FGA_CLIENT_SECRET"),
}
}
};
var fgaClient = new OpenFgaClient(configuration);
}
}
var options = new ClientCheckOptions {
AuthorizationModelId = "1uHxCSuTP0VKPYSnkq1pbb1jeZw",
};
var body = new ClientCheckRequest {
User = "user:emily",
Relation = "viewer",
Object = "document:planning",
};
var response = await fgaClient.Check(body, options);
// response.Allowed = true
Initialize the SDK
# Checkout the "How to Setup the SDK Client" page for more details.
import os
import openfga_sdk
from openfga_sdk.client import OpenFgaClient, ClientConfiguration
from openfga_sdk.credentials import Credentials, CredentialConfiguration
# 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
credentials = Credentials(
method='client_credentials',
configuration=CredentialConfiguration(
api_issuer= os.environ.get('FGA_API_TOKEN_ISSUER'),
api_audience= os.environ.get('FGA_API_AUDIENCE'),
client_id= os.environ.get('FGA_CLIENT_ID'),
client_secret= os.environ.get('FGA_CLIENT_SECRET'),
)
)
configuration = ClientConfiguration(
api_scheme = os.environ.get('FGA_API_SCHEME'),
api_host = os.environ.get('FGA_API_HOST'),
store_id = os.environ.get('FGA_STORE_ID'),
model_id = os.environ.get('FGA_MODEL_ID'),
credentials = credentials, # Credentials are not needed if connecting to the Playground API
)
async with OpenFgaClient(configuration) as fga_client:
api_response = await fga_client.read_authorization_models() # call requests
await fga_client.close() # close when done
options = {
"authorization_model_id": "1uHxCSuTP0VKPYSnkq1pbb1jeZw"
}
body = ClientCheckRequest(
user="user:emily",
relation="viewer",
object="document:planning",
)
response = await fga_client.check(body, options)
# response.allowed = true
Set the required environment variables
# Not needed when calling the Playground API
curl -X POST \
https://fga.us.auth0.com/oauth/token \
-H 'content-type: application/json' \
-d '{"client_id":"'$FGA_CLIENT_ID'","client_secret":"'$FGA_CLIENT_SECRET'","audience":"https://api.us1.fga.dev/","grant_type":"client_credentials"}'
# The response will be returned in the form
# {
# "access_token": "eyJ...Ggg",
# "expires_in": 86400,
# "scope": "read:tuples write:tuples check:tuples ... write:authorization-models",
# "token_type": "Bearer"
# }
# Store this `access_token` value in environment variable `FGA_BEARER_TOKEN`
# For non-playground environment
FGA_SERVER_URL='https://api.us1.fga.dev'
# For playground environment
# FGA_SERVER_URL='https://api.playground.fga.dev'
fga query check --store-id=$FGA_STORE_ID --model-id=1uHxCSuTP0VKPYSnkq1pbb1jeZw user:emily viewer document:planning
# Response: {"allowed":true}
Set the required environment variables
# Not needed when calling the Playground API
curl -X POST \
https://fga.us.auth0.com/oauth/token \
-H 'content-type: application/json' \
-d '{"client_id":"'$FGA_CLIENT_ID'","client_secret":"'$FGA_CLIENT_SECRET'","audience":"https://api.us1.fga.dev/","grant_type":"client_credentials"}'
# The response will be returned in the form
# {
# "access_token": "eyJ...Ggg",
# "expires_in": 86400,
# "scope": "read:tuples write:tuples check:tuples ... write:authorization-models",
# "token_type": "Bearer"
# }
# Store this `access_token` value in environment variable `FGA_BEARER_TOKEN`
# For non-playground environment
FGA_SERVER_URL='https://api.us1.fga.dev'
# For playground environment
# FGA_SERVER_URL='https://api.playground.fga.dev'
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:emily","relation":"viewer","object":"document:planning"}}'
# Response: {"allowed":true}
check(
user = "user:emily", // check if the user `user:emily`
relation = "viewer", // has an `viewer` relation
object = "document:planning", // with the object `document:planning`
authorization_id = "1uHxCSuTP0VKPYSnkq1pbb1jeZw"
);
Reply: true
This is because:
- Emily is an
editor
of the planning document. - The authorization model specified that anyone who is an
editor
on adocument
is also aviewer
on that document.
In this case, there is NO direct viewer relationship between Emily and the planning document. The only viewer relationship that exists is implied because Emily is an editor and the authorization model specified that any document's editor
is that document's viewer.
2. With Direct Relationships Disabled
In this section, we will investigate the effect of disabling direct relationships on the document's viewer
relation.
- DSL
- JSON
model
schema 1.1
type user
type document
relations
define viewer: editor
define editor: [user, team#member]
type team
relations
define member: [user]
{
"schema_version": "1.1",
"type_definitions": [
{
"type": "user"
},
{
"type": "document",
"relations": {
"viewer": {
"computedUserset": {
"relation": "editor"
}
},
"editor": {
"this": {}
}
},
"metadata": {
"relations": {
"editor": {
"directly_related_user_types": [
{
"type": "user"
},
{
"type": "team",
"relation": "member"
}
]
}
}
}
},
{
"type": "team",
"relations": {
"member": {
"this": {}
}
},
"metadata": {
"relations": {
"member": {
"directly_related_user_types": [
{
"type": "user"
}
]
}
}
}
}
]
}
Notice that in this updated authorization model, the direct relationship keyword has been removed from the document's viewer
relation definition.
Now choose the type of relation to see how it affects your system:
- Direct User
- Everyone
- Userset
- Indirect Relationship
Assume you have a tuple that states that Fred is a viewer
of document:planning
[
{
"user": "user:fred",
"relation": "viewer",
"object": "document:planning",
},
]
Now if we do a check request to see if Fred can view the planning document, we will get a response of {"allowed": false}
.
- Node.js
- Go
- .NET
- Python
- CLI
- curl
- Pseudocode
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:fred',
relation: 'viewer',
object: 'document:planning',
}, {
authorization_model_id: '1uHxCSuTP0VKPYSnkq1pbb1jeZw',
});
// allowed = false
Initialize the SDK
// Checkout the "How to Setup the SDK Client" page for more details.
import (
"os"
openfga "github.com/openfga/go-sdk"
. "github.com/openfga/go-sdk/client"
"github.com/openfga/go-sdk/credentials"
)
// 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
func main() {
fgaClient, err := NewSdkClient(&ClientConfiguration{
ApiScheme: os.Getenv("FGA_API_SCHEME")
ApiHost: os.Getenv("FGA_API_HOST"),
StoreId: os.Getenv("FGA_STORE_ID"),
AuthorizationModelId: openfga.PtrString(os.Getenv("FGA_MODEL_ID")),
Credentials: &credentials.Credentials{ // Credentials are not needed if connecting to the Playground API
Method: credentials.CredentialsMethodClientCredentials,
Config: &credentials.Config{
ClientCredentialsClientId: os.Getenv("FGA_CLIENT_ID"),
ClientCredentialsClientSecret: os.Getenv("FGA_CLIENT_SECRET"),
ClientCredentialsApiAudience: os.Getenv("FGA_API_AUDIENCE"),
ClientCredentialsApiTokenIssuer: os.Getenv("FGA_API_TOKEN_ISSUER"),
},
},
})
if err != nil {
// .. Handle error
}
}
options := ClientCheckOptions{
AuthorizationModelId: openfga.PtrString("1uHxCSuTP0VKPYSnkq1pbb1jeZw"),
}
body := ClientCheckRequest{
User: "user:fred",
Relation: "viewer",
Object: "document:planning",
}
data, err := fgaClient.Check(context.Background()).Body(body).Options(options).Execute()
// data = { allowed: false }
Initialize the SDK
// Checkout the "How to Setup the SDK Client" page for more details.
using OpenFga.Sdk.Client;
using OpenFga.Sdk.Client.Model;
using OpenFga.Sdk.Model;
using Environment = System.Environment;
namespace Example;
// 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
class MyProgram {
static async Task Main() {
var configuration = new ClientConfiguration() {
ApiScheme = Environment.GetEnvironmentVariable("FGA_API_SCHEME"),
ApiHost = Environment.GetEnvironmentVariable("FGA_API_HOST"),
StoreId = Environment.GetEnvironmentVariable("FGA_STORE_ID"),
AuthorizationModelId = Environment.GetEnvironmentVariable("FGA_MODEL_ID"),
Credentials = new Credentials() { // Credentials are not needed if connecting to the Playground API
Method = CredentialsMethod.ClientCredentials,
Config = new CredentialsConfig() {
ApiTokenIssuer = Environment.GetEnvironmentVariable("FGA_API_TOKEN_ISSUER"),
ApiAudience = Environment.GetEnvironmentVariable("FGA_API_AUDIENCE"),
ClientId = Environment.GetEnvironmentVariable("FGA_CLIENT_ID"),
ClientSecret = Environment.GetEnvironmentVariable("FGA_CLIENT_SECRET"),
}
}
};
var fgaClient = new OpenFgaClient(configuration);
}
}
var options = new ClientCheckOptions {
AuthorizationModelId = "1uHxCSuTP0VKPYSnkq1pbb1jeZw",
};
var body = new ClientCheckRequest {
User = "user:fred",
Relation = "viewer",
Object = "document:planning",
};
var response = await fgaClient.Check(body, options);
// response.Allowed = false
Initialize the SDK
# Checkout the "How to Setup the SDK Client" page for more details.
import os
import openfga_sdk
from openfga_sdk.client import OpenFgaClient, ClientConfiguration
from openfga_sdk.credentials import Credentials, CredentialConfiguration
# 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
credentials = Credentials(
method='client_credentials',
configuration=CredentialConfiguration(
api_issuer= os.environ.get('FGA_API_TOKEN_ISSUER'),
api_audience= os.environ.get('FGA_API_AUDIENCE'),
client_id= os.environ.get('FGA_CLIENT_ID'),
client_secret= os.environ.get('FGA_CLIENT_SECRET'),
)
)
configuration = ClientConfiguration(
api_scheme = os.environ.get('FGA_API_SCHEME'),
api_host = os.environ.get('FGA_API_HOST'),
store_id = os.environ.get('FGA_STORE_ID'),
model_id = os.environ.get('FGA_MODEL_ID'),
credentials = credentials, # Credentials are not needed if connecting to the Playground API
)
async with OpenFgaClient(configuration) as fga_client:
api_response = await fga_client.read_authorization_models() # call requests
await fga_client.close() # close when done
options = {
"authorization_model_id": "1uHxCSuTP0VKPYSnkq1pbb1jeZw"
}
body = ClientCheckRequest(
user="user:fred",
relation="viewer",
object="document:planning",
)
response = await fga_client.check(body, options)
# response.allowed = false
Set the required environment variables
# Not needed when calling the Playground API
curl -X POST \
https://fga.us.auth0.com/oauth/token \
-H 'content-type: application/json' \
-d '{"client_id":"'$FGA_CLIENT_ID'","client_secret":"'$FGA_CLIENT_SECRET'","audience":"https://api.us1.fga.dev/","grant_type":"client_credentials"}'
# The response will be returned in the form
# {
# "access_token": "eyJ...Ggg",
# "expires_in": 86400,
# "scope": "read:tuples write:tuples check:tuples ... write:authorization-models",
# "token_type": "Bearer"
# }
# Store this `access_token` value in environment variable `FGA_BEARER_TOKEN`
# For non-playground environment
FGA_SERVER_URL='https://api.us1.fga.dev'
# For playground environment
# FGA_SERVER_URL='https://api.playground.fga.dev'
fga query check --store-id=$FGA_STORE_ID --model-id=1uHxCSuTP0VKPYSnkq1pbb1jeZw user:fred viewer document:planning
# Response: {"allowed":false}
Set the required environment variables
# Not needed when calling the Playground API
curl -X POST \
https://fga.us.auth0.com/oauth/token \
-H 'content-type: application/json' \
-d '{"client_id":"'$FGA_CLIENT_ID'","client_secret":"'$FGA_CLIENT_SECRET'","audience":"https://api.us1.fga.dev/","grant_type":"client_credentials"}'
# The response will be returned in the form
# {
# "access_token": "eyJ...Ggg",
# "expires_in": 86400,
# "scope": "read:tuples write:tuples check:tuples ... write:authorization-models",
# "token_type": "Bearer"
# }
# Store this `access_token` value in environment variable `FGA_BEARER_TOKEN`
# For non-playground environment
FGA_SERVER_URL='https://api.us1.fga.dev'
# For playground environment
# FGA_SERVER_URL='https://api.playground.fga.dev'
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:fred","relation":"viewer","object":"document:planning"}}'
# Response: {"allowed":false}
check(
user = "user:fred", // check if the user `user:fred`
relation = "viewer", // has an `viewer` relation
object = "document:planning", // with the object `document:planning`
authorization_id = "1uHxCSuTP0VKPYSnkq1pbb1jeZw"
);
Reply: false
This is because:
- Even though there is a relationship tuple specifying that Fred has a
viewer
relationship withdocument:planning
. - Direct relationships are NOT allowed in the
viewer
relation definition in thedocument
type definition.
You will see the same behaviour with a relationship tuple specifying everyone of type user
as the user.
Assume you have a tuple that states that everyone of type user
is a viewer
of document:planning
.
[
{
"user": "user:*",
"relation": "viewer",
"object": "document:planning",
},
]
Now if we do a check request to see if Gabriel can view the planning document, we will get a response of {"allowed": false}
.
- Node.js
- Go
- .NET
- Python
- CLI
- curl
- Pseudocode
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:gabriel',
relation: 'viewer',
object: 'document:planning',
}, {
authorization_model_id: '1uHxCSuTP0VKPYSnkq1pbb1jeZw',
});
// allowed = false
Initialize the SDK
// Checkout the "How to Setup the SDK Client" page for more details.
import (
"os"
openfga "github.com/openfga/go-sdk"
. "github.com/openfga/go-sdk/client"
"github.com/openfga/go-sdk/credentials"
)
// 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
func main() {
fgaClient, err := NewSdkClient(&ClientConfiguration{
ApiScheme: os.Getenv("FGA_API_SCHEME")
ApiHost: os.Getenv("FGA_API_HOST"),
StoreId: os.Getenv("FGA_STORE_ID"),
AuthorizationModelId: openfga.PtrString(os.Getenv("FGA_MODEL_ID")),
Credentials: &credentials.Credentials{ // Credentials are not needed if connecting to the Playground API
Method: credentials.CredentialsMethodClientCredentials,
Config: &credentials.Config{
ClientCredentialsClientId: os.Getenv("FGA_CLIENT_ID"),
ClientCredentialsClientSecret: os.Getenv("FGA_CLIENT_SECRET"),
ClientCredentialsApiAudience: os.Getenv("FGA_API_AUDIENCE"),
ClientCredentialsApiTokenIssuer: os.Getenv("FGA_API_TOKEN_ISSUER"),
},
},
})
if err != nil {
// .. Handle error
}
}
options := ClientCheckOptions{
AuthorizationModelId: openfga.PtrString("1uHxCSuTP0VKPYSnkq1pbb1jeZw"),
}
body := ClientCheckRequest{
User: "user:gabriel",
Relation: "viewer",
Object: "document:planning",
}
data, err := fgaClient.Check(context.Background()).Body(body).Options(options).Execute()
// data = { allowed: false }
Initialize the SDK
// Checkout the "How to Setup the SDK Client" page for more details.
using OpenFga.Sdk.Client;
using OpenFga.Sdk.Client.Model;
using OpenFga.Sdk.Model;
using Environment = System.Environment;
namespace Example;
// 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
class MyProgram {
static async Task Main() {
var configuration = new ClientConfiguration() {
ApiScheme = Environment.GetEnvironmentVariable("FGA_API_SCHEME"),
ApiHost = Environment.GetEnvironmentVariable("FGA_API_HOST"),
StoreId = Environment.GetEnvironmentVariable("FGA_STORE_ID"),
AuthorizationModelId = Environment.GetEnvironmentVariable("FGA_MODEL_ID"),
Credentials = new Credentials() { // Credentials are not needed if connecting to the Playground API
Method = CredentialsMethod.ClientCredentials,
Config = new CredentialsConfig() {
ApiTokenIssuer = Environment.GetEnvironmentVariable("FGA_API_TOKEN_ISSUER"),
ApiAudience = Environment.GetEnvironmentVariable("FGA_API_AUDIENCE"),
ClientId = Environment.GetEnvironmentVariable("FGA_CLIENT_ID"),
ClientSecret = Environment.GetEnvironmentVariable("FGA_CLIENT_SECRET"),
}
}
};
var fgaClient = new OpenFgaClient(configuration);
}
}
var options = new ClientCheckOptions {
AuthorizationModelId = "1uHxCSuTP0VKPYSnkq1pbb1jeZw",
};
var body = new ClientCheckRequest {
User = "user:gabriel",
Relation = "viewer",
Object = "document:planning",
};
var response = await fgaClient.Check(body, options);
// response.Allowed = false
Initialize the SDK
# Checkout the "How to Setup the SDK Client" page for more details.
import os
import openfga_sdk
from openfga_sdk.client import OpenFgaClient, ClientConfiguration
from openfga_sdk.credentials import Credentials, CredentialConfiguration
# 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
credentials = Credentials(
method='client_credentials',
configuration=CredentialConfiguration(
api_issuer= os.environ.get('FGA_API_TOKEN_ISSUER'),
api_audience= os.environ.get('FGA_API_AUDIENCE'),
client_id= os.environ.get('FGA_CLIENT_ID'),
client_secret= os.environ.get('FGA_CLIENT_SECRET'),
)
)
configuration = ClientConfiguration(
api_scheme = os.environ.get('FGA_API_SCHEME'),
api_host = os.environ.get('FGA_API_HOST'),
store_id = os.environ.get('FGA_STORE_ID'),
model_id = os.environ.get('FGA_MODEL_ID'),
credentials = credentials, # Credentials are not needed if connecting to the Playground API
)
async with OpenFgaClient(configuration) as fga_client:
api_response = await fga_client.read_authorization_models() # call requests
await fga_client.close() # close when done
options = {
"authorization_model_id": "1uHxCSuTP0VKPYSnkq1pbb1jeZw"
}
body = ClientCheckRequest(
user="user:gabriel",
relation="viewer",
object="document:planning",
)
response = await fga_client.check(body, options)
# response.allowed = false
Set the required environment variables
# Not needed when calling the Playground API
curl -X POST \
https://fga.us.auth0.com/oauth/token \
-H 'content-type: application/json' \
-d '{"client_id":"'$FGA_CLIENT_ID'","client_secret":"'$FGA_CLIENT_SECRET'","audience":"https://api.us1.fga.dev/","grant_type":"client_credentials"}'
# The response will be returned in the form
# {
# "access_token": "eyJ...Ggg",
# "expires_in": 86400,
# "scope": "read:tuples write:tuples check:tuples ... write:authorization-models",
# "token_type": "Bearer"
# }
# Store this `access_token` value in environment variable `FGA_BEARER_TOKEN`
# For non-playground environment
FGA_SERVER_URL='https://api.us1.fga.dev'
# For playground environment
# FGA_SERVER_URL='https://api.playground.fga.dev'
fga query check --store-id=$FGA_STORE_ID --model-id=1uHxCSuTP0VKPYSnkq1pbb1jeZw user:gabriel viewer document:planning
# Response: {"allowed":false}
Set the required environment variables
# Not needed when calling the Playground API
curl -X POST \
https://fga.us.auth0.com/oauth/token \
-H 'content-type: application/json' \
-d '{"client_id":"'$FGA_CLIENT_ID'","client_secret":"'$FGA_CLIENT_SECRET'","audience":"https://api.us1.fga.dev/","grant_type":"client_credentials"}'
# The response will be returned in the form
# {
# "access_token": "eyJ...Ggg",
# "expires_in": 86400,
# "scope": "read:tuples write:tuples check:tuples ... write:authorization-models",
# "token_type": "Bearer"
# }
# Store this `access_token` value in environment variable `FGA_BEARER_TOKEN`
# For non-playground environment
FGA_SERVER_URL='https://api.us1.fga.dev'
# For playground environment
# FGA_SERVER_URL='https://api.playground.fga.dev'
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:gabriel","relation":"viewer","object":"document:planning"}}'
# Response: {"allowed":false}
check(
user = "user:gabriel", // check if the user `user:gabriel`
relation = "viewer", // has an `viewer` relation
object = "document:planning", // with the object `document:planning`
authorization_id = "1uHxCSuTP0VKPYSnkq1pbb1jeZw"
);
Reply: false
This is because:
- Even though there is a relationship tuple specifying that everyone has a
viewer
relationship withdocument:planning
. - Direct relationships are NOT allowed in the
viewer
relation definition in thedocument
type definition.
The same logic applies to usersets.
Assume you have two relationship tuples:
- Henry is a member of the product team.
- Members of the product team are viewers of the planning document.
[
{
"user": "user:henry",
"relation": "member",
"object": "team:product",
},
{
"user": "team:product#member",
"relation": "viewer",
"object": "document:planning",
},
]
Now if we do a check request to see if Henry can view the planning document, we will get a response of {"allowed": false}
.
- Node.js
- Go
- .NET
- Python
- CLI
- curl
- Pseudocode
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:henry',
relation: 'viewer',
object: 'document:planning',
}, {
authorization_model_id: '1uHxCSuTP0VKPYSnkq1pbb1jeZw',
});
// allowed = false
Initialize the SDK
// Checkout the "How to Setup the SDK Client" page for more details.
import (
"os"
openfga "github.com/openfga/go-sdk"
. "github.com/openfga/go-sdk/client"
"github.com/openfga/go-sdk/credentials"
)
// 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
func main() {
fgaClient, err := NewSdkClient(&ClientConfiguration{
ApiScheme: os.Getenv("FGA_API_SCHEME")
ApiHost: os.Getenv("FGA_API_HOST"),
StoreId: os.Getenv("FGA_STORE_ID"),
AuthorizationModelId: openfga.PtrString(os.Getenv("FGA_MODEL_ID")),
Credentials: &credentials.Credentials{ // Credentials are not needed if connecting to the Playground API
Method: credentials.CredentialsMethodClientCredentials,
Config: &credentials.Config{
ClientCredentialsClientId: os.Getenv("FGA_CLIENT_ID"),
ClientCredentialsClientSecret: os.Getenv("FGA_CLIENT_SECRET"),
ClientCredentialsApiAudience: os.Getenv("FGA_API_AUDIENCE"),
ClientCredentialsApiTokenIssuer: os.Getenv("FGA_API_TOKEN_ISSUER"),
},
},
})
if err != nil {
// .. Handle error
}
}
options := ClientCheckOptions{
AuthorizationModelId: openfga.PtrString("1uHxCSuTP0VKPYSnkq1pbb1jeZw"),
}
body := ClientCheckRequest{
User: "user:henry",
Relation: "viewer",
Object: "document:planning",
}
data, err := fgaClient.Check(context.Background()).Body(body).Options(options).Execute()
// data = { allowed: false }
Initialize the SDK
// Checkout the "How to Setup the SDK Client" page for more details.
using OpenFga.Sdk.Client;
using OpenFga.Sdk.Client.Model;
using OpenFga.Sdk.Model;
using Environment = System.Environment;
namespace Example;
// 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
class MyProgram {
static async Task Main() {
var configuration = new ClientConfiguration() {
ApiScheme = Environment.GetEnvironmentVariable("FGA_API_SCHEME"),
ApiHost = Environment.GetEnvironmentVariable("FGA_API_HOST"),
StoreId = Environment.GetEnvironmentVariable("FGA_STORE_ID"),
AuthorizationModelId = Environment.GetEnvironmentVariable("FGA_MODEL_ID"),
Credentials = new Credentials() { // Credentials are not needed if connecting to the Playground API
Method = CredentialsMethod.ClientCredentials,
Config = new CredentialsConfig() {
ApiTokenIssuer = Environment.GetEnvironmentVariable("FGA_API_TOKEN_ISSUER"),
ApiAudience = Environment.GetEnvironmentVariable("FGA_API_AUDIENCE"),
ClientId = Environment.GetEnvironmentVariable("FGA_CLIENT_ID"),
ClientSecret = Environment.GetEnvironmentVariable("FGA_CLIENT_SECRET"),
}
}
};
var fgaClient = new OpenFgaClient(configuration);
}
}
var options = new ClientCheckOptions {
AuthorizationModelId = "1uHxCSuTP0VKPYSnkq1pbb1jeZw",
};
var body = new ClientCheckRequest {
User = "user:henry",
Relation = "viewer",
Object = "document:planning",
};
var response = await fgaClient.Check(body, options);
// response.Allowed = false
Initialize the SDK
# Checkout the "How to Setup the SDK Client" page for more details.
import os
import openfga_sdk
from openfga_sdk.client import OpenFgaClient, ClientConfiguration
from openfga_sdk.credentials import Credentials, CredentialConfiguration
# 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
credentials = Credentials(
method='client_credentials',
configuration=CredentialConfiguration(
api_issuer= os.environ.get('FGA_API_TOKEN_ISSUER'),
api_audience= os.environ.get('FGA_API_AUDIENCE'),
client_id= os.environ.get('FGA_CLIENT_ID'),
client_secret= os.environ.get('FGA_CLIENT_SECRET'),
)
)
configuration = ClientConfiguration(
api_scheme = os.environ.get('FGA_API_SCHEME'),
api_host = os.environ.get('FGA_API_HOST'),
store_id = os.environ.get('FGA_STORE_ID'),
model_id = os.environ.get('FGA_MODEL_ID'),
credentials = credentials, # Credentials are not needed if connecting to the Playground API
)
async with OpenFgaClient(configuration) as fga_client:
api_response = await fga_client.read_authorization_models() # call requests
await fga_client.close() # close when done
options = {
"authorization_model_id": "1uHxCSuTP0VKPYSnkq1pbb1jeZw"
}
body = ClientCheckRequest(
user="user:henry",
relation="viewer",
object="document:planning",
)
response = await fga_client.check(body, options)
# response.allowed = false
Set the required environment variables
# Not needed when calling the Playground API
curl -X POST \
https://fga.us.auth0.com/oauth/token \
-H 'content-type: application/json' \
-d '{"client_id":"'$FGA_CLIENT_ID'","client_secret":"'$FGA_CLIENT_SECRET'","audience":"https://api.us1.fga.dev/","grant_type":"client_credentials"}'
# The response will be returned in the form
# {
# "access_token": "eyJ...Ggg",
# "expires_in": 86400,
# "scope": "read:tuples write:tuples check:tuples ... write:authorization-models",
# "token_type": "Bearer"
# }
# Store this `access_token` value in environment variable `FGA_BEARER_TOKEN`
# For non-playground environment
FGA_SERVER_URL='https://api.us1.fga.dev'
# For playground environment
# FGA_SERVER_URL='https://api.playground.fga.dev'
fga query check --store-id=$FGA_STORE_ID --model-id=1uHxCSuTP0VKPYSnkq1pbb1jeZw user:henry viewer document:planning
# Response: {"allowed":false}
Set the required environment variables
# Not needed when calling the Playground API
curl -X POST \
https://fga.us.auth0.com/oauth/token \
-H 'content-type: application/json' \
-d '{"client_id":"'$FGA_CLIENT_ID'","client_secret":"'$FGA_CLIENT_SECRET'","audience":"https://api.us1.fga.dev/","grant_type":"client_credentials"}'
# The response will be returned in the form
# {
# "access_token": "eyJ...Ggg",
# "expires_in": 86400,
# "scope": "read:tuples write:tuples check:tuples ... write:authorization-models",
# "token_type": "Bearer"
# }
# Store this `access_token` value in environment variable `FGA_BEARER_TOKEN`
# For non-playground environment
FGA_SERVER_URL='https://api.us1.fga.dev'
# For playground environment
# FGA_SERVER_URL='https://api.playground.fga.dev'
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:henry","relation":"viewer","object":"document:planning"}}'
# Response: {"allowed":false}
check(
user = "user:henry", // check if the user `user:henry`
relation = "viewer", // has an `viewer` relation
object = "document:planning", // with the object `document:planning`
authorization_id = "1uHxCSuTP0VKPYSnkq1pbb1jeZw"
);
Reply: false
This is because although:
- Henry is a member of the product team.
- There is a relationship tuple specifying that all members of the product team have a
viewer
relationship withdocument:planning
.
Direct relationships are NOT allowed in the viewer
relation definition in the document
type definition.
Indirect relationships are not affected by disabling a direct relationship on a certain relation.
Assume there is a relationship tuple that specifies that Ingred is an editor
of document:planning
.
[
{
"user": "user:ingred",
"relation": "editor",
"object": "document:planning",
},
]
A subsequent check request to see if Ingred can view the planning document will still return a response of {"allowed": true}
.
- Node.js
- Go
- .NET
- Python
- CLI
- curl
- Pseudocode
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:ingred',
relation: 'viewer',
object: 'document:planning',
}, {
authorization_model_id: '1uHxCSuTP0VKPYSnkq1pbb1jeZw',
});
// allowed = true
Initialize the SDK
// Checkout the "How to Setup the SDK Client" page for more details.
import (
"os"
openfga "github.com/openfga/go-sdk"
. "github.com/openfga/go-sdk/client"
"github.com/openfga/go-sdk/credentials"
)
// 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
func main() {
fgaClient, err := NewSdkClient(&ClientConfiguration{
ApiScheme: os.Getenv("FGA_API_SCHEME")
ApiHost: os.Getenv("FGA_API_HOST"),
StoreId: os.Getenv("FGA_STORE_ID"),
AuthorizationModelId: openfga.PtrString(os.Getenv("FGA_MODEL_ID")),
Credentials: &credentials.Credentials{ // Credentials are not needed if connecting to the Playground API
Method: credentials.CredentialsMethodClientCredentials,
Config: &credentials.Config{
ClientCredentialsClientId: os.Getenv("FGA_CLIENT_ID"),
ClientCredentialsClientSecret: os.Getenv("FGA_CLIENT_SECRET"),
ClientCredentialsApiAudience: os.Getenv("FGA_API_AUDIENCE"),
ClientCredentialsApiTokenIssuer: os.Getenv("FGA_API_TOKEN_ISSUER"),
},
},
})
if err != nil {
// .. Handle error
}
}
options := ClientCheckOptions{
AuthorizationModelId: openfga.PtrString("1uHxCSuTP0VKPYSnkq1pbb1jeZw"),
}
body := ClientCheckRequest{
User: "user:ingred",
Relation: "viewer",
Object: "document:planning",
}
data, err := fgaClient.Check(context.Background()).Body(body).Options(options).