> ## 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

> Secure your AgentOS application with JWT token validation and RBAC

<Badge icon="code-branch" color="orange">
  <Tooltip tip="Introduced in v2.1.0" cta="View release notes" href="https://github.com/agno-agi/agno/releases/tag/v2.1.0">v2.1.0</Tooltip>
</Badge>

Authenticate and authorize requests to your AgentOS application using JWT tokens. The middleware extracts tokens from Authorization headers or cookies, validates them, and automatically injects user\_id, session\_id, and custom claims into your endpoints.

The JWT middleware provides three main features:

1. **Token Validation**: Validates JWT tokens and handles authentication
2. **Parameter Injection**: Automatically injects user\_id, session\_id, and custom claims into endpoint parameters
3. **RBAC Authorization**: Validates scopes against required permissions for each endpoint

```python jwt_middleware_setup.py theme={null}
from agno.os.middleware import JWTMiddleware
from agno.os.middleware.jwt import TokenSource

app.add_middleware(
    JWTMiddleware,
    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
)
```

## Token Sources

The middleware supports three token sources:

<Tabs>
  <Tab title="Authorization Header">
    Extract JWT from `Authorization: Bearer <token>` header.

    ```python theme={null}
    from agno.os.middleware.jwt import TokenSource

    app.add_middleware(
        JWTMiddleware,
        verification_keys=["your-key"],
        token_source=TokenSource.HEADER,  # Default
    )
    ```
  </Tab>

  <Tab title="HTTP-Only Cookies">
    Extract JWT from HTTP-only cookies for web applications.

    ```python theme={null}
    app.add_middleware(
        JWTMiddleware,
        verification_keys=["your-key"],
        token_source=TokenSource.COOKIE,
        cookie_name="access_token",  # Default
    )
    ```
  </Tab>

  <Tab title="Both Sources">
    Try both header and cookie (header takes precedence).

    ```python theme={null}
    app.add_middleware(
        JWTMiddleware,
        verification_keys=["your-key"],
        token_source=TokenSource.BOTH,
        cookie_name="access_token",  # Default
        token_header_key="Authorization",  # Default
    )
    ```
  </Tab>
</Tabs>

## 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:

```python jwks_file_setup.py theme={null}
app.add_middleware(
    JWTMiddleware,
    jwks_file="/path/to/jwks.json",
    algorithm="RS256",
    authorization=True,
)
```

The middleware will:

1. Load public keys from the JWKS file at startup
2. Match incoming tokens by their `kid` (key ID) header claim
3. Validate signatures using the appropriate key

### JWKS File Format

The JWKS file should follow the standard format:

```json theme={null}
{
  "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:

```bash theme={null}
export JWT_JWKS_FILE="/path/to/jwks.json"
```

<Note>
  JWKS keys are tried first (matched by `kid`). If no matching key is found, the middleware falls back to `verification_keys` if provided.
</Note>

## 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 claims
* `session_id` - Session identifier from token claims
* `dependencies` - Custom claims for agent tools
* `session_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_id` and `session_id` from your JWT token when running an agent
* Automatically filtering sessions retrieved from `/sessions` endpoints by `user_id` (where applicable)
* Automatically injecting `dependencies` from claims in your JWT token into the agent run, which then is available on tools called by your agent

View the [full example](/agent-os/usage/middleware/jwt-middleware) for more details.

## Security Features

<Note>
  Use strong verification keys, store them securely (not in code), and enable validation in production.
</Note>

**Token Validation**: When `validate=True`, the middleware:

* Verifies JWT signature using the verification key
* Checks token expiration (`exp` claim)
* Returns 401 errors for invalid/expired tokens

**Audience Verification**: When `verify_audience=True`, the middleware:

* If `audience` is provided, it will validate the token's audience claim matches the expected audience claim
* If `audience` is not provided, it will validate the token's audience claim matches the AgentOS ID
* Optionally set the `audience_claim` to validate a custom audience claim
* Returns 401 for tokens with mismatched audience

<Tip>
  **HTTP-Only Cookies**: When using cookies:

  * Set `httponly=True` to prevent JavaScript access (XSS protection)
  * Set `secure=True` for HTTPS-only transmission
  * Set `samesite="strict"` for CSRF protection
</Tip>

## RBAC Authorization

Enable Role-Based Access Control (RBAC) to validate JWT scopes against required permissions:

```python jwt_with_rbac.py theme={null}
app.add_middleware(
    JWTMiddleware,
    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 `scopes` claim 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:

```python custom_scope_mappings.py theme={null}
app.add_middleware(
    JWTMiddleware,
    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": [],
    }
)
```

<Tip>
  For detailed RBAC documentation including all available scopes and default mappings, see [RBAC Documentation](/agent-os/security/rbac).
</Tip>

## Excluded Routes

Skip middleware for specific routes:

```python jwt_excluded_routes.py theme={null}
app.add_middleware(
    JWTMiddleware,
    verification_keys=["your-key"],
    excluded_route_paths=[
        "/health",
        "/auth/login", 
        "/auth/register",
        "/public/*",  # Wildcards supported
    ]
)
```

## Configuration Options

See the [JWTMiddleware Reference](/reference/agent-os/jwt-middleware) 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`                         |

### 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  | `[]`           |
| `session_state_claims` | List of claims to extract for `session_state` parameter | `[]`           |

### Authorization Options (RBAC)

| Parameter              | Description                                                            | Default            |
| ---------------------- | ---------------------------------------------------------------------- | ------------------ |
| `authorization`        | Enable RBAC scope checking                                             | `False`            |
| `verify_audience`      | Verify `aud` claim matches AgentOS ID                                  | `False`            |
| `audience`             | Expected audience claim to validate against the token's audience claim | `AgentOS ID`       |
| `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 below          |

### Examples

<CardGroup cols={2}>
  <Card title="JWT with Headers" icon="shield" href="/agent-os/usage/middleware/jwt-middleware">
    JWT authentication using Authorization headers for API clients.
  </Card>

  <Card title="JWT with Cookies" icon="cookie" href="/agent-os/usage/middleware/jwt-cookies">
    JWT authentication using HTTP-only cookies for web applications.
  </Card>

  <Card title="Custom FastAPI + JWT" icon="code" href="/agent-os/usage/middleware/custom-fastapi-jwt">
    Custom FastAPI app with JWT middleware and AgentOS integration.
  </Card>

  <Card title="RBAC Documentation" icon="lock" href="/agent-os/security/rbac">
    Detailed RBAC scopes, permissions, and access control configuration.
  </Card>

  <Card title="JWTMiddleware Reference" icon="code" href="/reference/agent-os/jwt-middleware">
    Complete JWT middleware class reference.
  </Card>
</CardGroup>

### External Resources

<CardGroup cols={2}>
  <Card title="PyJWT Documentation" icon="book" href="https://pyjwt.readthedocs.io/">
    Official PyJWT library documentation for JWT encoding and decoding.
  </Card>
</CardGroup>
