How Authentication, Rate-Limiting, and Security Middleware Layers Work Together in Claude-Code-Telegram

The Claude-Code-Telegram bot processes every incoming update through a strict pipeline of authentication, rate-limiting, and security middleware layers that short-circuit on failure to protect the underlying Claude API from unauthorized access, abuse, and malicious payloads.

The RichardAtCT/claude-code-telegram repository implements a defense-in-depth architecture where three specialized middleware components intercept Telegram updates before they reach the business logic. Understanding how these middleware layers interact is essential for customizing security policies, debugging access issues, or extending the bot's protective capabilities.

Middleware Architecture Overview

The bot employs a layered middleware pattern managed by the MessageOrchestrator class in src/bot/orchestrator.py. Rather than handling authentication, rate limiting, and security as separate concerns, the orchestrator chains them into a unified processing stack.

The Processing Pipeline

Each incoming Telegram update traverses the following sequence:

  1. Authentication Middleware (auth_middleware in src/bot/middleware/auth.py) – Verifies user identity and session validity
  2. Rate-Limiting Middleware (rate_limit_middleware in src/bot/middleware/rate_limit.py) – Enforces usage quotas and cost controls
  3. Security Middleware (security_middleware in src/bot/middleware/security.py) – Sanitizes inputs and validates file uploads

The orchestrator constructs this chain by wrapping handlers in reverse order, ensuring that the outermost layer (authentication) executes first.

Authentication Middleware

The authentication layer guarantees that only recognized and authorized users can invoke bot commands. Located in src/bot/middleware/auth.py, the auth_middleware function implements session management and whitelist enforcement.

Key Implementation Steps

The middleware performs the following operations for every update:

  • Extracts the Telegram user_id and optional username from the incoming update
  • Retrieves the auth_manager and audit_logger from the handler context
  • Checks existing session validity via auth_manager.is_authenticated(user_id)
  • Refreshes active sessions using auth_manager.refresh_session(user_id) to prevent timeout
  • Authenticates new users through auth_manager.authenticate_user(user_id), which validates against configured whitelists or external providers
  • Logs all attempts via audit_logger.log_auth_attempt for security auditing
  • Short-circuits with an "Authentication Required" message if any check fails

# Simplified flow from src/bot/middleware/auth.py

async def auth_middleware(handler, event, data):
    user_id = event.from_user.id
    auth_manager = data["auth_manager"]
    audit_logger = data["audit_logger"]
    
    if not auth_manager.is_authenticated(user_id):
        result = await auth_manager.authenticate_user(user_id)
        audit_logger.log_auth_attempt(user_id, result)
        if not result.success:
            await event.answer("Authentication Required")
            return  # Stop processing

    
    auth_manager.refresh_session(user_id)
    return await handler(event, data)

Rate-Limiting Middleware

Once authenticated, requests pass to the rate-limiting layer in src/bot/middleware/rate_limit.py. This middleware prevents resource exhaustion and Claude API cost overruns by enforcing usage quotas per user.

Cost-Aware Rate Limiting

The rate_limit_middleware implements sophisticated cost estimation:

  • Calculates message cost via estimate_message_cost(event), considering message length, file attachments, and command complexity
  • Invokes rate_limiter.check_rate_limit(user_id, cost, tokens=1) to validate against configured quotas
  • Records violations through audit_logger.log_rate_limit_exceeded
  • Returns a friendly "⏱️ Rate limit exceeded" message and aborts processing if limits are breached

The middleware also supports burst protection and post-processing cost tracking when registered with the MessageOrchestrator.


# Excerpt from src/bot/middleware/rate_limit.py

async def rate_limit_middleware(handler, event, data):
    user_id = event.from_user.id
    rate_limiter = data["rate_limiter"]
    audit_logger = data["audit_logger"]
    
    cost = estimate_message_cost(event)
    allowed = await rate_limiter.check_rate_limit(user_id, cost, tokens=1)
    
    if not allowed:
        audit_logger.log_rate_limit_exceeded(user_id, cost)
        await event.reply("⏱️ Rate limit exceeded. Please try again later.")
        return  # Short-circuit

    
    return await handler(event, data)

Security Middleware

The final protective layer, located in src/bot/middleware/security.py, sanitizes inputs and validates file uploads to prevent command injection, path traversal, and other attacks.

Context-Aware Validation

The security_middleware adapts its behavior based on the bot's operational mode:

  • Retrieves the security_validator and audit_logger from context
  • Checks settings.agentic_mode to determine validation strictness
  • In standard mode, calls validate_message_content to scan for dangerous patterns using regex-based checks
  • For document uploads, invokes validate_file_upload to verify filename safety, size limits, and MIME type against a blacklist
  • Logs security events via the audit logger and short-circuits with a security alert if threats are detected

When agentic_mode is enabled, the middleware treats incoming text as free-form prompts, skipping restrictive validation to allow natural language interaction while still enforcing file upload checks.


# Simplified logic from src/bot/middleware/security.py

async def security_middleware(handler, event, data):
    security_validator = data["security_validator"]
    audit_logger = data["audit_logger"]
    
    if not settings.agentic_mode:
        is_safe = await security_validator.validate_message_content(event.text)
        if not is_safe:
            audit_logger.log_security_event(event.from_user.id, "dangerous_content")
            await event.reply("🛡️ Security alert: Potentially dangerous content detected.")
            return
    
    if event.document:
        file_safe = await security_validator.validate_file_upload(event.document)
        if not file_safe:
            await event.reply("🛡️ File validation failed.")
            return
    
    return await handler(event, data)

How the Layers Interact

The MessageOrchestrator in src/bot/orchestrator.py constructs the middleware chain by wrapping handlers in reverse order. This creates a nested execution flow where authentication executes first, followed by rate limiting, then security validation, and finally the business logic.

Execution Flow


# Conceptual chain construction from src/bot/orchestrator.py

handler = self._handle_agentic_message
handler = security_middleware(handler, event, data)
handler = rate_limit_middleware(handler, event, data)
handler = auth_middleware(handler, event, data)

await handler(event, data)  # Execution begins here

Short-Circuit Behavior

Each middleware layer implements fail-fast semantics. If any layer detects a violation, it immediately returns without calling the next handler, preventing unauthorized or dangerous requests from consuming Claude API resources.

Layer Success Action Failure Action
Authentication Refreshes session, proceeds to next layer Returns "Authentication Required", stops
Rate-Limiting Consumes quota, proceeds to next layer Returns "⏱️ Rate limit exceeded", stops
Security Validates content, proceeds to handler Returns "🛡️ Security alert", stops

This layered approach ensures that expensive AI processing only occurs for authenticated, compliant, and safe requests.

Summary

  • Authentication Middleware (src/bot/middleware/auth.py) validates user identity against whitelists and manages session refresh, short-circuiting unauthenticated requests before they consume resources.
  • Rate-Limiting Middleware (src/bot/middleware/rate_limit.py) enforces cost-aware usage quotas using estimate_message_cost and check_rate_limit, protecting against API cost overruns and resource exhaustion.
  • Security Middleware (src/bot/middleware/security.py) sanitizes inputs and validates file uploads, adapting validation strictness based on settings.agentic_mode to block command injection and path traversal attacks.
  • MessageOrchestrator (src/bot/orchestrator.py) chains these layers in reverse order (auth → rate-limit → security → handler), creating a fail-fast pipeline where each layer can abort processing to protect the Claude API backend.

Frequently Asked Questions

What happens if a user fails authentication but tries to send many requests?

The authentication middleware short-circuits every request immediately upon failure, returning an "Authentication Required" message without invoking the rate limiter or security validator. Because the request never reaches the Claude API, failed authentication attempts consume minimal server resources and do not count against rate limits.

How does the bot prevent API cost overruns from expensive file uploads?

The rate-limiting middleware calculates message costs using estimate_message_cost(event), which factors in file attachments, message length, and command complexity. Before processing uploads, rate_limiter.check_rate_limit(user_id, cost, tokens=1) verifies the user has sufficient quota. If an upload would exceed the budget, the middleware aborts with a "⏱️ Rate limit exceeded" message, preventing the expensive API call.

Why does the security middleware behave differently in agentic mode?

When settings.agentic_mode is enabled, the security middleware treats incoming text as free-form natural language prompts rather than structured commands. In this mode, validate_message_content skips restrictive regex checks that would otherwise block legitimate AI prompts, while still enforcing validate_file_upload for document attachments. This balance allows flexible conversational interaction while maintaining protection against malicious file uploads.

Can I add custom middleware without breaking the existing security chain?

Yes, the MessageOrchestrator in src/bot/orchestrator.py supports custom middleware insertion by wrapping the existing handler stack. New middleware should follow the pattern def custom_middleware(handler, event, data) and call await handler(event, data) to proceed. Insert custom layers between the existing auth, rate-limit, and security middleware, or wrap the entire chain, depending on whether your logic requires pre-authentication or post-security processing.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →