Zero-auth FastAPI middleware for Taleemabad authentication service
Project description
Taleemabad Auth — FastAPI Middleware
Zero-auth FastAPI middleware for Taleemabad authentication service. Clients add 1 line of setup, define 1 enrichment hook, and get full authentication with zero auth code.
Features
✅ Zero Auth Code — No JWT verification, token refresh, or auth logic in your app
✅ Backend-to-Backend Verification — Private key never leaves Taleemabad
✅ Automatic Token Refresh — Expired tokens automatically refreshed
✅ Per-Request Enrichment — Custom fields fetched fresh on every request
✅ Multi-Tenant Ready — Built for organizations
✅ Configurable Token Source — Header (default), session, or cookie
Installation (Phase 3: Integration Testing)
During initial integration testing, copy the middleware directory into your FastAPI project:
# Copy the taleemabad_auth/ directory to your project
cp -r /path/to/taleemabad-auth/middleware/python/taleemabad_auth ./
Your project structure should look like:
your-project/
├── main.py
├── taleemabad_auth/ ← Copy this entire directory
│ ├── __init__.py
│ ├── models.py
│ ├── exceptions.py
│ ├── client.py
│ ├── hooks.py
│ ├── token.py
│ └── middleware.py
└── ...
Then import from your local directory:
from taleemabad_auth import TaleebabadAuth, require_user
Future (Phase 4): After successful integration testing, this will be available on PyPI:
pip install taleemabad-auth
Quick Start
1. Get Credentials
Contact the Taleemabad team with your organization name. You'll receive:
TALEEMABAD_CLIENT_ID— your organization UUIDTALEEMABAD_CLIENT_SECRET— your organization secretTALEEMABAD_AUTH_SERVICE_URL— the auth service URL
Store in .env:
TALEEMABAD_CLIENT_ID=your-org-uuid
TALEEMABAD_CLIENT_SECRET=your-secret
TALEEMABAD_AUTH_SERVICE_URL=https://auth.taleemabad.com
2. Initialize in Your App
from fastapi import FastAPI, Depends
from taleemabad_auth import TaleebabadAuth, require_user
import os
app = FastAPI()
# Initialize Taleemabad auth
auth = TaleebabadAuth(
auth_service_url=os.getenv("TALEEMABAD_AUTH_SERVICE_URL"),
client_id=os.getenv("TALEEMABAD_CLIENT_ID"),
client_secret=os.getenv("TALEEMABAD_CLIENT_SECRET"),
token_source="header", # or "session" or "cookie"
)
# Add to app
app.add_middleware(auth.middleware)
3. Define Enrichment Hook
This is where you fetch custom fields from YOUR database:
@auth.register_hook("enrich_user_claims")
async def enrich_user(user_id: str) -> dict:
"""Fetch custom fields from your database."""
# Example: fetch user role and permissions from your DB
user = await db.get_user(user_id)
return {
"role": user.role,
"permissions": {
"create_class": True,
"grade_students": user.permissions.get("grade_students", False),
},
"organization_id": user.org_id,
}
4. Protect Routes
Use require_user dependency:
@app.get("/protected")
async def protected_route(user=Depends(require_user)):
return {"username": user.username, "role": user.role}
# Or access user from request.state
@app.get("/optional")
async def optional_auth(request):
if hasattr(request.state, "user"):
return {"username": request.state.user.username}
else:
return {"username": "anonymous"}
5. Logout
Add logout endpoint:
@app.post("/api/logout")
async def logout(request):
await auth.logout(request)
return {"message": "logged out"}
That's it! ✨
Request Flow
Client Frontend
│
├─→ POST /api/login
│ └─→ Middleware intercepts response
│ └─→ Stores tokens (access in localStorage, refresh in cookie)
│
├─→ GET /api/classes (with Authorization: Bearer <access_token>)
│ └─→ Middleware intercepts request
│ ├─ Extract token from Authorization header
│ ├─ POST /api/verify-token (backend-to-backend)
│ ├─ If expired: POST /api/refresh (auto-refresh)
│ ├─ Call enrichUserClaims hook
│ ├─ POST /api/sync-user-profile (store enriched data)
│ ├─ Attach user + claims to request.state
│ └─ Continue to route handler
│
└─→ POST /api/logout
└─→ Middleware revokes refresh token
Configuration
Token Source
Control where the middleware extracts the access token from:
auth = TaleebabadAuth(
token_source="header", # Authorization: Bearer <token>
# OR
token_source="session", # request.session['taleemabad_token']
# OR
token_source="cookie", # request.cookies['access_token']
)
Timeout
Adjust HTTP request timeout (default 10 seconds):
auth = TaleebabadAuth(
timeout=5, # 5 second timeout for all HTTP calls
)
Hooks
enrich_user_claims
Called on every request to fetch custom fields from your database.
@auth.register_hook("enrich_user_claims")
async def enrich(user_id: str) -> dict:
# Fetch from your database
user = await db.get_user(user_id)
return {
"role": user.role,
"permissions": user.permissions,
"organization_id": user.org_id,
}
on_user_verified (Optional)
Called after user is verified. Use for logging, analytics, etc.
@auth.register_hook("on_user_verified")
async def on_verified(user, claims):
# Log user verification
print(f"User {user.username} verified")
# Or send to analytics service
await analytics.track_login(user.id)
Error Handling
The middleware is non-fatal:
- If token verification fails → request continues without user
- If enrichment hook fails → request continues (empty custom fields)
- If sync fails → request continues (non-blocking)
- If token refresh fails → request continues without user
Use require_user dependency to enforce authentication on protected routes:
@app.get("/protected")
async def protected(user=Depends(require_user)):
# If user is not authenticated, returns 401
return {"username": user.username}
Testing
Run tests:
# Install dev dependencies
pip install -e ".[dev]"
# Run tests
pytest -v
# With coverage
pytest --cov=taleemabad_auth tests/
Test files:
tests/test_client.py— HTTP client teststests/test_hooks.py— Hook registry teststests/test_token.py— Token extraction and expiry checkstests/test_middleware.py— Full middleware flow tests
Development
# Install with dev dependencies
pip install -e ".[dev]"
# Format code
black taleemabad_auth/
# Lint
ruff check taleemabad_auth/
# Type check
mypy taleemabad_auth/
Under the Hood
What Middleware Does
- Extract Token — From header/session/cookie (configurable)
- Verify Backend-to-Backend — Calls
/api/verify-tokenwith client credentials - Handle Expiry — If token expired, auto-refreshes via
/api/refresh - Enrich with Hook — Calls your
enrich_user_claimsfunction - Sync Data — Stores enriched data in Taleemabad via
/api/sync-user-profile - Attach to Request — Adds
request.state.userandrequest.state.claims
What Your App Doesn't Need
✅ JWT verification
✅ Token refresh logic
✅ Password hashing
✅ Role checking
✅ Permission validation
✅ Session management
✅ Cookie handling
All handled by the middleware.
API Reference
TaleebabadAuth
Main class for initialization.
auth = TaleebabadAuth(
auth_service_url: str, # Taleemabad service URL
client_id: str, # Organization UUID
client_secret: str, # Organization secret
token_source: str = "header", # "header", "session", or "cookie"
schema: dict = None, # Optional schema definition
timeout: int = 10, # HTTP timeout in seconds
)
# Methods
auth.register_hook(name) # @auth.register_hook("hook_name")
await auth.logout(request) # Call from logout endpoint
require_user
FastAPI dependency for protecting routes.
from taleemabad_auth import require_user
from fastapi import Depends
@app.get("/protected")
async def protected(user=Depends(require_user)):
# user is AuthUser (guaranteed non-None)
return {"username": user.username}
Models
from taleemabad_auth import AuthUser, TokenClaims
# In your route handler:
@app.get("/me")
async def get_user(request):
user: AuthUser = request.state.user # id, username, email, phone
claims: TokenClaims = request.state.claims # user + custom_fields
return {"user": user, "claims": claims}
Support
- Documentation: Taleemabad Auth Service
- Issues: GitHub Issues
- Email: dev@taleemabad.com
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file taleemabad_auth-0.1.0.tar.gz.
File metadata
- Download URL: taleemabad_auth-0.1.0.tar.gz
- Upload date:
- Size: 18.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a90edaf8cdff1255d270183d234111f669196c8f801f0cde40686341657bfa53
|
|
| MD5 |
991eb6ff96d5be3e93384301fe130681
|
|
| BLAKE2b-256 |
6141c67eea07a06e47802051598043107f7ee1f15f7b794027fb58a08b387571
|
File details
Details for the file taleemabad_auth-0.1.0-py3-none-any.whl.
File metadata
- Download URL: taleemabad_auth-0.1.0-py3-none-any.whl
- Upload date:
- Size: 14.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cb1872f873bfb4869d91a364dec2e2860f9b26e41bc0774c2e3fa745a8acf2fe
|
|
| MD5 |
c4541426438de77a1e9cee25e0eabacc
|
|
| BLAKE2b-256 |
750b92ceb8006387bfc026ac0b1eb73610924f41a3576721efc7702ad60f6de0
|