Skip to main content

Integrate Firestore as the policy storage for Casbin with Python/Flask stack

· 6 min read
Serhii Hrekov
software engineer, creator, artist, programmer, projects founder

The fundamental way to integrate Firestore as the policy storage for Casbin is by using a dedicated Adapter. In Casbin, an adapter serves as the persistent layer, handling the LoadPolicy() and SavePolicy() operations between the in-memory enforcer and the database.

Since you are using a Python/Flask stack, you'll need the appropriate Python Firestore Adapter for Casbin [1].


1. Prerequisites and Installation​

To set up Firestore persistence for your Python Casbin enforcer, you need to install the necessary packages and ensure your Google Cloud credentials are configured.

  1. Casbin: The core Casbin library.

    pip install pycasbin
  2. Firestore Adapter: While there isn't one official adapter maintained by the core Casbin team for Python and Firestore, community-maintained packages exist, such as pycasbin-firebase-adapter [2] (which uses the Firebase Admin SDK to access Firestore).

    pip install pycasbin-firebase-adapter firebase-admin
  3. Authentication: Ensure the environment where your Flask app runs (e.g., GCP App Engine, Cloud Run, GKE) has the necessary IAM permissions to access Firestore, or that you have set up a service account key [3].


2. Setting up the Adapter and Enforcer​

The setup involves two main steps: initializing the Firebase Admin SDK and then passing the initialized object to the Casbin Adapter constructor.

A. Initialize Firebase Admin SDK​

The Casbin Firestore adapter relies on the Firebase Admin SDK to communicate with the database.

import firebase_admin
from firebase_admin import credentials
from firebase_admin import firestore

# --- 1. Load Credentials ---
# Best practice on GCP (e.g., Cloud Run) is to use Application Default Credentials (ADC).
try:
cred = credentials.ApplicationDefault()
firebase_admin.initialize_app(cred)
except:
# Fallback for local testing (replace with your path)
cred = credentials.Certificate("path/to/serviceAccountKey.json")
firebase_admin.initialize_app(cred)

db = firestore.client()

B. Create and Use the Casbin Adapter​

Now, you pass the initialized Firestore client (db) to the adapter, and then pass the adapter to the Casbin Enforcer.

import casbin
from pycasbin_firebase_adapter import Adapter as FirestoreAdapter # Rename for clarity

# 1. Instantiate the Adapter, pointing it to your Firestore client
# Note: The adapter may allow specifying a collection name (e.g., 'casbin_rules').
adapter = FirestoreAdapter(db)

# 2. Instantiate the Enforcer with your model and the new adapter
# 'model.conf' contains the definition of your access control model (e.g., RBAC).
e = casbin.Enforcer("model.conf", adapter)

# --- Policy is automatically loaded into memory here (LoadPolicy()) ---

# 3. Enforcement Check (Uses the in-memory policy)
sub = "alice"
obj = "/reports/finance"
act = "read"

if e.enforce(sub, obj, act):
print(f"{sub} is permitted to {act} {obj}.")
else:
print(f"{sub} is denied access to {obj}.")

Annotation: When the Enforcer is created, the Adapter's LoadPolicy() method is called, which fetches all policy rules (p, g, g2) from Firestore and loads them into Casbin's in-memory model.


3. Policy Management in Firestore​

Once the adapter is set up, you manage all policy rules using the Casbin API; you never interact directly with the Firestore collection for Casbin rules.

A. Saving New Policies​

When you make changes using the Casbin management API, the adapter automatically translates those changes into Firestore documents.

Casbin API CallFirestore Document Action
e.add_policy("editor", "/data", "write")Creates a new document in the Casbin collection (e.g., ptype: p, v0: editor, v1: /data, v2: write).
e.add_grouping_policy("user_x", "editor")Creates a new document (e.g., ptype: g, v0: user_x, v1: editor).
e.save_policy()Overwrites the entire policy in Firestore with the current in-memory state (used less frequently).

B. Firestore Policy Structure​

The Firestore adapter typically stores the policy rules as documents in a single collection (e.g., casbin_rules). Each document will have fields corresponding to the Casbin policy line structure:

FieldCasbin Policy Line Component
ptypeThe policy type (p, g, g2, etc.)
v0The first field (e.g., user or role)
v1The second field (e.g., resource or parent_role)
v2 to v5Subsequent fields (e.g., action or domain)

This ensures that the NoSQL structure of Firestore can faithfully represent the relational policy rules Casbin uses.

Sources and Further Reading​

  1. Casbin Documentation - Adapters
  2. GitHub - pycasbin-firebase-adapter
  3. Google Cloud - Application Default Credentials (ADC) Guide
  4. Casbin Documentation - Policy Storage Details

Related articles