Request Context
Where CoreSDK places authenticated claims after middleware runs. FastAPI uses request.state.coresdk_user, Flask uses g.claims, Django uses request.coresdk_claims.
Request Context
After the auth and policy middleware complete, CoreSDK attaches authenticated claims to the request. Your handler reads identity, tenant, and tracing data without touching raw headers or re-parsing the JWT.
Where claims live
The location depends on the framework:
| Framework | Claims location |
|---|---|
| FastAPI | request.state.coresdk_user |
| Flask | g.claims |
| Django | request.coresdk_claims |
What's in the claims
| Field | Type | Source |
|---|---|---|
sub | string | JWT sub claim (user ID) |
email | string | JWT email claim |
role | string | JWT role claim |
tenant_id | string | JWT tenant_id claim |
claims | dict | All raw JWT claims |
FastAPI: request.state.coresdk_user
from fastapi import FastAPI, Request
from coresdk import CoreSDKClient, SDKConfig
from coresdk.middleware.fastapi import CoreSDKMiddleware
_sdk = CoreSDKClient(SDKConfig.from_env())
app = FastAPI()
app.add_middleware(CoreSDKMiddleware, sdk=_sdk)
@app.get("/api/orders")
async def get_orders(request: Request):
user = request.state.coresdk_user
user_id = user.sub
email = user.email
tenant_id = user.tenant_id
role = user.role
# Access a raw claim not promoted to a named field
department = user.claims.get("department", "unknown")
return await db.fetch_orders(tenant_id=tenant_id, user_id=user_id)Flask: g.claims
from flask import Flask, g, jsonify
from coresdk import CoreSDKClient, SDKConfig
from coresdk.middleware.flask import CoreSDKFlask
_sdk = CoreSDKClient(SDKConfig.from_env())
app = Flask(__name__)
CoreSDKFlask(_sdk, app)
@app.route("/api/orders")
def get_orders():
claims = g.claims
user_id = claims["sub"]
email = claims["email"]
tenant_id = claims["tenant_id"]
role = claims["role"]
# Access any raw claim
department = claims.get("department", "unknown")
orders = db.fetch_orders(tenant_id=tenant_id, user_id=user_id)
return jsonify(orders)Django: request.coresdk_claims
# settings.py
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"coresdk.django.CoreSDKMiddleware",
# ...
]
# views.py
from django.http import JsonResponse
def get_orders(request):
claims = request.coresdk_claims
user_id = claims["sub"]
email = claims["email"]
tenant_id = claims["tenant_id"]
role = claims["role"]
department = claims.get("department", "unknown")
orders = list(Order.objects.filter(tenant_id=tenant_id))
return JsonResponse({"orders": orders})Rust: context via Tower state
In Rust/axum, authenticated identity is injected via Tower middleware extensions:
use axum::{extract::Extension, response::Json};
use coresdk_engine::auth::AuthDecision;
async fn get_orders(Extension(decision): Extension<AuthDecision>) -> Json<serde_json::Value> {
let user_id = &decision.claims["sub"];
let tenant_id = &decision.claims["tenant_id"];
let role = &decision.claims["role"];
// fetch orders ...
Json(serde_json::json!({ "orders": [] }))
}Propagating context across service calls
When calling a downstream service, forward the trace context and tenant identity so the downstream can correlate logs and enforce its own policies.
FastAPI
import httpx
from fastapi import Request
@app.get("/api/orders-with-inventory")
async def get_orders_with_inventory(request: Request):
user = request.state.coresdk_user
# Forward traceparent and CoreSDK identity headers
headers = {
"traceparent": request.headers.get("traceparent", ""),
"X-CoreSDK-Tenant-Id": user.tenant_id,
"X-CoreSDK-User-Id": user.sub,
}
async with httpx.AsyncClient() as client:
inventory = await client.get(
"https://inventory.internal/items",
headers=headers,
)
return {"inventory": inventory.json()}Flask
import requests
from flask import g, request as flask_request
@app.route("/api/orders-with-inventory")
def get_orders_with_inventory():
claims = g.claims
headers = {
"traceparent": flask_request.headers.get("traceparent", ""),
"X-CoreSDK-Tenant-Id": claims["tenant_id"],
"X-CoreSDK-User-Id": claims["sub"],
}
inventory = requests.get(
"https://inventory.internal/items",
headers=headers,
).json()
return jsonify({"inventory": inventory})The receiving service must run CoreSDK (or an OTel-compatible collector) to extract and use these headers.
Require role helper
Use a FastAPI dependency to enforce roles directly in the route signature:
from fastapi import Depends, HTTPException, Request
def require_role(required_role: str):
def _check(request: Request):
user = request.state.coresdk_user
if user.role != required_role:
raise HTTPException(status_code=403, detail="Insufficient role")
return user
return _check
@app.get("/admin/users")
async def list_users(user=Depends(require_role("admin"))):
return await db.list_users()Next steps
- Middleware Pipeline — where and how context is populated
- Error Handling — what happens when auth or policy fails before context is set
- Intent Annotations — attaching semantic labels to traced handlers
Middleware Pipeline
How CoreSDK intercepts requests in FastAPI, Flask, and Django. Real middleware classes, exclude_paths, and how to read authenticated claims in handlers.
Error Handling
CoreSDK error format (RFC 9457), ProblemDetailError, built-in error types for auth, policy, and tenant failures, mapping SDK errors to HTTP responses, and customizing error output.