List all users with a relationship to an object
The ListUsers API returns a list of all the users of a specific type that have a relation to a given object.
To arrive at a result, the API uses:
-
Explicit tuples written through the Write API
-
Contextual tuples present in the request
-
Implicit tuples that exist by virtue of applying set theory
For example: document:2021-budget#viewer@document:2021-budget#viewer. In this example, the set of users who are viewers of document:2021-budget are the set of users who are the viewers of document:2021-budget.
An authorization_model_id may be specified in the body. If it is not specified, the latest authorization model ID is used.
Note: We recommend you specify authorization model ID for better performance.
You may also specify contextual_tuples that are treated as regular tuples. Each of these tuples may have an associated condition.
You may also provide a context object used to evaluate the conditioned tuples in the system.
Note: We recommend you provide a value for all the input parameters of all the conditions. This ensures that all tuples be evaluated correctly.
The response contains the related users in an array in the “users” field of the response. These results may include specific objects, usersets or type-bound public access. Each of these types of results is encoded in its own type and not represented as a string.
In cases where a type-bound public access result is returned (e.g. user:*), it cannot be inferred that all subjects
of that type have a relation to the object; it is possible that negations exist and checks should still be queried
on individual subjects to ensure access to that document.
The number of users in the response array are limited by the execution timeout specified in the flag OPENFGA_LIST_USERS_DEADLINE and by the upper bound specified in the flag OPENFGA_LIST_USERS_MAX_RESULTS, whichever is hit first.
The returned users are not sorted, and therefore two identical calls may yield different sets of users.
const { OpenFgaClient, ConsistencyPreference } = require('@openfga/sdk');
const fgaClient = new OpenFgaClient({
apiUrl: process.env.FGA_API_URL,
storeId: process.env.FGA_STORE_ID,
authorizationModelId: process.env.FGA_MODEL_ID, // Optional; requests can override this.
});
async function main() {
const body = {
"object": {"type": "document", "id": "budget"},
"relation": "reader",
"user_filters": [
{
"type": "user"
}
]
};
const options = {
};
const response = await fgaClient.listUsers(body, options);
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});package main
import (
"context"
"os"
openfga "github.com/openfga/go-sdk"
. "github.com/openfga/go-sdk/client"
)
func main() {
fgaClient, err := NewSdkClient(&ClientConfiguration{
ApiUrl: os.Getenv("FGA_API_URL"),
StoreId: os.Getenv("FGA_STORE_ID"),
AuthorizationModelId: os.Getenv("FGA_MODEL_ID"), // Optional; requests can override this.
})
if err != nil {
panic(err)
}
body := ClientListUsersRequest{
Object: openfga.FgaObject{
Type: "document",
Id: "budget",
},
Relation: "reader",
UserFilters: []openfga.UserTypeFilter{
openfga.UserTypeFilter{
Type: "user",
},
},
}
options := ClientListUsersOptions{
}
data, err := fgaClient.ListUsers(context.Background()).Body(body).Options(options).Execute()
if err != nil {
panic(err)
}
_ = data
}using System.Collections.Generic;
using OpenFga.Sdk.Client;
using OpenFga.Sdk.Client.Model;
using OpenFga.Sdk.Model;
using Environment = System.Environment;
var fgaClient = new OpenFgaClient(new ClientConfiguration() {
ApiUrl = Environment.GetEnvironmentVariable("FGA_API_URL"),
StoreId = Environment.GetEnvironmentVariable("FGA_STORE_ID"),
AuthorizationModelId = Environment.GetEnvironmentVariable("FGA_MODEL_ID"), // Optional; requests can override this.
});
var body = new ClientListUsersRequest {
Object = new FgaObject {
Type = "document",
Id = "budget",
},
Relation = "reader",
UserFilters = new List<UserTypeFilter> {
new UserTypeFilter {
Type = "user",
},
},
};
var options = new ClientListUsersOptions {
};
var response = await fgaClient.ListUsers(body, options);import asyncio
import os
from openfga_sdk.client import OpenFgaClient, ClientConfiguration
from openfga_sdk.client.models import ClientTuple
from openfga_sdk.client.models.list_users_request import ClientListUsersRequest
from openfga_sdk.models import RelationshipCondition, FgaObject, UserTypeFilter
async def main():
configuration = ClientConfiguration(
api_url=os.environ.get("FGA_API_URL"),
store_id=os.environ.get("FGA_STORE_ID"),
authorization_model_id=os.environ.get("FGA_MODEL_ID"), # Optional; requests can override this.
)
async with OpenFgaClient(configuration) as fga_client:
body = ClientListUsersRequest(
object=FgaObject(
type="document",
id="budget",
),
relation="reader",
user_filters=[
UserTypeFilter(
type="user",
)
],
)
options = {
}
response = await fga_client.list_users(body, options)
asyncio.run(main())import dev.openfga.sdk.api.client.OpenFgaClient;
import dev.openfga.sdk.api.configuration.ClientConfiguration;
import dev.openfga.sdk.api.configuration.*;
import dev.openfga.sdk.api.client.model.*;
import dev.openfga.sdk.api.model.*;
import java.util.List;
import java.util.Map;
import java.util.ArrayList;
public class Example {
public static void main(String[] args) throws Exception {
var config = new ClientConfiguration()
.apiUrl(System.getenv("FGA_API_URL"))
.storeId(System.getenv("FGA_STORE_ID"))
.authorizationModelId(System.getenv("FGA_MODEL_ID")); // Optional; requests can override this.
var fgaClient = new OpenFgaClient(config);
var body = new ClientListUsersRequest()
._object(new FgaObject()
.type("document")
.id("budget"))
.relation("reader")
.userFilters(java.util.Arrays.asList(new UserTypeFilter()
.type("user")));
var options = new ClientListUsersOptions();
var response = fgaClient.listUsers(body, options).get();
}
}# Set FGA_API_URL to the URL of your OpenFGA server.
# Set FGA_STORE_ID to your store ID.
# These examples use a server with authentication disabled.
# For authenticated servers, see /docs/getting-started/setup-sdk-client.
curl -X POST "$FGA_API_URL/stores/$FGA_STORE_ID/list-users" \
-H "content-type: application/json" \
-d '{
"authorization_model_id": "'"$FGA_MODEL_ID"'",
"object": {
"type": "document",
"id": "budget"
},
"relation": "reader",
"user_filters": [
{
"type": "user"
}
]
}'{
"users": [
{
"object": {
"id": "0bcdf6fa-a6aa-4730-a8eb-9cf172ff16d9",
"type": "document"
},
"userset": {
"id": "fga",
"relation": "member",
"type": "group"
},
"wildcard": {
"type": "employee"
}
}
]
}{
"code": "validation_error",
"message": "Generic validation error"
}{
"code": "unauthenticated",
"message": "unauthenticated"
}{
"code": "forbidden",
"message": "the principal is not authorized to perform the action"
}{
"code": "undefined_endpoint",
"message": "Endpoint not enabled"
}{
"code": "10",
"message": "transaction conflict"
}{
"code": "throttled_timeout_error",
"message": "timeout due to throttling on complex request"
}{
"code": "internal_error",
"message": "Internal Server Error"
}Path Parameters
Body
Object represents an OpenFGA Object.
An Object is composed of a type and identifier (e.g. 'document:1')
Show child attributes
Show child attributes
"document:example"
"reader"
The type of results returned. Only accepts exactly one value.
1 elementShow child attributes
Show child attributes
[ { "type": "user" }, { "relation": "member", "type": "group" } ]
"01G5JAVJ41T49E9TT3SKVS7X1J"
Controls the consistency preference for this request. Default value is UNSPECIFIED, which has the same behavior as MINIMIZE_LATENCY.
UNSPECIFIED, MINIMIZE_LATENCY, HIGHER_CONSISTENCY "MINIMIZE_LATENCY"
Additional request context used to evaluate any ABAC conditions encountered in the query evaluation.
100Show child attributes
Show child attributes
Response
A successful response.
Show child attributes
Show child attributes
Was this page helpful?
const { OpenFgaClient, ConsistencyPreference } = require('@openfga/sdk');
const fgaClient = new OpenFgaClient({
apiUrl: process.env.FGA_API_URL,
storeId: process.env.FGA_STORE_ID,
authorizationModelId: process.env.FGA_MODEL_ID, // Optional; requests can override this.
});
async function main() {
const body = {
"object": {"type": "document", "id": "budget"},
"relation": "reader",
"user_filters": [
{
"type": "user"
}
]
};
const options = {
};
const response = await fgaClient.listUsers(body, options);
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});package main
import (
"context"
"os"
openfga "github.com/openfga/go-sdk"
. "github.com/openfga/go-sdk/client"
)
func main() {
fgaClient, err := NewSdkClient(&ClientConfiguration{
ApiUrl: os.Getenv("FGA_API_URL"),
StoreId: os.Getenv("FGA_STORE_ID"),
AuthorizationModelId: os.Getenv("FGA_MODEL_ID"), // Optional; requests can override this.
})
if err != nil {
panic(err)
}
body := ClientListUsersRequest{
Object: openfga.FgaObject{
Type: "document",
Id: "budget",
},
Relation: "reader",
UserFilters: []openfga.UserTypeFilter{
openfga.UserTypeFilter{
Type: "user",
},
},
}
options := ClientListUsersOptions{
}
data, err := fgaClient.ListUsers(context.Background()).Body(body).Options(options).Execute()
if err != nil {
panic(err)
}
_ = data
}using System.Collections.Generic;
using OpenFga.Sdk.Client;
using OpenFga.Sdk.Client.Model;
using OpenFga.Sdk.Model;
using Environment = System.Environment;
var fgaClient = new OpenFgaClient(new ClientConfiguration() {
ApiUrl = Environment.GetEnvironmentVariable("FGA_API_URL"),
StoreId = Environment.GetEnvironmentVariable("FGA_STORE_ID"),
AuthorizationModelId = Environment.GetEnvironmentVariable("FGA_MODEL_ID"), // Optional; requests can override this.
});
var body = new ClientListUsersRequest {
Object = new FgaObject {
Type = "document",
Id = "budget",
},
Relation = "reader",
UserFilters = new List<UserTypeFilter> {
new UserTypeFilter {
Type = "user",
},
},
};
var options = new ClientListUsersOptions {
};
var response = await fgaClient.ListUsers(body, options);import asyncio
import os
from openfga_sdk.client import OpenFgaClient, ClientConfiguration
from openfga_sdk.client.models import ClientTuple
from openfga_sdk.client.models.list_users_request import ClientListUsersRequest
from openfga_sdk.models import RelationshipCondition, FgaObject, UserTypeFilter
async def main():
configuration = ClientConfiguration(
api_url=os.environ.get("FGA_API_URL"),
store_id=os.environ.get("FGA_STORE_ID"),
authorization_model_id=os.environ.get("FGA_MODEL_ID"), # Optional; requests can override this.
)
async with OpenFgaClient(configuration) as fga_client:
body = ClientListUsersRequest(
object=FgaObject(
type="document",
id="budget",
),
relation="reader",
user_filters=[
UserTypeFilter(
type="user",
)
],
)
options = {
}
response = await fga_client.list_users(body, options)
asyncio.run(main())import dev.openfga.sdk.api.client.OpenFgaClient;
import dev.openfga.sdk.api.configuration.ClientConfiguration;
import dev.openfga.sdk.api.configuration.*;
import dev.openfga.sdk.api.client.model.*;
import dev.openfga.sdk.api.model.*;
import java.util.List;
import java.util.Map;
import java.util.ArrayList;
public class Example {
public static void main(String[] args) throws Exception {
var config = new ClientConfiguration()
.apiUrl(System.getenv("FGA_API_URL"))
.storeId(System.getenv("FGA_STORE_ID"))
.authorizationModelId(System.getenv("FGA_MODEL_ID")); // Optional; requests can override this.
var fgaClient = new OpenFgaClient(config);
var body = new ClientListUsersRequest()
._object(new FgaObject()
.type("document")
.id("budget"))
.relation("reader")
.userFilters(java.util.Arrays.asList(new UserTypeFilter()
.type("user")));
var options = new ClientListUsersOptions();
var response = fgaClient.listUsers(body, options).get();
}
}# Set FGA_API_URL to the URL of your OpenFGA server.
# Set FGA_STORE_ID to your store ID.
# These examples use a server with authentication disabled.
# For authenticated servers, see /docs/getting-started/setup-sdk-client.
curl -X POST "$FGA_API_URL/stores/$FGA_STORE_ID/list-users" \
-H "content-type: application/json" \
-d '{
"authorization_model_id": "'"$FGA_MODEL_ID"'",
"object": {
"type": "document",
"id": "budget"
},
"relation": "reader",
"user_filters": [
{
"type": "user"
}
]
}'{
"users": [
{
"object": {
"id": "0bcdf6fa-a6aa-4730-a8eb-9cf172ff16d9",
"type": "document"
},
"userset": {
"id": "fga",
"relation": "member",
"type": "group"
},
"wildcard": {
"type": "employee"
}
}
]
}{
"code": "validation_error",
"message": "Generic validation error"
}{
"code": "unauthenticated",
"message": "unauthenticated"
}{
"code": "forbidden",
"message": "the principal is not authorized to perform the action"
}{
"code": "undefined_endpoint",
"message": "Endpoint not enabled"
}{
"code": "10",
"message": "transaction conflict"
}{
"code": "throttled_timeout_error",
"message": "timeout due to throttling on complex request"
}{
"code": "internal_error",
"message": "Internal Server Error"
}