SDKsPython SDKGuides
Django Integration
Protect Django views with Avnology ID authentication and authorization.
Django Integration
Setup
pip install avnology-id djangoSettings
# settings.py
AVNOLOGY_ID = {
"BASE_URL": "https://api.id.avnology.com",
"CLIENT_ID": os.environ["AVNOLOGY_CLIENT_ID"],
"CLIENT_SECRET": os.environ["AVNOLOGY_CLIENT_SECRET"],
}Client singleton
# lib/avnology.py
from django.conf import settings
from avnology_id import AvnologyId
_client = None
def get_client() -> AvnologyId:
global _client
if _client is None:
config = settings.AVNOLOGY_ID
_client = AvnologyId(
base_url=config["BASE_URL"],
client_id=config["CLIENT_ID"],
client_secret=config["CLIENT_SECRET"],
)
return _clientAuthentication middleware
# middleware/auth.py
from django.http import JsonResponse
from lib.avnology import get_client
class AvnologyAuthMiddleware:
def __init__(self, get_response):
self.get_response = get_response
self.exempt_paths = ["/health", "/webhooks/"]
def __call__(self, request):
if any(request.path.startswith(p) for p in self.exempt_paths):
return self.get_response(request)
auth_header = request.headers.get("Authorization", "")
if not auth_header.startswith("Bearer "):
return JsonResponse({"error": "missing_token"}, status=401)
token = auth_header.removeprefix("Bearer ")
client = get_client()
result = client.oauth.introspect_token(token=token)
if not result.active:
return JsonResponse({"error": "invalid_token"}, status=401)
request.avnology_user_id = result.sub
request.avnology_scopes = result.scope.split()
request.avnology_org_id = result.org_id
return self.get_response(request)Register in settings
# settings.py
MIDDLEWARE = [
"middleware.auth.AvnologyAuthMiddleware",
# ... other middleware
]View decorator
# decorators.py
from functools import wraps
from django.http import JsonResponse
from lib.avnology import get_client
def require_permission(relation, object_fn):
def decorator(view_func):
@wraps(view_func)
def wrapper(request, *args, **kwargs):
obj = object_fn(request, *args, **kwargs)
client = get_client()
allowed = client.permissions.check(
subject=f"user:{request.avnology_user_id}",
relation=relation,
object=obj,
)
if not allowed:
return JsonResponse({"error": "forbidden"}, status=403)
return view_func(request, *args, **kwargs)
return wrapper
return decorator
# Usage:
@require_permission("editor", lambda req, pk: f"project:{pk}")
def update_project(request, pk):
# User has editor permission
...Webhook view
# views.py
from django.http import HttpResponse, JsonResponse
from django.views.decorators.csrf import csrf_exempt
from avnology_id.webhook import verify_signature
@csrf_exempt
def webhook_handler(request):
if request.method != "POST":
return HttpResponse(status=405)
signature = request.headers.get("X-Avnology-Signature", "")
if not verify_signature(request.body, signature, WEBHOOK_SECRET):
return JsonResponse({"error": "invalid_signature"}, status=401)
event = json.loads(request.body)
# Process event...
return HttpResponse(status=200)See also
- FastAPI guide -- FastAPI integration
- Flask guide -- Flask integration