Custom Roles
In this guide you'll learn how to model custom roles in your system using OpenFGA.
For example, a Business-to-Business (B2B) application could allow customers to create their own custom roles on the application to grant their users.
In many cases, roles would fit in well as relations on an object type, as seen in Modeling Roles and Permissions. In some cases, however, they may not be enough.
Custom roles are useful when:
- Users of the application are able to create arbitrary sets of roles with different permissions that govern the users' access to objects.
- It is not known beforehand (at the time of Authorization Model creation) what the application roles are.
- The team responsible for building the authorization model is different from the teams responsible for defining roles and access to the application.
Before you start
Before you start this guide, make sure you're familiar with some OpenFGA Concepts and know how to develop the things listed below.
Initial Model
To start, let's say there is an application with a type called asset-category
. Users can have view and/or edit access to assets in that category. Any user who can edit can also view.
asset-category
. Users can have view and/or edit access to assets in that category. Any user who can edit can also view.We'll start with the following authorization model showing a system with an asset-category
type. This type allows users to have view and edit access to it.
- DSL
- JSON
model
schema 1.1
type user
type asset-category
relations
define viewer: [user] or editor
define editor: [user]
{
"schema_version": "1.1",
"type_definitions": [
{
"type": "user"
},
{
"type": "asset-category",
"relations": {
"viewer": {
"union": {
"child": [
{
"this": {}
},
{
"computedUserset": {
"relation": "editor"
}
}
]
}
},
"editor": {
"this": {}
}
},
"metadata": {
"relations": {
"editor": {
"directly_related_user_types": [
{
"type": "user"
}
]
},
"viewer": {
"directly_related_user_types": [
{
"type": "user"
}
]
}
}
}
}
]
}
In addition, you'll need to know the following:
Modeling Roles and Permissions
You need to know how to add users to groups and grant groups access to resources. Learn more →
Modeling Object-to-Object Relationships
You need to know how to create relationships between objects and how that might affect a user's relationships to those objects. Learn more →
Concepts & Configuration Language
Step By Step
Starting with the authorization model mentioned above, we want to enable users to create their own custom roles, and tie permissions to those roles to our two users and to the permissions on the logo asset category.
For this guide, we'll model a scenario where a certain organization using our app has created an asset-category
called "logos", and another called "text content".
The company administrator would like to create:
- a media-manager role that allows users to edit assets in the logos asset category
- a media-viewer role that allows users to view all assets in the logos asset category
- a blog-editor role that allows users to edit all assets in the text content asset category
- a blog-viewer role that allows users to view all assets in the text content asset category
Imagine these are what the permissions the roles in one organization using our service are like:
Finally, the administrator wants to assign Anne the media-manager role and Beth the media-viewer role.
At the end, we'll verify our model by ensuring the following access check requests return the expected result.
In order to do this, we need to:
- Update the Authorization Model to add a Role Type
- Use Relationship Tuples to tie the Users to the Roles
- Use Relationship Tuples to associate Permissions with the Roles
- Verify that the Authorization Model works
01. Update The Authorization Model To Add A Role Type
Because our roles are going to be dynamic and might change frequently, we represent them in a new type instead of as relations on that same type. We'll create new type called role
, where users can be related as assignee to it.
The authorization model becomes this:
- DSL
- JSON
model
schema 1.1
type user
type asset-category
relations
define viewer: [user,role#assignee] or editor
define editor: [user,role#assignee]
type role
relations
define assignee: [user]
{
"schema_version": "1.1",
"type_definitions": [
{
"type": "user"
},
{
"type": "asset-category",
"relations": {
"viewer": {
"union": {
"child": [
{
"this": {}
},
{
"computedUserset": {
"relation": "editor"
}
}
]
}
},
"editor": {
"this": {}
}
},
"metadata": {
"relations": {
"viewer": {
"directly_related_user_types": [
{
"type": "user"
},
{
"type": "role",
"relation": "assignee"
}
]
},
"editor": {
"directly_related_user_types": [
{
"type": "user"
},
{
"type": "role",
"relation": "assignee"
}
]
}
}
}
},
{
"type": "role",
"relations": {
"assignee": {
"this": {}
}
},
"metadata": {
"relations": {
"assignee": {
"directly_related_user_types": [
{
"type": "user"
}
]
}
}
}
}
]
}
With this change we can add relationship tuples indicating that a certain user is assigned
a certain role
.
02.Use Relationship Tuples To Tie The Users To The Roles
Once we've added the role
type, we can assign roles to Anne and Beth. Anne is assigned the "media-manager" role and Beth is assigned the "media-viewer" role. We can do that by adding relationship tuples as follows:
- Node.js
- Go
- .NET
- Python
- curl
- Pseudocode
Initialize the SDK
// ApiTokenIssuer, ApiAudience, ClientId and ClientSecret are optional.
// import the SDK
const { OpenFgaApi } = require('@openfga/sdk');
// Initialize the SDK with no auth - see "How to setup SDK client" for more options
const fgaClient = new OpenFgaApi({
apiScheme: process.env.FGA_API_SCHEME, // Either "http" or "https", defaults to "https"
apiHost: process.env.FGA_API_HOST, // required, define without the scheme (e.g. api.openfga.example instead of https://api.openfga.example)
storeId: process.env.FGA_STORE_ID, // Either "http" or "https", defaults to "https"
});
await fgaClient.write({
writes: {
tuple_keys: [
// Anne is assigned the media-manager role
{ user: 'user:anne', relation: 'assignee', object: 'role:media-manager'},
// Beth is assigned the media-viewer role
{ user: 'user:beth', relation: 'assignee', object: 'role:media-viewer'}
]
},
authorization_model_id: "1uHxCSuTP0VKPYSnkq1pbb1jeZw"
});
Initialize the SDK
// ApiTokenIssuer, ApiAudience, ClientId and ClientSecret are optional.
import (
fgaSdk "github.com/openfga/go-sdk"
"os"
)
func main() {
// Initialize the SDK with no auth - see "How to setup SDK client" for more options
configuration, err := fgaSdk.NewConfiguration(fgaSdk.UserConfiguration{
ApiScheme: os.Getenv("FGA_SCHEME"), // Either "http" or "https", defaults to "https"
ApiHost: os.Getenv("FGA_API_HOST"), // required, define without the scheme (e.g. api.openfga.example instead of https://api.openfga.example)
StoreId: os.Getenv("FGA_STORE_ID"), // optional, not needed for `CreateStore` and `ListStores`, required before calling for all other methods
})
if err != nil {
// .. Handle error
}
fgaClient := fgaSdk.NewAPIClient(configuration)
}
body := fgaSdk.WriteRequest{
Writes: &fgaSdk.TupleKeys{
TupleKeys: []fgaSdk.TupleKey {
{
// Anne is assigned the media-manager role
User: fgaSdk.PtrString("user:anne"),
Relation: fgaSdk.PtrString("assignee"),
Object: fgaSdk.PtrString("role:media-manager"),
},
{
// Beth is assigned the media-viewer role
User: fgaSdk.PtrString("user:beth"),
Relation: fgaSdk.PtrString("assignee"),
Object: fgaSdk.PtrString("role:media-viewer"),
},
},
},
AuthorizationModelId: fgaSdk.PtrString("1uHxCSuTP0VKPYSnkq1pbb1jeZw")}
_, response, err := fgaClient.OpenFgaApi.Write(context.Background()).Body(body).Execute()
if err != nil {
// .. Handle error
}
Initialize the SDK
// ApiTokenIssuer, ApiAudience, ClientId and ClientSecret are optional.
// import the SDK
using OpenFga.Sdk.Api;
using OpenFga.Sdk.Configuration;
using Environment = System.Environment;
namespace ExampleApp;
class MyProgram {
static async Task Main() {
// Initialize the SDK with no auth - see "How to setup SDK client" for more options
var configuration = new Configuration() {
ApiScheme = Environment.GetEnvironmentVariable("FGA_API_SCHEME"), // Either "http" or "https", defaults to "https"
ApiHost = Environment.GetEnvironmentVariable("FGA_API_HOST"), // required, define without the scheme (e.g. api.openfga.example instead of https://api.openfga.example)
StoreId = Environment.GetEnvironmentVariable("FGA_STORE_ID"), // optional, not needed for `CreateStore` and `ListStores`, required before calling for all other methods
};
var fgaClient = new OpenFgaApi(configuration);
}
}
await fgaClient.Write(new WriteRequest{
Writes = new TupleKeys(new List<TupleKey>() {
// Anne is assigned the media-manager role
new() { User = "user:anne", Relation = "assignee", Object = "role:media-manager" },
// Beth is assigned the media-viewer role
new() { User = "user:beth", Relation = "assignee", Object = "role:media-viewer" }
}),
AuthorizationModelId = "1uHxCSuTP0VKPYSnkq1pbb1jeZw"
});
Initialize the SDK
# ApiTokenIssuer, ApiAudience, ClientId and ClientSecret are optional.
import os
import json
import openfga_sdk
from openfga_sdk.api import open_fga_api
configuration = openfga_sdk.Configuration(
api_scheme = os.environ.get('FGA_API_SCHEME'), # Either "http" or "https", defaults to "https"
api_host = os.environ.get('FGA_API_HOST'), # required, define without the scheme (e.g. api.openfga.example instead of https://api.openfga.example)
store_id = os.environ.get('FGA_STORE_ID') # optional, not needed for `CreateStore` and `ListStores`, required before calling for all other methods
)
# Create an instance of the API class
fga_client_instance = open_fga_api.OpenFgaApi(openfga_sdk.ApiClient(configuration))
# from openfga_sdk.models.tuple_key import TupleKey
# from openfga_sdk.models.tuple_keys import TupleKeys
# from openfga_sdk.models.write_request import WriteRequest
async def write():
body = WriteRequest(
writes=TupleKeys(
tuple_keys=[
TupleKey(
# Anne is assigned the media-manager role
user="user:anne",
relation="assignee",
object="role:media-manager",
),
TupleKey(
# Beth is assigned the media-viewer role
user="user:beth",
relation="assignee",
object="role:media-viewer",
),
],
),
authorization_model_id="1uHxCSuTP0VKPYSnkq1pbb1jeZw",
)
await fga_client_instance.write(body)
Get the Bearer Token and set up the FGA_API_URL environment variable
Set FGA_API_URL according to the service you are using
curl -X POST $FGA_API_URL/stores/$FGA_STORE_ID/write \
-H "Authorization: Bearer $FGA_BEARER_TOKEN" \ # Not needed if service does not require authorization
-H "content-type: application/json" \
-d '{"writes": { "tuple_keys" : [{"user":"user:anne","relation":"assignee","object":"role:media-manager"},{"user":"user:beth","relation":"assignee","object":"role:media-viewer"}] }, "authorization_model_id": "1uHxCSuTP0VKPYSnkq1pbb1jeZw"}'
write([
// Anne is assigned the media-manager role
{
"user":"user:anne",
"relation":"assignee",
"object":"role:media-manager"
},
// Beth is assigned the media-viewer role
{
"user":"user:beth",
"relation":"assignee",
"object":"role:media-viewer"
}
], authorization_model_id="1uHxCSuTP0VKPYSnkq1pbb1jeZw")
We can verify they are members of said roles by issuing the following check requests:
- Node.js
- Go
- .NET
- Python
- curl
- Pseudocode
Initialize the SDK
// ApiTokenIssuer, ApiAudience, ClientId and ClientSecret are optional.
// import the SDK
const { OpenFgaApi } = require('@openfga/sdk');
// Initialize the SDK with no auth - see "How to setup SDK client" for more options
const fgaClient = new OpenFgaApi({
apiScheme: process.env.FGA_API_SCHEME, // Either "http" or "https", defaults to "https"
apiHost: process.env.FGA_API_HOST, // required, define without the scheme (e.g. api.openfga.example instead of https://api.openfga.example)
storeId: process.env.FGA_STORE_ID, // Either "http" or "https", defaults to "https"
});
// Run a check
const { allowed } = await fgaClient.check({
authorization_model_id: '1uHxCSuTP0VKPYSnkq1pbb1jeZw',
tuple_key: {
user: 'user:anne',
relation: 'assignee',
object: 'role:media-manager',
},
});
// allowed = true
Initialize the SDK
// ApiTokenIssuer, ApiAudience, ClientId and ClientSecret are optional.
import (
fgaSdk "github.com/openfga/go-sdk"
"os"
)
func main() {
// Initialize the SDK with no auth - see "How to setup SDK client" for more options
configuration, err := fgaSdk.NewConfiguration(fgaSdk.UserConfiguration{
ApiScheme: os.Getenv("FGA_SCHEME"), // Either "http" or "https", defaults to "https"
ApiHost: os.Getenv("FGA_API_HOST"), // required, define without the scheme (e.g. api.openfga.example instead of https://api.openfga.example)
StoreId: os.Getenv("FGA_STORE_ID"), // optional, not needed for `CreateStore` and `ListStores`, required before calling for all other methods
})
if err != nil {
// .. Handle error
}
fgaClient := fgaSdk.NewAPIClient(configuration)
}
body := fgaSdk.CheckRequest{
AuthorizationModelId: fgaSdk.PtrString("1uHxCSuTP0VKPYSnkq1pbb1jeZw"),
TupleKey: fgaSdk.TupleKey{
User: "user:anne",
Relation: "assignee",
Object: "role:media-manager",
},
}
data, response, err := fgaClient.OpenFgaApi.Check(context.Background()).Body(body).Execute()
// data = { allowed: true }
Initialize the SDK
// ApiTokenIssuer, ApiAudience, ClientId and ClientSecret are optional.
// import the SDK
using OpenFga.Sdk.Api;
using OpenFga.Sdk.Configuration;
using Environment = System.Environment;
namespace ExampleApp;
class MyProgram {
static async Task Main() {
// Initialize the SDK with no auth - see "How to setup SDK client" for more options
var configuration = new Configuration() {
ApiScheme = Environment.GetEnvironmentVariable("FGA_API_SCHEME"), // Either "http" or "https", defaults to "https"
ApiHost = Environment.GetEnvironmentVariable("FGA_API_HOST"), // required, define without the scheme (e.g. api.openfga.example instead of https://api.openfga.example)
StoreId = Environment.GetEnvironmentVariable("FGA_STORE_ID"), // optional, not needed for `CreateStore` and `ListStores`, required before calling for all other methods
};
var fgaClient = new OpenFgaApi(configuration);
}
}
// Run a check
var response = await fgaClient.Check(new CheckRequest
{
TupleKey = new TupleKey() {
User = "user:anne",
Relation = "assignee",
Object = "role:media-manager"
}, AuthorizationModelId = "1uHxCSuTP0VKPYSnkq1pbb1jeZw"});
// response.Allowed = true
Initialize the SDK
# ApiTokenIssuer, ApiAudience, ClientId and ClientSecret are optional.
import os
import json
import openfga_sdk
from openfga_sdk.api import open_fga_api
configuration = openfga_sdk.Configuration(
api_scheme = os.environ.get('FGA_API_SCHEME'), # Either "http" or "https", defaults to "https"
api_host = os.environ.get('FGA_API_HOST'), # required, define without the scheme (e.g. api.openfga.example instead of https://api.openfga.example)
store_id = os.environ.get('FGA_STORE_ID') # optional, not needed for `CreateStore` and `ListStores`, required before calling for all other methods
)
# Create an instance of the API class
fga_client_instance = open_fga_api.OpenFgaApi(openfga_sdk.ApiClient(configuration))
# from openfga_sdk.models.check_request import CheckRequest
# from openfga_sdk.models.tuple_key import TupleKey
# from openfga_sdk.models.contextual_tuple_keys import ContextualTupleKeys
# Run a check
async def check():
body = CheckRequest(
tuple_key=TupleKey(
user="user:anne",
relation="assignee",
object="role:media-manager",
),
authorization_model_id="1uHxCSuTP0VKPYSnkq1pbb1jeZw",
)
response = await fga_client_instance.check(body)
# response.allowed = true
Get the Bearer Token and set up the FGA_API_URL environment variable
Set FGA_API_URL according to the service you are using
curl -X POST $FGA_API_URL/stores/$FGA_STORE_ID/check \
-H "Authorization: Bearer $FGA_BEARER_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":"assignee","object":"role:media-manager"}}'
# Response: {"allowed":true}
check(
user = "user:anne", // check if the user `user:anne`
relation = "assignee", // has an `assignee` relation
object = "role:media-manager", // with the object `role:media-manager`
authorization_id = "1uHxCSuTP0VKPYSnkq1pbb1jeZw"
);
Reply: true
03. Use Relationship Tuples To Associate Permissions With The Roles
With our users and roles set up, we still need to tie members of a certain role to it's corresponding permission(s).
- Node.js
- Go
- .NET
- Python
- curl
- Pseudocode
Initialize the SDK
// ApiTokenIssuer, ApiAudience, ClientId and ClientSecret are optional.
// import the SDK
const { OpenFgaApi } = require('@openfga/sdk');
// Initialize the SDK with no auth - see "How to setup SDK client" for more options
const fgaClient = new OpenFgaApi({
apiScheme: process.env.FGA_API_SCHEME, // Either "http" or "https", defaults to "https"
apiHost: process.env.FGA_API_HOST, // required, define without the scheme (e.g. api.openfga.example instead of https://api.openfga.example)
storeId: process.env.FGA_STORE_ID, // Either "http" or "https", defaults to "https"
});
await fgaClient.write({
writes: {
tuple_keys: [
// Users assigned the media-manager role can edit in the Logos assets category
{ user: 'role:media-manager#assignee', relation: 'editor', object: 'asset-category:logos'},
// Users assigned the media-viewer role can view from the Logos assets category
{ user: 'role:media-viewer#assignee', relation: 'viewer', object: 'asset-category:logos'}
]
},
authorization_model_id: "1uHxCSuTP0VKPYSnkq1pbb1jeZw"
});
Initialize the SDK
// ApiTokenIssuer, ApiAudience, ClientId and ClientSecret are optional.
import (
fgaSdk "github.com/openfga/go-sdk"
"os"
)
func main() {
// Initialize the SDK with no auth - see "How to setup SDK client" for more options
configuration, err := fgaSdk.NewConfiguration(fgaSdk.UserConfiguration{
ApiScheme: os.Getenv("FGA_SCHEME"), // Either "http" or "https", defaults to "https"
ApiHost: os.Getenv("FGA_API_HOST"), // required, define without the scheme (e.g. api.openfga.example instead of https://api.openfga.example)
StoreId: os.Getenv("FGA_STORE_ID"), // optional, not needed for `CreateStore` and `ListStores`, required before calling for all other methods
})
if err != nil {
// .. Handle error
}
fgaClient := fgaSdk.NewAPIClient(configuration)
}
body := fgaSdk.WriteRequest{
Writes: &fgaSdk.TupleKeys{
TupleKeys: []fgaSdk.TupleKey {
{
// Users assigned the media-manager role can edit in the Logos assets category
User: fgaSdk.PtrString("role:media-manager#assignee"),
Relation: fgaSdk.PtrString("editor"),
Object: fgaSdk.PtrString("asset-category:logos"),
},
{
// Users assigned the media-viewer role can view from the Logos assets category
User: fgaSdk.PtrString("role:media-viewer#assignee"),
Relation: fgaSdk.PtrString("viewer"),
Object: fgaSdk.PtrString("asset-category:logos"),
},
},
},
AuthorizationModelId: fgaSdk.PtrString("1uHxCSuTP0VKPYSnkq1pbb1jeZw")}
_, response, err := fgaClient.OpenFgaApi.Write(context.Background()).Body(body).Execute()
if err != nil {
// .. Handle error
}
Initialize the SDK
// ApiTokenIssuer, ApiAudience, ClientId and ClientSecret are optional.
// import the SDK
using OpenFga.Sdk.Api;
using OpenFga.Sdk.Configuration;
using Environment = System.Environment;
namespace ExampleApp;
class MyProgram {
static async Task Main() {
// Initialize the SDK with no auth - see "How to setup SDK client" for more options
var configuration = new Configuration() {
ApiScheme = Environment.GetEnvironmentVariable("FGA_API_SCHEME"), // Either "http" or "https", defaults to "https"
ApiHost = Environment.GetEnvironmentVariable("FGA_API_HOST"), // required, define without the scheme (e.g. api.openfga.example instead of https://api.openfga.example)
StoreId = Environment.GetEnvironmentVariable("FGA_STORE_ID"), // optional, not needed for `CreateStore` and `ListStores`, required before calling for all other methods
};
var fgaClient = new OpenFgaApi(configuration);
}
}
await fgaClient.Write(new WriteRequest{
Writes = new TupleKeys(new List<TupleKey>() {
// Users assigned the media-manager role can edit in the Logos assets category
new() { User = "role:media-manager#assignee", Relation = "editor", Object = "asset-category:logos" },
// Users assigned the media-viewer role can view from the Logos assets category
new() { User = "role:media-viewer#assignee", Relation = "viewer", Object = "asset-category:logos" }
}),
AuthorizationModelId = "1uHxCSuTP0VKPYSnkq1pbb1jeZw"
});
Initialize the SDK
# ApiTokenIssuer, ApiAudience, ClientId and ClientSecret are optional.
import os
import json
import openfga_sdk
from openfga_sdk.api import open_fga_api
configuration = openfga_sdk.Configuration(
api_scheme = os.environ.get('FGA_API_SCHEME'), # Either "http" or "https", defaults to "https"
api_host = os.environ.get('FGA_API_HOST'), # required, define without the scheme (e.g. api.openfga.example instead of https://api.openfga.example)
store_id = os.environ.get('FGA_STORE_ID') # optional, not needed for `CreateStore` and `ListStores`, required before calling for all other methods
)
# Create an instance of the API class
fga_client_instance = open_fga_api.OpenFgaApi(openfga_sdk.ApiClient(configuration))
# from openfga_sdk.models.tuple_key import TupleKey
# from openfga_sdk.models.tuple_keys import TupleKeys
# from openfga_sdk.models.write_request import WriteRequest
async def write():
body = WriteRequest(
writes=TupleKeys(
tuple_keys=[
TupleKey(
# Users assigned the media-manager role can edit in the Logos assets category
user="role:media-manager#assignee",
relation="editor",
object="asset-category:logos",
),
TupleKey(
# Users assigned the media-viewer role can view from the Logos assets category
user="role:media-viewer#assignee",
relation="viewer",
object="asset-category:logos",
),
],
),
authorization_model_id="1uHxCSuTP0VKPYSnkq1pbb1jeZw",
)
await fga_client_instance.write(body)
Get the Bearer Token and set up the FGA_API_URL environment variable
Set FGA_API_URL according to the service you are using
curl -X POST $FGA_API_URL/stores/$FGA_STORE_ID/write \
-H "Authorization: Bearer $FGA_BEARER_TOKEN" \ # Not needed if service does not require authorization
-H "content-type: application/json" \
-d '{"writes": { "tuple_keys" : [{"user":"role:media-manager#assignee","relation":"editor","object":"asset-category:logos"},{"user":"role:media-viewer#assignee","relation":"viewer","object":"asset-category:logos"}] }, "authorization_model_id": "1uHxCSuTP0VKPYSnkq1pbb1jeZw"}'
write([
// Users assigned the media-manager role can edit in the Logos assets category
{
"user":"role:media-manager#assignee",
"relation":"editor",
"object":"asset-category:logos"
},
// Users assigned the media-viewer role can view from the Logos assets category
{
"user":"role:media-viewer#assignee",
"relation":"viewer",
"object":"asset-category:logos"
}
], authorization_model_id="1uHxCSuTP0VKPYSnkq1pbb1jeZw")
04. Verify That The Authorization Model Works
To ensure our model works, it needs to match our expectations:
- Node.js
- Go
- .NET
- Python
- curl
- Pseudocode
Initialize the SDK
// ApiTokenIssuer, ApiAudience, ClientId and ClientSecret are optional.
// import the SDK
const { OpenFgaApi } = require('@openfga/sdk');
// Initialize the SDK with no auth - see "How to setup SDK client" for more options
const fgaClient = new OpenFgaApi({
apiScheme: process.env.FGA_API_SCHEME, // Either "http" or "https", defaults to "https"
apiHost: process.env.FGA_API_HOST, // required, define without the scheme (e.g. api.openfga.example instead of https://api.openfga.example)
storeId: process.env.FGA_STORE_ID, // Either "http" or "https", defaults to "https"
});
// Run a check
const { allowed } = await fgaClient.check({
authorization_model_id: '1uHxCSuTP0VKPYSnkq1pbb1jeZw',
tuple_key: {
user: 'user:anne',
relation: 'editor',
object: 'asset-category:logos',
},
});
// allowed = true
Initialize the SDK
// ApiTokenIssuer, ApiAudience, ClientId and ClientSecret are optional.
import (
fgaSdk "github.com/openfga/go-sdk"
"os"
)
func main() {
// Initialize the SDK with no auth - see "How to setup SDK client" for more options
configuration, err := fgaSdk.NewConfiguration(fgaSdk.UserConfiguration{
ApiScheme: os.Getenv("FGA_SCHEME"), // Either "http" or "https", defaults to "https"
ApiHost: os.Getenv("FGA_API_HOST"), // required, define without the scheme (e.g. api.openfga.example instead of https://api.openfga.example)
StoreId: os.Getenv("FGA_STORE_ID"), // optional, not needed for `CreateStore` and `ListStores`, required before calling for all other methods
})
if err != nil {
// .. Handle error
}
fgaClient := fgaSdk.NewAPIClient(configuration)
}
body := fgaSdk.CheckRequest{
AuthorizationModelId: fgaSdk.PtrString("1uHxCSuTP0VKPYSnkq1pbb1jeZw"),
TupleKey: fgaSdk.TupleKey{
User: "user:anne",
Relation: "editor",
Object: "asset-category:logos",
},
}
data, response, err := fgaClient.OpenFgaApi.Check(context.Background()).Body(body).Execute()
// data = { allowed: true }
Initialize the SDK
// ApiTokenIssuer, ApiAudience, ClientId and ClientSecret are optional.
// import the SDK
using OpenFga.Sdk.Api;
using OpenFga.Sdk.Configuration;
using Environment = System.Environment;
namespace ExampleApp;
class MyProgram {
static async Task Main() {
// Initialize the SDK with no auth - see "How to setup SDK client" for more options
var configuration = new Configuration() {
ApiScheme = Environment.GetEnvironmentVariable("FGA_API_SCHEME"), // Either "http" or "https", defaults to "https"
ApiHost = Environment.GetEnvironmentVariable("FGA_API_HOST"), // required, define without the scheme (e.g. api.openfga.example instead of https://api.openfga.example)
StoreId = Environment.GetEnvironmentVariable("FGA_STORE_ID"), // optional, not needed for `CreateStore` and `ListStores`, required before calling for all other methods
};
var fgaClient = new OpenFgaApi(configuration);
}
}
// Run a check
var response = await fgaClient.Check(new CheckRequest
{
TupleKey = new TupleKey() {
User = "user:anne",
Relation = "editor",
Object = "asset-category:logos"
}, AuthorizationModelId = "1uHxCSuTP0VKPYSnkq1pbb1jeZw"});
// response.Allowed = true
Initialize the SDK
# ApiTokenIssuer, ApiAudience, ClientId and ClientSecret are optional.
import os
import json
import openfga_sdk
from openfga_sdk.api import open_fga_api
configuration = openfga_sdk.Configuration(
api_scheme = os.environ.get('FGA_API_SCHEME'), # Either "http" or "https", defaults to "https"
api_host = os.environ.get('FGA_API_HOST'), # required, define without the scheme (e.g. api.openfga.example instead of https://api.openfga.example)
store_id = os.environ.get('FGA_STORE_ID') # optional, not needed for `CreateStore` and `ListStores`, required before calling for all other methods
)
# Create an instance of the API class
fga_client_instance = open_fga_api.OpenFgaApi(openfga_sdk.ApiClient(configuration))
# from openfga_sdk.models.check_request import CheckRequest
# from openfga_sdk.models.tuple_key import TupleKey
# from openfga_sdk.models.contextual_tuple_keys import ContextualTupleKeys
# Run a check
async def check():
body = CheckRequest(
tuple_key=TupleKey(
user="user:anne",
relation="editor",
object="asset-category:logos",
),
authorization_model_id="1uHxCSuTP0VKPYSnkq1pbb1jeZw",
)
response = await fga_client_instance.check(body)
# response.allowed = true
Get the Bearer Token and set up the FGA_API_URL environment variable
Set FGA_API_URL according to the service you are using
curl -X POST $FGA_API_URL/stores/$FGA_STORE_ID/check \
-H "Authorization: Bearer $FGA_BEARER_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":"editor","object":"asset-category:logos"}}'
# Response: {"allowed":true}
check(
user = "user:anne", // check if the user `user:anne`
relation = "editor", // has an `editor` relation
object = "asset-category:logos", // with the object `asset-category:logos`
authorization_id = "1uHxCSuTP0VKPYSnkq1pbb1jeZw"
);
Reply: true
The checks come back as we expect, so our model is working correctly.