Skip to main content

A comprehensive API protection library for Python with rate limiting, authentication, and security features

Project description

APIProtector 🛡️

A comprehensive and lightweight API protection library for Python that provides rate limiting, authentication, request validation, and security scanning capabilities. Works with any Python web framework including Flask, Django, FastAPI, and more.

Features

  • Rate Limiting: Configurable rate limiting with sliding window algorithm
  • Authentication: Support for API keys and JWT tokens
  • Security Scanning: Detects SQL injection, XSS, and path traversal attacks
  • Request Validation: JSON schema validation and field validation
  • IP Blocking/Whitelisting: Block malicious IPs and whitelist trusted ones
  • Framework Agnostic: Works with Flask, Django, FastAPI, Pyramid, Tornado, and more
  • Thread-Safe: Built for concurrent applications
  • Logging: Comprehensive request logging and monitoring
  • Zero Dependencies: Pure Python implementation with no external dependencies

Installation

pip install apiprotector

Quick Start

Basic Usage

from apiprotector import APIProtector

# Create protector instance
protector = APIProtector({
    'rate_limit': 100,  # 100 requests per hour
    'window': 3600,     # 1 hour window
    'api_keys': {'your-api-key': 'user1'},
    'enable_security_scan': True
})

# Use as decorator
@protector.protect(rate_limit=50, require_auth=True)
def your_api_endpoint():
    return {"message": "Protected endpoint"}

Flask Integration

from flask import Flask, request
from apiprotector import APIProtector

app = Flask(__name__)
protector = APIProtector({
    'rate_limit': 100,
    'api_keys': {'secret-key-123': 'user1'},
    'blocked_ips': ['192.168.1.100'],
    'whitelisted_ips': ['192.168.1.1']
})

@app.route('/api/data')
@protector.protect(rate_limit=50, require_auth=True, auth_type='api_key')
def get_data():
    return {"data": "This is protected data"}

@app.route('/api/users', methods=['POST'])
@protector.protect(
    rate_limit=20,
    require_auth=True,
    validate_schema={'name': str, 'email': str},
    required_fields=['name', 'email'],
    field_limits={'name': 50, 'email': 100}
)
def create_user():
    return {"message": "User created"}

FastAPI Integration

from fastapi import FastAPI, Request
from apiprotector import APIProtector

app = FastAPI()
protector = APIProtector({
    'rate_limit': 100,
    'jwt_secret': 'your-jwt-secret-key',
    'enable_security_scan': True
})

@app.get("/api/protected")
@protector.protect(rate_limit=30, require_auth=True, auth_type='jwt')
async def protected_endpoint(request: Request):
    return {"message": "JWT Protected endpoint"}

@app.post("/api/validate")
@protector.protect(
    rate_limit=10,
    validate_schema={'username': str, 'password': str},
    required_fields=['username', 'password'],
    enable_security_scan=True
)
async def validate_data(request: Request):
    return {"message": "Data validated"}

Django Integration

from django.http import JsonResponse
from apiprotector import APIProtector

protector = APIProtector({
    'rate_limit': 100,
    'api_keys': {'django-api-key': 'user1'}
})

@protector.protect(rate_limit=25, require_auth=True)
def django_api_view(request):
    return JsonResponse({"message": "Django protected view"})

Configuration Options

config = {
    # Rate limiting
    'rate_limit': 100,          # Default requests per window
    'window': 3600,             # Time window in seconds
    
    # Authentication
    'api_keys': {               # API key to user mapping
        'key1': 'user1',
        'key2': 'user2'
    },
    'jwt_secret': 'secret',     # JWT secret key
    
    # Security
    'enable_security_scan': True,
    'blocked_ips': ['1.2.3.4'],
    'whitelisted_ips': ['192.168.1.1'],
    'blocked_user_agents': ['BadBot/1.0'],
    
    # Logging
    'enable_logging': True,
}

protector = APIProtector(config)

Decorator Parameters

@protector.protect(
    rate_limit=50,                    # Override default rate limit
    window=1800,                      # Override default window (30 min)
    require_auth=True,                # Require authentication
    auth_type='api_key',              # 'api_key' or 'jwt'
    validate_schema={                 # JSON schema validation
        'name': str,
        'age': int
    },
    required_fields=['name'],         # Required fields list
    field_limits={                    # Field length limits
        'name': 100,
        'description': 500
    },
    enable_security_scan=True         # Enable security scanning
)
def your_endpoint():
    pass

Security Features

SQL Injection Detection

# These patterns are automatically detected:
# - UNION SELECT statements
# - INSERT INTO statements
# - DELETE FROM statements
# - DROP TABLE statements
# - EXEC statements

XSS Protection

# Detects various XSS patterns:
# - <script> tags
# - javascript: URLs
# - Event handlers (onclick, onload, etc.)
# - iframe, object, embed tags

Path Traversal Protection

# Detects directory traversal attempts:
# - ../../../etc/passwd
# - ..%2f..%2f..%2fetc%2fpasswd
# - Various encoding variations

Authentication Methods

API Key Authentication

# Request headers:
# X-API-Key: your-api-key
# or
# Authorization: Bearer your-api-key

@protector.protect(require_auth=True, auth_type='api_key')
def protected_endpoint():
    pass

JWT Authentication

# Request headers:
# Authorization: Bearer jwt-token-here

@protector.protect(require_auth=True, auth_type='jwt')
def jwt_protected_endpoint():
    pass

Management Methods

# Get protection statistics
stats = protector.get_stats()
print(stats)

# Manage blocked IPs
protector.add_blocked_ip('192.168.1.100')
protector.remove_blocked_ip('192.168.1.100')

