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:
- Authentication Middleware (
auth_middlewareinsrc/bot/middleware/auth.py) – Verifies user identity and session validity - Rate-Limiting Middleware (
rate_limit_middlewareinsrc/bot/middleware/rate_limit.py) – Enforces usage quotas and cost controls - Security Middleware (
security_middlewareinsrc/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_idand optionalusernamefrom the incoming update - Retrieves the
auth_managerandaudit_loggerfrom 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_attemptfor 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_validatorandaudit_loggerfrom context - Checks
settings.agentic_modeto determine validation strictness - In standard mode, calls
validate_message_contentto scan for dangerous patterns using regex-based checks - For document uploads, invokes
validate_file_uploadto 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 usingestimate_message_costandcheck_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 onsettings.agentic_modeto 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →