FastAPI-Topaz
FastAPI-Topaz asks a Topaz authorizer whether each request may proceed, and returns HTTP 403 Forbidden when the answer is no.
Full documentation: jmanteau.github.io/fastapi-topaz
Upgrading from 1.x? See Upgrading to 2.0.
How it works
Your FastAPI app sends the user's identity and the route to Topaz. Topaz evaluates a policy and returns allowed or denied.
flowchart LR
C[Client] --> F[FastAPI route]
F --> D["Dependency<br/>or TopazMiddleware"]
D --> TC[TopazConfig]
TC -->|"gRPC"| T[Topaz authorizer]
T --> P["Policies (Rego)"]
T --> R["Directory (relationships)"]
TC -.->|"denied"| X[HTTP 403]
| Component | Role | Source |
|---|---|---|
TopazConfig |
Holds the Topaz connection, how to find the user, and the policy root. Create it once at startup. | config.py L153–L243 |
| Dependencies | Protect one route at a time with Depends(...). |
dependencies.py |
TopazMiddleware |
Protects every route in the app, except the paths you exclude. | middleware.py L131–L186 |
Requirements
- Python 3.10 or later
- FastAPI 0.100 or later (except 0.137.0 and 0.137.1)
- A running Topaz instance
Install
pip install fastapi-topaz
Quick start
This example protects GET /documents. Topaz evaluates the policy myapp.GET.documents for the user in request.state.user_id.
from fastapi import Depends, FastAPI, Request
from fastapi_topaz import (
AuthorizerOptions,
Identity,
IdentityType,
TopazConfig,
require_policy_allowed,
)
config = TopazConfig(
authorizer_options=AuthorizerOptions(url="localhost:8282"),
policy_path_root="myapp",
identity_provider=lambda req: Identity(
type=IdentityType.IDENTITY_TYPE_SUB,
value=req.state.user_id,
),
policy_instance_name="myapp",
)
app = FastAPI()
@app.get("/documents")
async def list_documents(
request: Request,
_: None = Depends(require_policy_allowed(config, "myapp.GET.documents")),
):
return {"documents": [...]}
Choose a check
Pick the check that matches your question. Not sure which one? Read Choosing an authorization approach.
| Question to answer | Use | Source |
|---|---|---|
| May this user call this route? (you name the policy) | require_policy_allowed() |
dependencies.py L137–L169 |
| May this user call this route? (policy name built from the route) | require_policy_auto() |
dependencies.py L172–L232 |
Does this user have a relation to this object, such as can_write on a document? |
require_rebac_allowed() |
dependencies.py L235–L305 |
| Does this user have access at every level of a nested path, such as org → project → document? | require_rebac_hierarchy() |
dependencies.py L497 |
| Fetch one object, and return it only if the user may see it | get_authorized_resource() |
dependencies.py L308 |
| Keep only the objects in a list that the user may see | filter_authorized_resources() |
dependencies.py L413 |
| Protect every route without editing each one | TopazMiddleware |
middleware.py L131 |
require_policy_auto() builds the policy name from the HTTP method and the route template:
| Route | Policy name |
|---|---|
GET /documents |
myapp.GET.documents |
GET /documents/{id} |
myapp.GET.documents.__id |
PUT /users/{user_id}/docs/{doc_id} |
myapp.PUT.users.__user_id.docs.__doc_id |
Example of a relationship check: the user must have the can_write relation on the document whose ID is in the {id} path parameter.
@app.put("/documents/{id}")
async def update_document(
id: int,
_: None = Depends(require_rebac_allowed(config, "document", "can_write")),
):
...
Production features
Turn each feature on by passing an object to TopazConfig. All are optional.
| Feature | What it does | TopazConfig argument |
Guide |
|---|---|---|---|
| Decision cache | Reuses recent decisions for a set Time To Live (TTL), so Topaz gets fewer calls. | decision_cache |
Reference |
| Circuit breaker | Stops calling Topaz after repeated failures, then falls back to cached decisions. | circuit_breaker |
Circuit breaker |
| Audit logging | Writes each decision as a structured JSON log line. | audit_logger |
Audit logging |
| Metrics | Exports Prometheus metrics. | metrics |
Observability |
| Tracing | Exports OpenTelemetry (OTel) traces. | tracing |
Observability |
| Test doubles | Replaces Topaz with fixed rules in unit tests. | — (fastapi_topaz.testing) |
Testing |
Command-line tool
The package installs a fastapi-topaz command. Each subcommand reads your app from module:attribute.
| Command | What it does |
|---|---|
generate-policies |
Writes a Rego policy skeleton for each route. |
policy-diff |
Lists routes that have no policy, and policies that match no route. |
generate-rights-matrix |
Writes a Markdown table of routes and their policies. |
policy-map |
Prints which policy each route uses. |
check |
Shows which policy a given request URL resolves to. Add --live to ask Topaz for the decision. |
fastapi-topaz policy-diff --app myapp.main:app --policies policies/
Full options: CLI reference. Source: cli.py L329.
Terms
| Term | Meaning |
|---|---|
| Policy | A rule, written in Rego, that Topaz evaluates to return allowed or denied. |
| Rego | The policy language of Open Policy Agent (OPA), which Topaz uses. |
| ReBAC | Relationship-Based Access Control. Access depends on how the user relates to an object, for example "owner of document 42". |
| gRPC | The remote procedure call protocol this library uses to talk to Topaz (default port 8282). |
| Identity provider | Your function that reads the current user from the request. |
Documentation
The documentation follows the Diátaxis framework.
| Section | Read it when you want to… |
|---|---|
| Tutorials | learn step by step, from zero |
| How-to guides | solve one specific problem |
| Reference | look up an exact function, argument, or CLI option |
| Explanation | understand the design and the concepts |
Related: Topaz documentation · FastAPI documentation
License
Apache 2.0
Metadata
Release files for fastapi-topaz 2.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| fastapi_topaz-2.0.0.tar.gz | 182.2 kB | Without provenance | Details for fastapi_topaz-2.0.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| fastapi_topaz-2.0.0-py3-none-any.whl | Python 3 | none | any | Details for fastapi_topaz-2.0.0-py3-none-any.whl |
Total release size: 244.2 kB
Release files / fastapi_topaz-2.0.0.tar.gz
| Download URL | fastapi_topaz-2.0.0.tar.gz |
|---|---|
| Size | 182.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2446cd45c5c146df75f05482112179ef5597df74999a8fa35733a57ceb916040
|
|
BLAKE2b-256 checksum How to use checksums |
feafc62d9ed66dd655d1e3c8c42f7ed0c74398ead5b2cd0e5ebdd4c58033926d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.12
|
Release files / fastapi_topaz-2.0.0-py3-none-any.whl
| Download URL | fastapi_topaz-2.0.0-py3-none-any.whl |
|---|---|
| Size | 62.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c4e6f5a4306e0f61b738762a613a3117410761ef00c19a82bc968a14978bb19c
|
|
BLAKE2b-256 checksum How to use checksums |
75011c12d79cfe9ccb0fd53a81acc6fb418b4c290579f7fe2b2908e4fc204067
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.12
|
Security for fastapi-topaz 2.0.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.