# Manage whitelisted IPs
protector.add_whitelisted_ip('192.168.1.1')
protector.remove_whitelisted_ip('192.168.1.1')

Error Handling

from apiprotector import (
    APIProtectorError,
    RateLimitExceeded,
    AuthenticationFailed,
    ValidationError,
    SecurityThreat
)

try:
    # Your protected endpoint
    pass
except RateLimitExceeded:
    return {"error": "Rate limit exceeded"}, 429
except AuthenticationFailed:
    return {"error": "Authentication failed"}, 401
except ValidationError:
    return {"error": "Validation failed"}, 400
except SecurityThreat:
    return {"error": "Security threat detected"}, 403
except APIProtectorError:
    return {"error": "API protection error"}, 500

Quick Protection Helper

For simple use cases, use the quick protection helper:

from apiprotector import quick_protect

@quick_protect(rate_limit=50, window=3600, require_auth=True)
def simple_endpoint():
    return {"message": "Simply protected"}

Logging

APIProtector provides comprehensive logging of all requests:

{
    "timestamp": "2024-01-15T10:30:00Z",
    "ip": "192.168.1.100",
    "method": "POST",
    "path": "/api/users",
    "user_agent": "Mozilla/5.0...",
    "status": "ALLOWED",
    "message": ""
}

Log statuses:

  • ALLOWED: Request passed all checks
  • BLOCKED: Request blocked (IP/User-Agent)
  • RATE_LIMITED: Rate limit exceeded
  • AUTH_FAILED: Authentication failed
  • VALIDATION_FAILED: Request validation failed
  • SECURITY_THREAT: Security threat detected
  • ERROR: Internal error occurred

Advanced Usage

Custom Security Scanning

from apiprotector import SecurityScanner

scanner = SecurityScanner()

# Check for specific threats
data = {"query": "SELECT * FROM users WHERE id = 1"}
threats = scanner.scan_all(data)
if threats:
    print(f"Threats detected: {threats}")

Custom Rate Limiting

from apiprotector import RateLimiter

limiter = RateLimiter()

# Check if client is within limits
if limiter.is_allowed("client_id", limit=10, window=60):
    print("Request allowed")
else:
    print("Rate limit exceeded")

# Get remaining requests
remaining = limiter.get_remaining_requests("client_id", limit=10, window=60)
print(f"Remaining requests: {remaining}")

Framework-Specific Examples

Tornado

import tornado.web
from apiprotector import APIProtector

protector = APIProtector({'rate_limit': 100})

class MainHandler(tornado.web.RequestHandler):
    @protector.protect(rate_limit=20)
    def get(self):
        self.write({"message": "Tornado protected"})

app = tornado.web.Application([
    (r"/", MainHandler),
])

Pyramid

from pyramid.config import Configurator
from pyramid.response import Response
from apiprotector import APIProtector

protector = APIProtector({'rate_limit': 100})

@protector.protect(rate_limit=30)
def hello_world(request):
    return Response('Pyramid protected!')

config = Configurator()
config.add_route('hello', '/')
config.add_view(hello_world, route_name='hello')

Best Practices

  1. Use Environment Variables: Store API keys and JWT secrets in environment variables
  2. Configure Appropriate Limits: Set rate limits based on your API capacity
  3. Enable Security Scanning: Always enable security scanning for public APIs
  4. Monitor Logs: Regularly monitor protection logs for suspicious activity
  5. Update IP Lists: Keep blocked and whitelisted IP lists updated
  6. Use HTTPS: Always use HTTPS in production
  7. Validate All Input: Use schema validation for all user inputs

Performance Considerations

  • Thread-Safe: All operations are thread-safe
  • Memory Usage: Rate limiting data is stored in memory
  • Cleanup: Old rate limit data is automatically cleaned up
  • Scalability: For high-traffic applications, consider using Redis for rate limiting

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests
  5. Submit a pull request

License

MIT License - see LICENSE file for details.

Support

Changelog

Version 1.0.0

  • Initial release
  • Rate limiting with sliding window
  • API key and JWT authentication
  • Security scanning (SQL injection, XSS, path traversal)
  • Request validation
  • IP blocking/whitelisting
  • Framework-agnostic design
  • Comprehensive logging

Examples Repository

For more examples and use cases, check out the examples repository.


Made with ❤️ by Kodukulla Phani Kumar

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

apiprotector-1.0.0.tar.gz (18.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

apiprotector-1.0.0-py3-none-any.whl (11.3 kB view details)

Uploaded Python 3

File details

Details for the file apiprotector-1.0.0.tar.gz.

File metadata

  • Download URL: apiprotector-1.0.0.tar.gz
  • Upload date:
  • Size: 18.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.10.11

File hashes

Hashes for apiprotector-1.0.0.tar.gz
Algorithm Hash digest
SHA256 b602555af3e9e8987c8a2730d81847ce9b08dd0ed4494057e640fde1ccbd425d
MD5 6dce4e936191778d72f0380fdaa5dc6e
BLAKE2b-256 9afdb4ea26494adc7794b8a83e231c1b91668a9f426874f772e3f061bd5feae0

See more details on using hashes here.

File details

Details for the file apiprotector-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: apiprotector-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 11.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.10.11

File hashes

Hashes for apiprotector-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9919bc081ded5738f5fb5e45e48f0468b5e39ffdefa4e449b98210a9ae04a4af
MD5 f671811bb97425688cfa0a556a8bcc00
BLAKE2b-256 279b0f55f60a90a9b501d028dabdf54c1cf6fb5a1ed52bc6bc23149261138d20

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page