Auth Middleware
Configure AuthMiddleware for JWT validation, claim injection, and RBAC across REST, MCP, and WebSocket connections.
AuthMiddleware is the AgentOS authentication layer. It validates JWTs, service-account tokens (agno_pat_...), and the OS security key. For JWTs it extracts tokens from Authorization headers or cookies, validates them, and injects user_id, session_id, and custom claims into your endpoints. This page covers the JWT configuration. For the other two credential types, see Service Accounts and the security key.
The class was renamed from JWTMiddleware in v2.7. JWTMiddleware remains as an alias, so existing app.add_middleware(JWTMiddleware, ...) setups keep working.
The middleware provides three main features:
- Token Validation: Validates JWT tokens and handles authentication
- Parameter Injection: Automatically injects user_id, session_id, and custom claims into endpoint parameters
- RBAC Authorization: Validates scopes against required permissions for each endpoint
The examples on this page are alternative middleware configuration fragments. Create app = agent_os.get_app() first, as in the middleware quickstart, and add your chosen middleware before serving. Replace verification-key placeholders with a real key for the selected algorithm; the quickstart includes local token generation. Do not stack the alternatives together.
from agno.os.middleware.jwt import AuthMiddleware
app.add_middleware(
AuthMiddleware,
verification_keys=["your-jwt-verification-key"], # or use JWT_VERIFICATION_KEY environment variable
algorithm="RS256", # RS256 for asymmetric keys, HS256 for symmetric
user_id_claim="sub", # Extract user_id from 'sub' claim
session_id_claim="session_id", # Extract session_id from claim
dependencies_claims=["name", "email", "roles"], # Additional claims
validate=True, # Enable token validation
authorization=True, # Enable RBAC scope checking
verify_audience=True, # Verify `aud` claim matches AgentOS ID
)Coverage Across Surfaces
JWT and OS security-key deployments share the parent-app authentication layer across the runtime surfaces below. An MCP OAuth configuration uses its configured OAuth authentication path; see MCP security. Route scopes still determine which operations a credential can call.
| Surface | How it is covered |
|---|---|
| REST routes | Requests pass through the middleware directly |
Mounted /mcp app | In JWT/security-key mode, parent middleware validates requests before mount dispatch; MCP OAuth has its own authentication path |
| WebSockets | The middleware publishes its validator, audience, admin scope, and user-isolation settings to app.state; WebSocket handshakes validate against the same configuration |
Credential Dispatch
The middleware resolves each bearer credential in order:
- Tokens with the
agno_pat_prefix authenticate as service accounts against the AgentOS database. This happens before JWT validation. Service-account scopes are enforced even whenauthorization=False, since they are ACL data owned by your AgentOS instance. - The internal service token, used by the scheduler executor to run scheduled jobs.
- The OS security key, when no JWT source is configured.
- Anything else is validated as a JWT.
Token Sources
The middleware supports three token sources:
Extract JWT from Authorization: Bearer <token> header.
from agno.os.middleware.jwt import AuthMiddleware, TokenSource
app.add_middleware(
AuthMiddleware,
verification_keys=["your-key"],
token_source=TokenSource.HEADER, # Default
)Extract JWT from HTTP-only cookies for web applications.
from agno.os.middleware.jwt import AuthMiddleware, TokenSource
app.add_middleware(
AuthMiddleware,
verification_keys=["your-key"],
token_source=TokenSource.COOKIE,
cookie_name="access_token", # Default
)Try both header and cookie (header takes precedence).
from agno.os.middleware.jwt import AuthMiddleware, TokenSource
app.add_middleware(
AuthMiddleware,
verification_keys=["your-key"],
token_source=TokenSource.BOTH,
cookie_name="access_token", # Default
token_header_key="Authorization", # Default
)JWKS File Support
For environments using RSA keys managed via JWKS (JSON Web Key Set), you can point to a static JWKS file instead of providing raw public keys:
app.add_middleware(
AuthMiddleware,
jwks_file="/path/to/jwks.json",
algorithm="RS256",
authorization=True,
)The middleware will:
- Load public keys from the JWKS file at startup
- Match incoming tokens by their
kid(key ID) header claim - Validate signatures using the appropriate key
JWKS File Format
The JWKS file should follow the standard format:
{
"keys": [
{
"kty": "RSA",
"kid": "my-key-id",
"use": "sig",
"alg": "RS256",
"n": "0vx7agoebGc...",
"e": "AQAB"
}
]
}Environment Variable
You can also set the JWKS file path via environment variable:
export JWT_JWKS_FILE="/path/to/jwks.json"JWKS keys are tried first (matched by kid). If no matching key is found, the middleware falls back to verification_keys if provided.
Parameter Injection
The middleware automatically injects JWT claims into AgentOS endpoints. The following parameters are extracted from tokens and injected into requests:
user_id- User identifier from token claimssession_id- Session identifier from token claimsdependencies- Custom claims for agent toolssession_state- Custom claims for session management
For example, the /agents/{agent_id}/runs endpoint automatically uses user_id, session_id, dependencies, and session_state from the JWT token when available.
This is useful for:
- Automatically using the
user_idandsession_idfrom your JWT token when running an agent - Automatically filtering sessions retrieved from
/sessionsendpoints byuser_id(where applicable) - Automatically injecting
dependenciesfrom claims in your JWT token into the agent run, which then is available on tools called by your agent
See the full example.
Security Features
Use strong verification keys, store them securely (not in code), and enable validation in production.
Token Validation: When validate=True, the middleware:
- Verifies JWT signature using the verification key
- Checks token expiration (
expclaim) - Returns 401 errors for invalid/expired tokens
Audience Verification: When verify_audience=True, the middleware:
- If
audienceis provided, it will validate the token's audience claim matches the expected audience claim - If
audienceis not provided, it will validate the token's audience claim matches the AgentOS ID - Optionally set the
audience_claimto validate a custom audience claim - Returns 401 for tokens with mismatched audience
HTTP-Only Cookies: When using cookies:
- Set
httponly=Trueto prevent JavaScript access (XSS protection) - Set
secure=Truefor HTTPS-only transmission - Set
samesite="strict"for CSRF protection
Local Development
Do not use validate=False in production. The middleware decodes claims without verifying the JWT signature.
Skip signature verification in local development, or when an upstream API gateway already validates JWTs.
from agno.os.middleware.jwt import AuthMiddleware
app.add_middleware(
AuthMiddleware,
validate=False,
)No verification key is required. Claims are extracted from the token but not authenticated.
RBAC Authorization
Enable Role-Based Access Control (RBAC) to validate JWT scopes against required permissions:
app.add_middleware(
AuthMiddleware,
verification_keys=["your-jwt-key"],
algorithm="RS256",
authorization=True, # Enable RBAC
verify_audience=True, # Verify aud matches AgentOS ID
)When authorization=True, the middleware:
- Checks the
scopesclaim in JWT tokens - Validates scopes against required permissions for each endpoint
- Returns 403 Forbidden for insufficient permissions
Scope Format
| Format | Example | Description |
|---|---|---|
resource:action | agents:read | Access all resources |
resource:<id>:action | agents:my-agent:run | Access specific resource |
resource:*:action | agents:*:run | Wildcard access |
agent_os:admin | agent_os:admin | Full admin access |
Custom Scope Mappings
Override or extend default scope mappings:
app.add_middleware(
AuthMiddleware,
verification_keys=["your-key"],
authorization=True,
scope_mappings={
# Override default
"GET /agents": ["custom:agents:list"],
# Add new endpoint
"POST /custom/action": ["custom:write"],
# Allow without scopes
"GET /public": [],
}
)For all available scopes and default endpoint mappings, see Scopes.
User Isolation
RBAC controls which endpoints a caller can hit. User isolation controls which rows they can see and mutate. The two are independent toggles.
app.add_middleware(
AuthMiddleware,
verification_keys=["your-jwt-key"],
authorization=True,
user_isolation=True,
)When user_isolation=True, non-admin callers are scoped to the user_id from the JWT sub claim across sessions, memories, traces, approvals, and other user-owned AgentOS resources. Callers holding admin_scope bypass isolation. See Per-User Data Isolation for the full behavior.
Excluded Routes
These routes skip JWT and RBAC checks by default:
["/", "/health", "/info", "/docs", "/redoc", "/openapi.json", "/docs/oauth2-redirect"]Override them with excluded_route_paths:
app.add_middleware(
AuthMiddleware,
verification_keys=["your-key"],
excluded_route_paths=[
"/health",
"/auth/login",
"/auth/register",
"/public/*", # Wildcards supported
]
)excluded_route_paths replaces the defaults. Re-include any default routes you want to keep.
Configuration Options
See the AuthMiddleware reference for the complete list of configuration options.
Authentication Options
| Parameter | Description | Default |
|---|---|---|
verification_keys | List of keys for JWT verification. For RS256, use public keys. For HS256, use shared secrets. Each key is tried in order until one succeeds. | JWT_VERIFICATION_KEY env var |
jwks_file | Path to a static JWKS file containing public keys. Keys are matched by kid from the JWT header. | JWT_JWKS_FILE env var |
secret_key | (Deprecated) Use verification_keys instead. | - |
algorithm | JWT algorithm (RS256, HS256, ES256, etc.) | "RS256" |
validate | Enable token validation | True |
security_key | Static OS security key credential. Only consulted when no JWT source is configured. | None |
service_account_verifier | Verifier for agno_pat_ service-account tokens. Falls back to app.state.service_account_verifier, which AgentOS sets whenever a database is configured. | None |
Constructing the middleware requires at least one credential source: a JWT key source (verification_keys, jwks_file, or their environment variables), validate=False, a security_key, or a service_account_verifier. authorization=True also requires a JWT source (verification keys, a JWKS file, or validate=False for unverified dev mode).
Token Source Options
| Parameter | Description | Default |
|---|---|---|
token_source | Where to extract token from: HEADER, COOKIE, or BOTH | TokenSource.HEADER |
token_header_key | Header key for Authorization (when using HEADER or BOTH) | "Authorization" |
cookie_name | Cookie name (when using COOKIE or BOTH) | "access_token" |
Claim Extraction Options
| Parameter | Description | Default |
|---|---|---|
user_id_claim | JWT claim for user ID | "sub" |
session_id_claim | JWT claim for session ID | "session_id" |
scopes_claim | JWT claim for scopes | "scopes" |
audience_claim | JWT claim for audience/OS ID | "aud" |
dependencies_claims | List of claims to extract for dependencies parameter | None |
session_state_claims | List of claims to extract for session_state parameter | None |
Authorization Options (RBAC)
| Parameter | Description | Default |
|---|---|---|
authorization | Enable RBAC scope checking. Auto-enabled when scope_mappings is provided. | None |
verify_audience | Verify aud claim matches AgentOS ID | False |
audience | Expected audience claim to validate against the token's audience claim | AgentOS ID |
user_isolation | Opt in to per-user isolation for user-owned data and resources throughout AgentOS. When True, AgentOS uses the JWT sub claim as the user_id for every non-admin caller: user-owned reads are scoped to it and user-owned writes are coerced to it. Callers holding admin_scope bypass isolation. | False |
scope_mappings | Custom route-to-scope mappings (additive to defaults) | None |
admin_scope | Scope that grants full admin access | "agent_os:admin" |
excluded_route_paths | Routes to skip JWT/RBAC checks | See Excluded Routes |
Examples
JWT with Headers
JWT authentication using Authorization headers for API clients.
JWT with Cookies
JWT authentication using HTTP-only cookies for web applications.
Custom FastAPI + JWT
Custom FastAPI app with JWT middleware and AgentOS integration.
Authorization
Scopes, roles, and access control configuration.
AuthMiddleware Reference
Complete auth middleware class reference.