Skip to main content

OAuth with the helper library

diagrid-identity is a thin, framework-agnostic library that hands your agent — or any Catalyst-fronted service — the verified identity of the user who invoked it. It works with any Python agent framework because it only reads a header the Catalyst data plane has already populated. For where this fits in the wider flow, see the Enterprise identity overview.

The library is Python-only. Other SDKs are not yet available.

API surface

The function names, decorator signatures, and VerifiedUser fields on this page are the shipping shapes. The exact fields on OAuthConfig ship with the reference implementation — everywhere below shows OAuthConfig(...) as a placeholder.

The header contract

The caller presents its upstream IdP token in X-Diagrid-User-Token. Catalyst verifies that token, exchanges it for a Catalyst-issued user token, and overwrites the same header before the request reaches your agent:

X-Diagrid-User-Token: Bearer <catalyst-user-jwt>

So the header your agent reads always carries the post-exchange Catalyst token — your code never touches the raw upstream credential. The helper library reads this header, validates the Catalyst token, and returns a VerifiedUser.

Install

pip install diagrid-identity

Core types (OAuthConfig, VerifiedUser, claims_from_request) live in diagrid.identity. Framework-specific mount helpers live in per-framework submodules — diagrid.identity.asgi for FastAPI/Starlette middleware, diagrid.identity.fastapi for the FastAPI dependency, diagrid.identity.flask for the Flask decorator.

from diagrid.identity import VerifiedUser

Configure

Every attachment pattern below takes an OAuthConfig instance. Construct it once at startup and pass it into the middleware, dependency, or decorator you attach:

from diagrid.identity import OAuthConfig

# Fields ship with the reference implementation. Populate with the identity
# policy your Catalyst operator gave you (required scopes, allowed audiences,
# and so on).
oauth = OAuthConfig(...)

The oauth variable in every code sample below refers to this object.

FastAPI

FastAPI supports two patterns. Add the middleware to enforce identity on every route, or use the dependency to require it on individual routes.

Middleware

OAuthMiddleware verifies the token on every request and rejects unauthenticated calls before they reach your handlers. It attaches the VerifiedUser to request.state.user for handlers to read:

from fastapi import FastAPI, Request
from diagrid.identity import VerifiedUser
from diagrid.identity.asgi import OAuthMiddleware

app = FastAPI()
app.add_middleware(OAuthMiddleware, config=oauth)

@app.post("/invoke")
async def invoke(request: Request):
user: VerifiedUser = request.state.user
return {"subject": user.subject}

Dependency

require_user is a dependency that both enforces identity and injects the VerifiedUser into the route that needs it:

from fastapi import Depends, FastAPI
from diagrid.identity import VerifiedUser
from diagrid.identity.fastapi import require_user

app = FastAPI()

@app.post("/invoke")
async def invoke(user: VerifiedUser = Depends(require_user(oauth))):
return {"subject": user.subject}

Flask

Decorate a route with require_user to enforce identity and receive the VerifiedUser:

from flask import Flask
from diagrid.identity import VerifiedUser
from diagrid.identity.flask import require_user

app = Flask(__name__)

@app.post("/invoke")
@require_user(oauth)
def invoke(user: VerifiedUser):
return {"subject": user.subject}

Plain function

When you are not using a web framework — inside a worker, a script, or a custom server — call claims_from_request directly. It accepts any request-like object that exposes a headers mapping (Starlette, Flask, http.server, and most HTTP client libraries all qualify):

from diagrid.identity import claims_from_request, VerifiedUser

def handle(request) -> dict:
user: VerifiedUser = claims_from_request(request, config=oauth)
return {"subject": user.subject}

If your caller only has the raw token string (for example, off a queue message), pull it out yourself and pass through the same helper library by constructing a minimal request-like object with the X-Diagrid-User-Token header set.

What VerifiedUser gives you

A VerifiedUser is the trusted, decoded identity of the caller. Use it to make authorization decisions or to attribute actions to a user.

FieldDescription
subjectThe user's stable subject identifier (sub claim).
tenantThe tenant the user belongs to.
scopesThe scopes granted to the user.
claimsThe full set of decoded token claims.
issuer_idThe identifier of the federation that issued and validated the token.

Rejection semantics

The library rejects invalid requests with a standard HTTP status determined by the rejection code:

  • 401 Unauthorized — the caller failed authentication. The token is missing, malformed, expired, or its signature or issuer does not validate.
  • 403 Forbidden — the caller authenticated successfully but is not authorized. The verified user lacks a scope your policy requires.

Each rejection carries a machine-readable code. See Troubleshooting for the full list and the operator debugging path for each.

What's next