Skip to main content
JWT Authentication Middleware with optional RBAC (Role-Based Access Control) for AgentOS.

Import

from agno.os.middleware import JWTMiddleware
from agno.os.middleware.jwt import TokenSource

JWTMiddleware Parameters

ParameterTypeDefaultDescription
verification_keysOptional[List[str]]JWT_VERIFICATION_KEY env varList of keys for JWT verification. For RS256, use public keys. For HS256, use shared secrets. Each key is tried in order until one succeeds - useful for accepting tokens from multiple issuers.
jwks_fileOptional[str]JWT_JWKS_FILE env varPath to a static JWKS (JSON Web Key Set) file. Keys are looked up by kid (key ID) from the JWT header.
secret_keyOptional[str]None(Deprecated) Use verification_keys instead.
algorithmstr"RS256"JWT algorithm (RS256, HS256, ES256, etc.)
validateboolTrueWhether to validate JWT tokens
authorizationOptional[bool]NoneEnable RBAC scope checking
token_sourceTokenSourceTokenSource.HEADERWhere to extract JWT token from
token_header_keystr"Authorization"Header key for Authorization
cookie_namestr"access_token"Cookie name for JWT token
scopes_claimstr"scopes"JWT claim name for scopes
user_id_claimstr"sub"JWT claim name for user ID
session_id_claimstr"session_id"JWT claim name for session ID
audience_claimstr"aud"JWT claim name for audience/OS ID
verify_audienceboolFalseVerify aud claim matches AgentOS ID
dependencies_claimsOptional[List[str]]NoneClaims to extract for dependencies parameter
session_state_claimsOptional[List[str]]NoneClaims to extract for session_state parameter
scope_mappingsOptional[Dict[str, List[str]]]NoneCustom route-to-scope mappings (additive to defaults)
excluded_route_pathsOptional[List[str]]See belowRoutes to skip JWT/RBAC checks
admin_scopeOptional[str]"agent_os:admin"Scope that grants full admin access

TokenSource Enum

ValueDescription
TokenSource.HEADERExtract JWT from Authorization: Bearer <token> header
TokenSource.COOKIEExtract JWT from HTTP cookie
TokenSource.BOTHTry header first, then cookie as fallback

Default Excluded Routes

[
    "/",
    "/health",
    "/docs",
    "/redoc",
    "/openapi.json",
    "/docs/oauth2-redirect",
]

Usage

Basic JWT Validation

from agno.os import AgentOS
from agno.os.middleware import JWTMiddleware

agent_os = AgentOS(agents=[my_agent])
app = agent_os.get_app()

app.add_middleware(
    JWTMiddleware,
    verification_keys=["your-jwt-key"],
    algorithm="RS256",
    validate=True,
)

JWT with RBAC Authorization

app.add_middleware(
    JWTMiddleware,
    verification_keys=["your-jwt-key"],
    algorithm="RS256",
    authorization=True,
    verify_audience=True,
)

JWT from Cookies

from agno.os.middleware.jwt import TokenSource

app.add_middleware(
    JWTMiddleware,
    verification_keys=["your-jwt-key"],
    token_source=TokenSource.COOKIE,
    cookie_name="access_token",
)

Parameter Injection

app.add_middleware(
    JWTMiddleware,
    verification_keys=["your-jwt-key"],
    user_id_claim="sub",
    session_id_claim="session_id",
    dependencies_claims=["name", "email", "roles"],
    session_state_claims=["preferences"],
)

Using JWKS File

# Using a static JWKS file (e.g., from your identity provider)
app.add_middleware(
    JWTMiddleware,
    jwks_file="/path/to/jwks.json",
    algorithm="RS256",
    authorization=True,
)
The JWKS file should have the standard format:
{
  "keys": [
    {
      "kty": "RSA",
      "kid": "my-key-id",
      "use": "sig",
      "alg": "RS256",
      "n": "0vx7agoebGc...",
      "e": "AQAB"
    }
  ]
}

Custom Scope Mappings

app.add_middleware(
    JWTMiddleware,
    verification_keys=["your-jwt-key"],
    authorization=True,
    scope_mappings={
        # Override default scope
        "GET /agents": ["custom:agents:list"],
        # Add new endpoint
        "POST /custom/action": ["custom:write"],
        # Allow without scopes
        "GET /public": [],
    }
)

Request State

After processing, the middleware stores the following in request.state:
AttributeTypeDescription
authenticatedboolWhether the user is authenticated
user_idOptional[str]User ID from token claims
session_idOptional[str]Session ID from token claims
scopesList[str]User’s permission scopes
audienceOptional[str]Audience claim value
tokenstrThe raw JWT token
authorization_enabledboolWhether RBAC is enabled
dependenciesDict[str, Any]Extracted dependencies claims
session_stateDict[str, Any]Extracted session state claims
accessible_resource_idsSet[str]Resource IDs user can access (for listing endpoints)

Error Responses

Status CodeDescription
401 UnauthorizedMissing or invalid JWT token
401 UnauthorizedToken has expired
401 UnauthorizedInvalid audience (token not for this AgentOS)
403 ForbiddenInsufficient scopes for the requested operation

See Also