---
title: "Authentication Middleware"
description: "JWT and API key authentication middleware"
keywords: [authentication, middleware, jwt, api keys, security]
---

# Authentication Middleware

Authentication middleware for validating JWT tokens and API keys.

## JWT Authentication

### Token Validation

```python
from fastapi import Depends, HTTPException, status
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from jose import jwt, JWTError

security = HTTPBearer()

async def get_current_user(
    credentials: HTTPAuthorizationCredentials = Depends(security)
) -> dict:
    """Validate JWT token and return user."""
    token = credentials.credentials
    
    try:
        payload = jwt.decode(
            token,
            SECRET_KEY,
            algorithms=["HS256"]
        )
        user_id = payload.get("sub")
        if user_id is None:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="Invalid token"
            )
        return {"user_id": user_id, "email": payload.get("email")}
    except JWTError:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid token"
        )
```

## API Key Authentication

### API Key Validation

```python
from fastapi import Header, HTTPException

async def verify_api_key(
    x_api_key: str = Header(..., alias="X-API-Key")
) -> dict:
    """Validate API key."""
    from tracertm.auth import APIKeyManager
    
    key_manager = APIKeyManager()
    validation = key_manager.validate(x_api_key)
    
    if not validation["valid"]:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid API key"
        )
    
    return {
        "api_key": x_api_key,
        "scopes": validation.get("scopes", [])
    }
```

## Optional Authentication

### Public or Authenticated

```python
from typing import Optional

async def get_optional_user(
    credentials: Optional[HTTPAuthorizationCredentials] = Depends(
        HTTPBearer(auto_error=False)
    )
) -> Optional[dict]:
    """Get user if authenticated, None otherwise."""
    if not credentials:
        return None
    
    try:
        payload = jwt.decode(credentials.credentials, SECRET_KEY)
        return {"user_id": payload.get("sub")}
    except JWTError:
        return None
```

## Scope Checking

### Require Scopes

```python
from fastapi import Depends, HTTPException

def require_scope(required_scope: str):
    """Dependency factory for scope checking."""
    async def check_scope(
        user: dict = Depends(get_current_user)
    ) -> dict:
        scopes = user.get("scopes", [])
        if required_scope not in scopes:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail=f"Missing scope: {required_scope}"
            )
        return user
    return check_scope

# Usage
@router.post("/items", dependencies=[Depends(require_scope("items:write"))])
async def create_item(request: CreateItemRequest):
    """Create item (requires items:write scope)."""
    pass
```

## Related Documentation

- [Middleware](./02-middleware) - Middleware overview
- [Authentication API](/docs/api-reference/authentication) - Authentication guide
