Perform a Check
This section will illustrate how to perform a check request to determine whether a user has a certain relationship with an object.
Before you start
- Node.js
- Go
- .NET
- Python
- Java
- CLI
- curl
- Deploy an instance of the OpenFGA server, and have ready the values for your setup: FGA_STORE_ID, FGA_API_URL and, if needed, FGA_API_TOKEN.
- You have installed the SDK.
- You have configured the authorization model and updated the relationship tuples.
- You have loaded
FGA_STORE_ID
andFGA_API_URL
as environment variables.
- Deploy an instance of the OpenFGA server, and have ready the values for your setup: FGA_STORE_ID, FGA_API_URL and, if needed, FGA_API_TOKEN.
- You have installed the SDK.
- You have configured the authorization model and updated the relationship tuples.
- You have loaded
FGA_STORE_ID
andFGA_API_URL
as environment variables.
- Deploy an instance of the OpenFGA server, and have ready the values for your setup: FGA_STORE_ID, FGA_API_URL and, if needed, FGA_API_TOKEN.
- You have installed the SDK.
- You have configured the authorization model and updated the relationship tuples.
- You have loaded
FGA_STORE_ID
andFGA_API_URL
as environment variables.
- Deploy an instance of the OpenFGA server, and have ready the values for your setup: FGA_STORE_ID, FGA_API_URL and, if needed, FGA_API_TOKEN.
- You have installed the SDK.
- You have configured the authorization model and updated the relationship tuples.
- You have loaded
FGA_STORE_ID
andFGA_API_URL
as environment variables.
- Deploy an instance of the OpenFGA server, and have ready the values for your setup: FGA_STORE_ID, FGA_API_URL and, if needed, FGA_API_TOKEN.
- You have installed the SDK.
- You have configured the authorization model and updated the relationship tuples.
- You have loaded
FGA_STORE_ID
andFGA_API_URL
as environment variables.
- Deploy an instance of the OpenFGA server, and have ready the values for your setup: FGA_STORE_ID, FGA_API_URL and, if needed, FGA_API_TOKEN.
- You have configured the authorization model.
- You have loaded
FGA_STORE_ID
andFGA_API_URL
as environment variables.
- Deploy an instance of the OpenFGA server, and have ready the values for your setup: FGA_STORE_ID, FGA_API_URL and, if needed, FGA_API_TOKEN.
- You have configured the authorization model and updated the relationship tuples.
- You have loaded
FGA_STORE_ID
andFGA_API_URL
as environment variables.
Step by step
Assume that you want to check whether user anne
has relationship reader
with object document:Z
01. Configure the OpenFGA API client
Before calling the check API, you will need to configure the API client.
- Node.js
- Go
- .NET
- Python
- Java
- CLI
- curl
// import the SDK
const { OpenFgaClient } = require('@openfga/sdk');
// Initialize the SDK with no auth - see "How to setup SDK client" for more options
const fgaClient = new OpenFgaClient({
apiUrl: process.env.FGA_API_URL, // required, e.g. https://api.fga.example
storeId: process.env.FGA_STORE_ID,
authorizationModelId: process.env.FGA_MODEL_ID, // Optional, can be overridden per request
});
import (
"os"
. "github.com/openfga/go-sdk"
. "github.com/openfga/go-sdk/client"
)
func main() {
// Initialize the SDK with no auth - see "How to setup SDK client" for more options
fgaClient, err := NewSdkClient(&ClientConfiguration{
ApiUrl: os.Getenv("FGA_API_URL"), // required, e.g. https://api.fga.example
StoreId: os.Getenv("FGA_STORE_ID"), // optional, not needed for `CreateStore` and `ListStores`, required before calling for all other methods
AuthorizationModelId: os.Getenv("FGA_MODEL_ID"), // Optional, can be overridden per request
})
if err != nil {
// .. Handle error
}
}
// import the SDK
using OpenFga.Sdk.Client;
using OpenFga.Sdk.Client.Model;
using OpenFga.Sdk.Model;
using Environment = System.Environment;
namespace Example;
class Example {
public static async Task Main() {
// Initialize the SDK with no auth - see "How to setup SDK client" for more options
var configuration = new ClientConfiguration() {
ApiUrl = Environment.GetEnvironmentVariable("FGA_API_URL"), ?? "http://localhost:8080", // required, e.g. https://api.fga.example
StoreId = Environment.GetEnvironmentVariable("FGA_STORE_ID"), // optional, not needed for `CreateStore` and `ListStores`, required before calling for all other methods
AuthorizationModelId = Environment.GetEnvironmentVariable("FGA_MODEL_ID"), // Optional, can be overridden per request
};
var fgaClient = new OpenFgaClient(configuration);
}
}
import asyncio
import os
import json
from openfga_sdk.client import ClientConfiguration, OpenFgaClient
async def main():
configuration = ClientConfiguration(
api_url = os.environ.get('FGA_API_URL'), # required, e.g. https://api.fga.example
store_id = os.environ.get('FGA_STORE_ID'), # optional, not needed for `CreateStore` and `ListStores`, required before calling for all other methods
authorization_model_id = os.environ.get('FGA_MODEL_ID'), # Optional, can be overridden per request
)
# Enter a context with an instance of the OpenFgaClient
async with OpenFgaClient(configuration) as fga_client:
api_response = await fga_client.read_authorization_models()
await fga_client.close()
asyncio.run(main())
import dev.openfga.sdk.api.client.OpenFgaClient;
import dev.openfga.sdk.api.configuration.ClientConfiguration;
public class Example {
public static void main(String[] args) throws Exception {
var config = new ClientConfiguration()
.apiUrl(System.getenv("FGA_API_URL")) // If not specified, will default to "https://localhost:8080"
.storeId(System.getenv("FGA_STORE_ID")) // Not required when calling createStore() or listStores()
.authorizationModelId(System.getenv("FGA_AUTHORIZATION_MODEL_ID")); // Optional, can be overridden per request
var fgaClient = new OpenFgaClient(config);
}
}
Set FGA_API_URL according to the service you are using (e.g. https://api.fga.example)
To obtain the access token:
Set FGA_API_URL according to the service you are using (e.g. https://api.fga.example)
02. Calling Check API
To check whether user user:anne
has relationship can_view
with object document:Z
- Node.js
- Go
- .NET
- Python
- Java
- CLI
- curl
// Run a check
const { allowed } = await fgaClient.check({
user: 'user:anne',
relation: 'can_view',
object: 'document:Z',
}, {
authorizationModelId: '01HVMMBCMGZNT3SED4Z17ECXCA',
});
// allowed = true
options := ClientCheckOptions{
AuthorizationModelId: PtrString("01HVMMBCMGZNT3SED4Z17ECXCA"),
}
body := ClientCheckRequest{
User: "user:anne",
Relation: "can_view",
Object: "document:Z",
}
data, err := fgaClient.Check(context.Background()).
Body(body).
Options(options).
Execute()
// data = { allowed: true }
var options = new ClientCheckOptions {
AuthorizationModelId = "01HVMMBCMGZNT3SED4Z17ECXCA",
};
var body = new ClientCheckRequest {
User = "user:anne",
Relation = "can_view",
Object = "document:Z",
};
var response = await fgaClient.Check(body, options);
// response.Allowed = true
options = {
authorization_model_id="01HVMMBCMGZNT3SED4Z17ECXCA"
}
body = ClientCheckRequest(
user="user:anne",
relation="can_view",
object="document:Z",
)
response = await fga_client.check(body, options)
# response.allowed = true
var options = new ClientCheckOptions()
.authorizationModelId("01HVMMBCMGZNT3SED4Z17ECXCA");
var body = new ClientCheckRequest()
.user("user:anne")
.relation("can_view")
._object("document:Z");
var response = fgaClient.check(body, options).get();
// response.getAllowed() = true
fga query check --store-id=$FGA_STORE_ID --model-id=01HVMMBCMGZNT3SED4Z17ECXCA user:anne can_view document:Z
# Response: {"allowed":true}
curl -X POST $FGA_API_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": "01HVMMBCMGZNT3SED4Z17ECXCA", "tuple_key":{"user":"user:anne","relation":"can_view","object":"document:Z"}}'
# Response: {"allowed":true}
The result's allowed
field will return true
if the relationship exists and false
if the relationship does not exist.
03. Calling Batch Check API
If you want to check multiple user-object-relationship combinations in a single request, you can use the Batch Check API endpoint. Batching authorization checks together in a single request significantly reduces overall network latency.
The BatchCheck endpoint is currently only supported by the JS SDK (>=v0.8.0 and the Python SDK (>=v0.9.0). Support in the other SDKs is being worked on.
In the SDKs that don't support the server-side BatchCheck
, the BatchCheck
method performs client-side batch checks by making multiple check requests with limited parallelization, in SDK versions that do support the server-side BatchCheck
, the existing method has been renamed to ClientBatchCheck
.
Refer to the README for each SDK for more information. Refer to the release notes of the relevant SDK version for more information on how to migrate from client-side to the server-side BatchCheck
.
The BatchCheck endpoint requires a correlation_id
parameter for each check. The correlation_id
is used to "correlate" the check responses with the checks sent in the request, since tuple_keys
and contextual_tuples
are not returned in the response on purpose to reduce data transfer to improve network latency. A correlation_id
can be composed of any string of alphanumeric characters or dashes between 1-36 characters in length.
This means you can use:
- simple iterating integers
1,2,3,etc
- UUID
e5fe049b-f252-40b3-b795-fe485d588279
- ULID
01JBMD9YG0XH3B4GVA8A9D2PSN
- or some other unique string
Each correlation_id
within a request must be unique.
If you are using one of our SDKs:
- the
correlation_id
is inserted for you by default and automatically correlates theallowed
response with the propertuple_key
- if you pass in more checks than the server supports in a single call (default
50
, configurable on the server), the SDK will automatically split and batch theBatchCheck
requests for you, how it does this can be configured using themaxBatchSize
andmaxParallelRequests
options in the SDK.
To check whether user user:anne
has multiple relationships writer
and reader
with object document:Z
- Node.js
- Go
- .NET
- Python
- Java
- curl
- Pseudocode
// Requires >=v0.8.0 for the server side BatchCheck, earlier versions support a client-side BatchCheck with a slightly different interface
const body = {
checks: [
{
user: 'user:anne',
relation: 'writer',
object: 'document:Z',
correlationId: '886224f6-04ae-4b13-bd8e-559c7d3754e1'
},{
user: 'user:anne',
relation: 'reader',
object: 'document:Z',
correlationId: 'da452239-a4e0-4791-b5d1-fb3d451ac078'
}
],
}
const options = {
authorization_model_id: '01HVMMBCMGZNT3SED4Z17ECXCA',
maxBatchSize: 50, // optional, default is 50, can be used to limit the number of checks in a single server request
maxParallelRequests: 10, // optional, default is 10, can be used to limit the parallelization of the BatchCheck chunks
};
const { result } = await fgaClient.batchCheck(body, options);
/*
{
"results": [
{
"correlationId": '886224f6-04ae-4b13-bd8e-559c7d3754e1',
"allowed": false,
"request": {
"user": 'user:anne',
"relation": 'writer',
"object": 'document:Z'}
}, {
"correlationId": 'da452239-a4e0-4791-b5d1-fb3d451ac078',
"allowed": true,
"request": {
"user": 'user:anne',
"relation": 'reader',
"object": 'document:Z'}
}
],
}
*/
// The Go SDK does not yet support server-side batch checks. This currently just calls the check endpoint in parallel.
body := ClientBatchCheckBody{
{
User: "user:anne",
Relation: "writer",
Object: "document:Z",
},
{
User: "user:anne",
Relation: "reader",
Object: "document:Z",
},
}
options := ClientBatchCheckOptions{
AuthorizationModelId: PtrString("01HVMMBCMGZNT3SED4Z17ECXCA"),
}
data, err := fgaClient.BatchCheck(context.Background()).Body(requestBody).Options(options).Execute()
/*
data = [{
Allowed: false,
Request: {
User: 'user:anne',
Relation: 'writer',
Object: 'document:Z'
}
}, {
Allowed: true,
Request: {
User: 'user:anne',
Relation: 'reader',
Object: 'document:Z'
}
}]
*/
// The .NET SDK does not yet support server-side batch checks. This currently just calls the check endpoint in parallel.
var body = new ClientBatchCheckRequest {
Checks = new List<ClientCheckRequest>() {
new() {
User = "user:anne",
Relation = "writer",
Object = "document:Z",
},
new() {
User = "user:anne",
Relation = "reader",
Object = "document:Z",
},
},
}
var options = new ClientBatchCheckOptions {
AuthorizationModelId: "01HVMMBCMGZNT3SED4Z17ECXCA",
}
var response = await fgaClient.BatchCheck(body, options);
/*
response.Responses = [{
Allowed: false,
Request: {
User: 'user:anne',
Relation: 'writer',
Object: 'document:Z'
}
}, {
Allowed: true,
Request: {
User: 'user:anne',
Relation: 'reader',
Object: 'document:Z'
}
}]
*/
# Requires >=v0.9.0 for the server side BatchCheck, earlier versions support a client-side BatchCheck with a slightly different interface
checks = [
ClientBatchCheckItem(
user="user:anne",
relation="writer",
object="document:Z",
correlation_id="886224f6-04ae-4b13-bd8e-559c7d3754e1",
ClientBatchCheckItem(
user="user:anne",
relation="reader",
object="document:Z",
correlation_id="da452239-a4e0-4791-b5d1-fb3d451ac078"
]
options = {
authorization_model_id="01HVMMBCMGZNT3SED4Z17ECXCA"}
response = await fga_client.batch_check(ClientBatchCheckRequest(checks=checks), options)
# response.results = [{
# correlation_id: '886224f6-04ae-4b13-bd8e-559c7d3754e1',
# allowed: false,
# request: {
# user: 'user:anne',
# relation: 'writer',
# object: 'document:Z'}
#}, {
# correlation_id: 'da452239-a4e0-4791-b5d1-fb3d451ac078',
# allowed: true,
# request: {
# user: 'user:anne',
# relation: 'reader',
# object: 'document:Z'}
#}]
// Requires >=v0.8.0 for the server side BatchCheck, earlier versions support a client-side BatchCheck with a slightly different interface
var request = new ClientBatchCheckRequest().checks(
List.of(
new ClientBatchCheckItem()
.user("user:anne")
.relation("writer")
._object("document:Z")
.correlationId("886224f6-04ae-4b13-bd8e-559c7d3754e1"),
new ClientBatchCheckItem()
.user("user:anne")
.relation("reader")
._object("document:Z")
.correlationId("da452239-a4e0-4791-b5d1-fb3d451ac078")
);
var options = new ClientBatchCheckOptions()
.authorizationModelId("01HVMMBCMGZNT3SED4Z17ECXCA")
.maxBatchSize(50) // optional, default is 50, can be used to limit the number of checks in a single server request
.maxParallelRequests(10); // optional, default is 10, can be used to limit the parallelization of the BatchCheck chunks
var response = fgaClient.batchCheck(request, options).get();
/*
{
"result": [
{
"correlationId": '886224f6-04ae-4b13-bd8e-559c7d3754e1',
"allowed": false,
"request": {
"user": 'user:anne',
"relation": 'writer',
"_object": 'document:Z'}
}, {
"correlationId": 'da452239-a4e0-4791-b5d1-fb3d451ac078',
"allowed": true,
"request": {
"user": 'user:anne',
"relation": 'reader',
"_object": 'document:Z'}
}
],
}
*/
curl -X POST $FGA_API_URL/stores/$FGA_STORE_ID/batch-check \
-H "Authorization: Bearer $FGA_API_TOKEN" \ # Not needed if service does not require authorization
-H "content-type: application/json" \
-d '{
"authorization_model_id": "01HVMMBCMGZNT3SED4Z17ECXCA",
"checks": [
{
"tuple_key": {
"user":"user:anne",
"relation":"writer",
"object":"document:Z",
},
"correlation_id": "886224f6-04ae-4b13-bd8e-559c7d3754e1"
},
{
"tuple_key": {
"user":"user:anne",
"relation":"reader",
"object":"document:Z",
},
"correlation_id": "da452239-a4e0-4791-b5d1-fb3d451ac078"
},
# Response:
{
"results": {
{ "886224f6-04ae-4b13-bd8e-559c7d3754e1": { "allowed": false }}, # writer
{ "da452239-a4e0-4791-b5d1-fb3d451ac078": { "allowed": true }}, # reader
}
}
BatchCheck([
- user="user:anne", relation="writer", object="document:Z", correlation_id="886224f6-04ae-4b13-bd8e-559c7d3754e1"
- user="user:anne", relation="reader", object="document:Z", correlation_id="da452239-a4e0-4791-b5d1-fb3d451ac078"
])
Reply:
- correlation_id="886224f6-04ae-4b13-bd8e-559c7d3754e1": false
- correlation_id="da452239-a4e0-4791-b5d1-fb3d451ac078": true
The result will include an allowed
field for each authorization check that will return true
if the relationship exists and false
if the relationship does not exist.
Configuring Batch Check
BatchCheck has two available configuration options:
-
Limit the number of checks allowed in a single BatchCheck request.
- Environment variable:
OPENFGA_MAX_CHECKS_PER_BATCH_CHECK
- Command line flag:
--max-checks-per-batch-check
- If more items are received in a single request than allowed by this limit, the API will return an error.
- Environment variable:
-
Limit the number of Checks which can be resolved concurrently
- Environment variable:
OPENFGA_MAX_CONCURRENT_CHECKS_PER_BATCH_CHECK
- Command line flag:
--max-concurrent-checks-per-batch-check
- Environment variable: