Middleware Configuration
========================

This section covers advanced configuration options for Auth Middleware, including environment variables, custom providers, and performance tuning.

Basic Middleware Setup
---------------------

The Auth Middleware is added to your FastAPI or Starlette application using the standard middleware protocol:

.. code-block:: python

   from fastapi import FastAPI
   from auth_middleware import JwtAuthMiddleware
   from auth_middleware.providers.authn.cognito_provider import CognitoProvider

   app = FastAPI()

   # Add authentication middleware
   app.add_middleware(
       JwtAuthMiddleware,
       auth_provider=your_auth_provider,
       # Additional configuration options...
   )

Middleware Parameters
--------------------

The ``JwtAuthMiddleware`` accepts the following parameters:

.. list-table::
   :header-rows: 1
   :widths: 20 30 20 30

   * - Parameter
     - Description
     - Type
     - Default
   * - ``auth_provider``
     - The authentication provider instance
     - ``AuthProvider``
     - Required
   * - ``exclude_paths``
     - Paths to exclude from authentication
     - ``List[str]``
     - ``[]``
   * - ``include_paths``
     - Paths to include in authentication
     - ``List[str]``
     - ``["/*"]``
   * - ``auth_header_name``
     - HTTP header for authentication token
     - ``str``
     - ``"Authorization"``
   * - ``auth_scheme``
     - Authentication scheme
     - ``str``
     - ``"Bearer"``

Path Configuration
-----------------

Excluding Paths from Authentication
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

You can exclude specific paths from authentication requirements:

.. code-block:: python

   app.add_middleware(
       JwtAuthMiddleware,
       auth_provider=cognito_provider,
       exclude_paths=[
           "/",                    # Public homepage
           "/health",              # Health check endpoint
           "/docs",                # OpenAPI documentation
           "/openapi.json",        # OpenAPI schema
           "/metrics",             # Prometheus metrics
           "/static/*",            # Static files
           "/public/*",            # Public assets
       ]
   )

Including Specific Paths Only
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Alternatively, you can specify only the paths that require authentication:

.. code-block:: python

   app.add_middleware(
       JwtAuthMiddleware,
       auth_provider=cognito_provider,
       include_paths=[
           "/api/*",               # All API endpoints
           "/admin/*",             # Admin interface
           "/user/*",              # User-specific endpoints
       ]
   )

Pattern Matching
~~~~~~~~~~~~~~~

The middleware supports glob-style pattern matching:

* ``*`` matches any characters within a single path segment
* ``**`` matches any characters across multiple path segments
* ``?`` matches any single character

.. code-block:: python

   exclude_paths = [
       "/api/v*/public/*",     # Version-specific public endpoints
       "/health*",             # All health-related endpoints
       "/static/**",           # All static files recursively
   ]

Environment Variables
--------------------

Core Configuration
~~~~~~~~~~~~~~~~~

.. list-table::
   :header-rows: 1
   :widths: 30 40 30

   * - Environment Variable
     - Description
     - Default
   * - ``AUTH_MIDDLEWARE_DISABLED``
     - Disable all authentication
     - ``false``
   * - ``AUTH_MIDDLEWARE_LOG_LEVEL``
     - Logging level
     - ``INFO``
   * - ``AUTH_MIDDLEWARE_LOGGER_NAME``
     - Logger name
     - ``auth_middleware``

Provider-Specific Variables
~~~~~~~~~~~~~~~~~~~~~~~~~~

**AWS Cognito**:

.. code-block:: bash

   AWS_COGNITO_USER_POOL_ID=us-east-1_abcdef123
   AWS_COGNITO_USER_POOL_REGION=us-east-1
   TOKEN_VERIFICATION_DISABLED=false

**Azure Entra ID**:

.. code-block:: bash

   AZURE_TENANT_ID=your-tenant-id
   AZURE_CLIENT_ID=your-client-id
   AZURE_CLIENT_SECRET=your-client-secret

