> ## Documentation Index
> Fetch the complete documentation index at: https://docs.agno.com/llms.txt
> Use this file to discover all available pages before exploring further.

# JWT Middleware with Authorization Headers

> Complete AgentOS setup with JWT middleware for authentication and parameter injection using Authorization headers

This example demonstrates how to use JWT middleware with AgentOS for authentication and automatic parameter injection using Authorization headers.

## Code

```python jwt_middleware.py theme={null}
from datetime import UTC, datetime, timedelta

import jwt
from agno.agent import Agent
from agno.db.postgres import PostgresDb
from agno.models.openai import OpenAIResponses
from agno.os import AgentOS
from agno.os.middleware import JWTMiddleware

# JWT Secret (use environment variable in production)
JWT_SECRET = "a-string-secret-at-least-256-bits-long"

# Setup database
db = PostgresDb(db_url="postgresql+psycopg://ai:ai@localhost:5532/ai")


# Define a tool that uses dependencies claims
def get_user_details(dependencies: dict):
    """
    Get the current user's details.
    """
    return {
        "name": dependencies.get("name"),
        "email": dependencies.get("email"),
        "roles": dependencies.get("roles"),
    }


# Create agent
research_agent = Agent(
    id="user-agent",
    model=OpenAIResponses(id="gpt-5.2"),
    db=db,
    tools=[get_user_details],
    instructions="You are a user agent that can get user details if the user asks for them.",
)


agent_os = AgentOS(
    description="JWT Protected AgentOS",
    agents=[research_agent],
)

# Get the final app
app = agent_os.get_app()

# Add JWT middleware to the app
# This middleware will automatically inject JWT values into request.state and is used in the relevant endpoints.
app.add_middleware(
    JWTMiddleware,
    verification_keys=[JWT_SECRET], # or use JWT_VERIFICATION_KEY environment variable
    algorithm="HS256",
    user_id_claim="sub",  # Extract user_id from 'sub' claim
    session_id_claim="session_id",  # Extract session_id from 'session_id' claim
    dependencies_claims=["name", "email", "roles"],
    # In this example, we want this middleware to demonstrate parameter injection, not token validation.
    # In production scenarios, you will probably also want token validation. Be careful setting this to False.
    validate=False,
)

if __name__ == "__main__":
    """
    Run your AgentOS with JWT parameter injection.
    
    Test by calling /agents/user-agent/runs with a message: "What do you know about me?"
    """
    # Test token with user_id and session_id:
    payload = {
        "sub": "user_123",  # This will be injected as user_id parameter
        "session_id": "demo_session_456",  # This will be injected as session_id parameter
        "exp": datetime.now(UTC) + timedelta(hours=24),
        "iat": datetime.now(UTC),
        # Dependency claims
        "name": "John Doe",
        "email": "john.doe@example.com",
        "roles": ["admin", "user"],
    }
    token = jwt.encode(payload, JWT_SECRET, algorithm="HS256")
    print("Test token:")
    print(token)
    agent_os.serve(app="jwt_middleware:app", port=7777, reload=True)
```

## Usage

<Steps>
  <Snippet file="create-venv-step.mdx" />

  <Step title="Set Environment Variables">
    ```bash theme={null}
    export OPENAI_API_KEY=your_openai_api_key
    ```
  </Step>

  <Step title="Install dependencies">
    ```bash theme={null}
    uv pip install -U agno openai pyjwt "fastapi[standard]" uvicorn sqlalchemy pgvector psycopg
    ```
  </Step>

  <Step title="Setup PostgreSQL Database">
    ```bash theme={null}
    # Using Docker
    docker run -d \
      --name agno-postgres \
      -e POSTGRES_DB=ai \
      -e POSTGRES_USER=ai \
      -e POSTGRES_PASSWORD=ai \
      -p 5532:5432 \
      pgvector/pgvector:pg17
    ```
  </Step>

  <Step title="Run Example">
    ```bash theme={null}
    python jwt_middleware.py
    ```

    The server will start and print a test JWT token to the console.
  </Step>

  <Step title="Test JWT Authentication">
    **Test with the generated token:**

    ```bash theme={null}
    # Use the token printed in the console
    export TOKEN="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."

    curl --location 'http://localhost:7777/agents/user-agent/runs' \
        --header 'Content-Type: application/x-www-form-urlencoded' \
        --header 'Authorization: Bearer $TOKEN' \
        --data-urlencode 'message=What do you know about me?'
    ```

    **Test without token (should still work validate=False):**

    ```bash theme={null}
    curl --location 'http://localhost:7777/agents/user-agent/runs' \
        --header 'Content-Type: application/x-www-form-urlencoded' \
        --data-urlencode 'message=What do you know about me?'
    ```

    **Check the AgentOS API docs:**
    Visit [http://localhost:7777/docs](http://localhost:7777/docs) to see all available endpoints.
  </Step>
</Steps>

## How It Works

1. **JWT Generation**: The example creates a test JWT token with user claims
2. **Middleware Setup**: JWT middleware extracts claims from the `Authorization: Bearer <token>` header
3. **Parameter Injection**: The middleware automatically injects:
   * `user_id` from the `sub` claim
   * `session_id` from the `session_id` claim
   * `dependencies` dict with name, email, and roles
4. **Agent Tools**: The agent can access user details through the injected dependencies

## Next Steps

* [JWT Middleware with Cookies](/agent-os/usage/middleware/jwt-cookies)
* [Custom FastAPI with JWT](/agent-os/usage/middleware/custom-fastapi-jwt)
* [JWT Middleware Documentation](/agent-os/middleware/jwt)
