Exception Handling

This module defines the custom exceptions used throughout the auth-middleware library. These exceptions provide specific error handling for authentication and authorization scenarios.

Exception Hierarchy

The auth-middleware library uses a hierarchical exception structure:

AuthMiddlewareException (base)
├── AuthenticationError
├── AuthorizationError
└── ConfigurationError

Exception Types

AuthenticationError

Raised when authentication fails, such as:

  • Invalid or expired JWT tokens

  • Missing authentication credentials

  • Token validation failures

  • Provider-specific authentication errors

from auth_middleware.exceptions import AuthenticationError

try:
    user = await authenticate_user(token)
except AuthenticationError as e:
    return JSONResponse(
        status_code=401,
        content={"error": "Authentication failed", "detail": str(e)}
    )

AuthorizationError

Raised when authorization checks fail, such as:

  • Insufficient permissions

  • Required group membership not met

  • Access to protected resources denied

from auth_middleware.exceptions import AuthorizationError

try:
    await check_user_permissions(user, required_permissions)
except AuthorizationError as e:
    return JSONResponse(
        status_code=403,
        content={"error": "Access denied", "detail": str(e)}
    )

ConfigurationError

Raised when there are configuration issues, such as:

  • Missing required environment variables

  • Invalid provider settings

  • Malformed configuration parameters

from auth_middleware.exceptions import ConfigurationError

try:
    provider = create_auth_provider(settings)
except ConfigurationError as e:
    logger.error(f"Configuration error: {e}")
    raise

Exception Handling Patterns

Middleware Error Handling

The middleware automatically handles exceptions and converts them to appropriate HTTP responses:

from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
from auth_middleware.exceptions import AuthenticationError, AuthorizationError

app = FastAPI()

@app.exception_handler(AuthenticationError)
async def authentication_error_handler(request: Request, exc: AuthenticationError):
    return JSONResponse(
        status_code=401,
        content={
            "error": "authentication_failed",
            "message": str(exc),
            "type": "AuthenticationError"
        }
    )

@app.exception_handler(AuthorizationError)
async def authorization_error_handler(request: Request, exc: AuthorizationError):
    return JSONResponse(
        status_code=403,
        content={
            "error": "access_denied",
            "message": str(exc),
            "type": "AuthorizationError"
        }
    )

Custom Error Responses

You can customize error responses based on the authentication provider:

@app.exception_handler(AuthenticationError)
async def custom_auth_error_handler(request: Request, exc: AuthenticationError):
    # Customize response based on provider type
    provider_type = getattr(request.state, 'auth_provider_type', 'unknown')

    if provider_type == 'cognito':
        return JSONResponse(
            status_code=401,
            content={
                "error": "invalid_token",
                "error_description": "AWS Cognito authentication failed",
                "error_uri": "https://docs.aws.amazon.com/cognito/"
            }
        )
    elif provider_type == 'entra_id':
        return JSONResponse(
            status_code=401,
            content={
                "error": "invalid_token",
                "error_description": "Azure AD authentication failed",
                "error_uri": "https://docs.microsoft.com/azure/active-directory/"
            }
        )

    return JSONResponse(
        status_code=401,
        content={"error": "authentication_failed", "message": str(exc)}
    )

Logging Exceptions

It’s recommended to log exceptions for debugging and monitoring:

import logging
from auth_middleware.exceptions import AuthMiddlewareException

logger = logging.getLogger(__name__)

@app.exception_handler(AuthMiddlewareException)
async def log_auth_errors(request: Request, exc: AuthMiddlewareException):
    logger.warning(
        f"Auth error: {exc.__class__.__name__}: {exc}",
        extra={
            "path": request.url.path,
            "method": request.method,
            "client": request.client.host if request.client else None,
            "user_agent": request.headers.get("user-agent"),
        }
    )

    # Re-raise to let other handlers process it
    raise exc

API Reference