OpenFGA Python SDK
The OpenFGA Python SDK provides a high-performance and flexible authorization/permission engine client, inspired by Google Zanzibar. It allows developers to integrate OpenFGA for fine-grained access control in their Python applications. The library is actively developed with frequent releases, typically every few weeks.
Warnings
- breaking The `OpenFgaClient` class was moved from `openfga_sdk.client.OpenFgaClient` to `openfga_sdk.OpenFgaClient` for direct import.
- breaking All API model classes (e.g., `WriteRequest`, `User`, `Object`) were moved from `openfga_sdk.client` to the `openfga_sdk.models` submodule.
- gotcha All OpenFGA operations require a `store_id`. This ID represents a tenant or distinct authorization store and must be created in your OpenFGA service instance (e.g., via the OpenFGA dashboard or API) before use.
- gotcha Correctly configuring authentication credentials (API Token vs. OAuth2 Client Credentials) is critical. For OAuth2, ensure `token_url` and `audience` are correctly specified in `Credentials`.
Install
-
pip install openfga-sdk
Imports
- OpenFgaClient
from openfga_sdk import OpenFgaClient
- Credentials
from openfga_sdk import Credentials
- Models
from openfga_sdk.models import WriteRequest, TupleKey, User, Relation, Object, CheckRequest
Quickstart
import os
from openfga_sdk import OpenFgaClient, Credentials
from openfga_sdk.models import WriteRequest, TupleKey, User, Relation, Object, CheckRequest
# Configure OpenFGA client using environment variables for sensitive data.
# Required: FGA_API_URL, FGA_STORE_ID
# Optional (for auth): FGA_API_TOKEN or FGA_CLIENT_ID/FGA_CLIENT_SECRET/FGA_TOKEN_URL/FGA_AUDIENCE
fga_api_url = os.environ.get("FGA_API_URL", "http://localhost:8080")
fga_store_id = os.environ.get("FGA_STORE_ID", "01H4F8G5K4S8K7J2G8R1T0V9M0") # Replace with your actual Store ID
credentials = None
api_token = os.environ.get("FGA_API_TOKEN")
if api_token:
credentials = Credentials(api_token=api_token)
elif os.environ.get("FGA_CLIENT_ID") and os.environ.get("FGA_CLIENT_SECRET"):
# Example for Client Credentials flow with OAuth2 (replace with your IdP details)
credentials = Credentials(
client_id=os.environ.get("FGA_CLIENT_ID", ""),
client_secret=os.environ.get("FGA_CLIENT_SECRET", ""),
token_url=os.environ.get("FGA_TOKEN_URL", "https://auth.fga.example.com/oauth/token"),
audience=os.environ.get("FGA_AUDIENCE", fga_api_url) # Audience often matches API URL
)
if not fga_store_id:
raise ValueError("FGA_STORE_ID environment variable is required.")
client = OpenFgaClient(
api_url=fga_api_url,
store_id=fga_store_id,
credentials=credentials,
)
try:
# 1. Write a relationship: "user:anne can view document:roadmap"
write_response = client.write(
body=WriteRequest(
writes=[
TupleKey(
user=User(id="anne"),
relation="viewer",
object=Object(type="document", id="roadmap")
)
]
)
)
print(f"Wrote relationship: user:anne is viewer of document:roadmap")
# 2. Check if "user:anne can view document:roadmap"
check_response = client.check(
body=CheckRequest(
user=User(id="anne"),
relation="viewer",
object=Object(type="document", id="roadmap")
)
)
print(f"Check result (anne can view roadmap): {check_response.allowed}") # Expected: True
# 3. Check if "user:bob can view document:roadmap" (assuming bob has no relation)
check_response_bob = client.check(
body=CheckRequest(
user=User(id="bob"),
relation="viewer",
object=Object(type="document", id="roadmap")
)
)
print(f"Check result (bob can view roadmap): {check_response_bob.allowed}") # Expected: False
except Exception as e:
print(f"An error occurred: {e}")
# The client uses an httpx.Client which is typically managed internally.
# No explicit close() is necessary for OpenFgaClient as of v0.10.0 in most cases.