**JWT Provider**:

.. code-block:: bash

   JWT_SECRET_KEY=your-secret-key
   JWT_ALGORITHM=HS256
   JWT_ISSUER=your-issuer

Custom Authentication Providers
------------------------------

Creating a Custom Provider
~~~~~~~~~~~~~~~~~~~~~~~~~

You can create custom authentication providers by implementing the ``AuthProvider`` interface:

.. code-block:: python

   from abc import ABC, abstractmethod
   from typing import Optional
   from auth_middleware.types import User

   class CustomAuthProvider(ABC):
       @abstractmethod
       async def authenticate(self, token: str) -> Optional[User]:
           """Validate token and return user information."""
           pass

       @abstractmethod
       async def get_user_groups(self, user: User) -> List[str]:
           """Get user group memberships."""
           pass

Example Custom Provider
~~~~~~~~~~~~~~~~~~~~~~

.. code-block:: python

   import jwt
   from auth_middleware.types import User
   from auth_middleware.exceptions import AuthenticationError

   class ApiKeyProvider:
       def __init__(self, valid_api_keys: dict):
           self.valid_api_keys = valid_api_keys

       async def authenticate(self, token: str) -> Optional[User]:
           # Remove 'Bearer ' prefix if present
           if token.startswith('Bearer '):
               token = token[7:]

           # Look up API key
           user_info = self.valid_api_keys.get(token)
           if not user_info:
               raise AuthenticationError("Invalid API key")

           return User(
               id=user_info["id"],
               name=user_info["name"],
               email=user_info["email"],
               groups=user_info.get("groups", []),
               raw_token=token,
           )

       async def get_user_groups(self, user: User) -> List[str]:
           return user.groups

   # Usage
   api_keys = {
       "api_key_123": {
           "id": "user1",
           "name": "John Doe",
           "email": "john@example.com",
           "groups": ["user", "admin"]
       }
   }

   app.add_middleware(
       JwtAuthMiddleware,
       auth_provider=ApiKeyProvider(api_keys)
   )

Performance Configuration
------------------------

Connection Pooling
~~~~~~~~~~~~~~~~~

For providers that make HTTP requests (like Cognito), configure connection pooling:

.. code-block:: python

   import httpx
   from auth_middleware.providers.authn.cognito_provider import CognitoProvider

   # Custom HTTP client with connection pooling
   http_client = httpx.AsyncClient(
       timeout=30.0,
       limits=httpx.Limits(
           max_keepalive_connections=10,
           max_connections=100,
       )
   )

   # Note: This is conceptual - actual implementation may vary
   cognito_provider = CognitoProvider(
       settings=auth_settings,
       http_client=http_client,
   )

Caching Configuration
~~~~~~~~~~~~~~~~~~~

Token validation results can be cached to improve performance:

.. code-block:: python

   # This is conceptual - check actual provider documentation
   auth_settings = CognitoAuthzProviderSettings(
       user_pool_id="us-east-1_abcdef123",
       user_pool_region="us-east-1",
       cache_jwks=True,              # Cache JSON Web Key Sets
       cache_ttl=3600,               # Cache TTL in seconds
   )

Logging Configuration
--------------------

Detailed Logging
~~~~~~~~~~~~~~~

Enable detailed logging for debugging:

.. code-block:: python

   import logging

   # Configure auth middleware logging
   auth_logger = logging.getLogger("auth_middleware")
   auth_logger.setLevel(logging.DEBUG)

   # Add handler
   handler = logging.StreamHandler()
   formatter = logging.Formatter(
       '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
   )
   handler.setFormatter(formatter)
   auth_logger.addHandler(handler)

Environment-based Logging
~~~~~~~~~~~~~~~~~~~~~~~~

.. code-block:: bash

   # Set log level via environment
   AUTH_MIDDLEWARE_LOG_LEVEL=DEBUG
   AUTH_MIDDLEWARE_LOG_FORMAT="%(asctime)s %(name)s %(levelname)s %(message)s"
   AUTH_MIDDLEWARE_LOGGER_NAME="my_auth"

Security Best Practices
-----------------------

Token Security
~~~~~~~~~~~~~

1. **Use HTTPS**: Always use HTTPS in production to protect tokens in transit
2. **Token Expiration**: Ensure tokens have reasonable expiration times
3. **Secure Storage**: Never log or store JWT tokens in plain text
4. **Rotation**: Implement token rotation strategies

Configuration Security
~~~~~~~~~~~~~~~~~~~~~

1. **Environment Variables**: Store sensitive configuration in environment variables
2. **Secrets Management**: Use proper secrets management systems in production
3. **Least Privilege**: Configure minimal required permissions
4. **Monitoring**: Monitor authentication failures and suspicious activity

Error Handling Configuration
---------------------------

Custom Error Handlers
~~~~~~~~~~~~~~~~~~~~

.. code-block:: python

   from fastapi import FastAPI, HTTPException
   from fastapi.responses import JSONResponse
   from auth_middleware.exceptions import (
       AuthenticationError,
       AuthorizationError,
       TokenExpiredError,
   )

   app = FastAPI()

   @app.exception_handler(AuthenticationError)
   async def authentication_error_handler(request, exc):
       return JSONResponse(
           status_code=401,
           content={
               "error": "Authentication Failed",
               "message": "Please provide a valid authentication token",
               "type": "authentication_error"
           }
       )

   @app.exception_handler(AuthorizationError)
   async def authorization_error_handler(request, exc):
       return JSONResponse(
           status_code=403,
           content={
               "error": "Access Denied",
               "message": "You don't have permission to access this resource",
               "type": "authorization_error"
           }
       )

   @app.exception_handler(TokenExpiredError)
   async def token_expired_handler(request, exc):
       return JSONResponse(
           status_code=401,
           content={
               "error": "Token Expired",
               "message": "Your authentication token has expired. Please login again",
               "type": "token_expired"
           }
       )

Development Configuration
------------------------

Development Mode
~~~~~~~~~~~~~~

For development and testing environments:

.. code-block:: python

   import os

   # Development-friendly configuration
   auth_settings = CognitoAuthzProviderSettings(
       user_pool_id=os.getenv("AWS_COGNITO_USER_POOL_ID"),
       user_pool_region=os.getenv("AWS_COGNITO_USER_POOL_REGION"),
       jwt_token_verification_disabled=os.getenv("ENVIRONMENT") == "development",
   )

Hot Reloading
~~~~~~~~~~~

Auth Middleware works with FastAPI's hot reloading in development:

.. code-block:: bash

   # Development server with hot reloading
   uvicorn main:app --reload --host 0.0.0.0 --port 8000

Testing Configuration
~~~~~~~~~~~~~~~~~~~

.. code-block:: python

   import pytest
   from fastapi.testclient import TestClient

   @pytest.fixture
   def test_app():
       app = FastAPI()
       
       # Use mock auth provider for testing
       app.add_middleware(
           JwtAuthMiddleware,
           auth_provider=MockAuthProvider(),
       )
       
       return app

   def test_protected_endpoint(test_app):
       client = TestClient(test_app)
       
       response = client.get(
           "/protected",
           headers={"Authorization": "Bearer test_token"}
       )
       
       assert response.status_code == 200

For more specific provider configurations, see the individual provider documentation:

* :doc:`cognito_provider`
* :doc:`entra_id_provider`
* :doc:`jwt_auth_provider`
   * - AUTH_MIDDLEWARE_JWKS_CACHE_INTERVAL_MINUTES
     - JWKS keys file refreshing interval
     - An integer value
     - 20
   * - AUTH_MIDDLEWARE_JWKS_CACHE_USAGES
     - JWKS keys refreshing interval (counter)
     - An integer value
     - 1000