Plug & play security library for FastAPI — rate limiting, honeypots, JWT, API keys, and more.
Project description
Plug & Play Security for FastAPI
Rate limiting · Honeypots · JWT · API Keys · Encrypted Audit Logging
⚡ What is Araxys?
Araxys is a comprehensive security library for FastAPI that provides enterprise-grade protection with a plug & play architecture. Add security to your API with three lines of code — no rewrites, no boilerplate.
from fastapi import FastAPI
from araxys import AraxysShield, AraxysConfig
app = FastAPI()
shield = AraxysShield(app, AraxysConfig(secret_key="your-32-char-secret-key-here!!!!"))
# That's it. Your API is now protected. 🛡️
🧩 Modules
| Module | Description | Status |
|---|---|---|
| 🚦 Rate Limiting | Dynamic sliding window with escalating bans | ✅ Ready |
| 🍯 Honeypots | Fake endpoints that auto-ban bots | ✅ Ready |
| 🔑 API Keys | Scoped keys with SHA-256 hashing & expiration | ✅ Ready |
| 🎟️ JWT Auth | Access + Refresh tokens with rotation & revocation | ✅ Ready |
| 🛡️ Secure Headers | HSTS, CSP, X-Frame-Options & more (OWASP) | ✅ Ready |
| 🧹 Sanitization | SQLi detection & XSS stripping | ✅ Ready |
| 📋 Audit Logging | AES-256-GCM encrypted structured logs | ✅ Ready |
📦 Installation
# Core (in-memory backends)
pip install araxys
# With Redis support (recommended for production)
pip install araxys[redis]
# Development
pip install araxys[dev]
Requires Python 3.13+
🚀 Quick Start
Full Protection (All Modules)
from fastapi import FastAPI
from araxys import AraxysShield, AraxysConfig
app = FastAPI()
shield = AraxysShield(
app,
AraxysConfig(
secret_key="super-secret-key-at-least-32-chars!",
redis_url="redis://localhost:6379", # Optional — omit for in-memory
rate_limit={"window_seconds": 60, "max_requests": 100},
honeypot={"paths": ["/admin/config", "/wp-admin", "/.env"]},
secure_headers={"enabled": True},
sanitize={"enabled": True},
audit={"encrypt": True, "log_file": "audit.log"},
),
)
API Key Authentication
from fastapi import Depends
from araxys import Scope
from araxys.api_keys.dependencies import require_api_key
from araxys.api_keys.models import APIKeyRecord
# Create a key
key = await shield.api_key_manager.create_key(
owner="service-a",
scopes=[Scope.READ, Scope.WRITE],
ttl_days=90,
)
print(f"Save this key: {key.raw_key}") # Shown only once!
### 💻 Command Line Interface (CLI)
Araxys includes a professional CLI for managing API keys and security assets directly from your terminal.
**Setup:**
Set the `ARAXYS_REDIS_URL` environment variable to point to your persistent storage.
```bash
export ARAXYS_REDIS_URL="redis://localhost:6379"
Usage:
# Create a new key
araxys keys create --owner "service-a" --scopes "read,write"
# List active keys
araxys keys list
# Revoke a key by prefix
araxys keys revoke [prefix]
Protect an endpoint
@app.get("/data") async def get_data( key: APIKeyRecord = Depends( require_api_key(Scope.READ, manager=shield.api_key_manager) ), ): return {"data": "protected", "owner": key.owner}
### JWT with Token Rotation
```python
from fastapi import Depends
from araxys import Scope
from araxys.jwt_auth.dependencies import require_jwt
from araxys.jwt_auth.tokens import TokenPayload
# Login — issue tokens
@app.post("/auth/login")
async def login(username: str, password: str):
# ... validate credentials ...
pair = await shield.jwt_manager.create_token_pair(
subject=user.id,
scopes=[Scope.READ, Scope.WRITE],
)
return pair.model_dump()
# Refresh — rotate tokens (old refresh token is blacklisted)
@app.post("/auth/refresh")
async def refresh(refresh_token: str):
new_pair = await shield.jwt_manager.rotate_tokens(refresh_token)
return new_pair.model_dump()
# Protected endpoint
@app.get("/profile")
async def profile(
user: TokenPayload = Depends(
require_jwt(Scope.READ, jwt_manager=shield.jwt_manager)
),
):
return {"user_id": user.sub, "scopes": user.scopes}
🏗️ Architecture
src/araxys/
├── core/ # Config, exceptions, shared types
│ ├── config.py # Pydantic Settings (env var support)
│ ├── exceptions.py # Custom exception hierarchy
│ └── types.py # Scope, AuditEntry, SecurityContext
├── rate_limit/ # 🚦 Dynamic rate limiting
│ ├── backends.py # Protocol + InMemory + Redis
│ ├── limiter.py # Sliding window + escalation
│ └── middleware.py # ASGI middleware
├── honeypot/ # 🍯 Trap endpoints
│ ├── trap.py # Route registration + auto-ban
│ └── middleware.py # IP ban enforcement
├── api_keys/ # 🔑 API Key management
│ ├── models.py # Pydantic models
│ ├── manager.py # CRUD + verification
│ ├── storage.py # Protocol + InMemory
│ └── dependencies.py # FastAPI dependencies
├── jwt_auth/ # 🎟️ JWT tokens
│ ├── tokens.py # Create, decode, rotate
│ ├── storage.py # JTI blacklisting
│ └── dependencies.py # FastAPI dependencies
├── headers/ # 🛡️ Security headers
│ └── middleware.py # HSTS, CSP, X-Frame-Options
├── sanitize/ # 🧹 Input sanitization
│ ├── patterns.py # SQLi + XSS regex patterns
│ ├── filters.py # Detection + stripping
│ └── middleware.py # ASGI middleware
├── audit/ # 📋 Audit logging
│ ├── encryption.py # AES-256-GCM + PBKDF2
│ ├── logger.py # Structured logger
│ └── events.py # Event types
└── shield.py # ⚡ Main orchestrator
🔐 Security Features in Detail
Rate Limiting
- Sliding window counter per IP + endpoint
- Escalating bans: repeated violations increase ban duration exponentially
- X-RateLimit headers:
Limit,Remaining,Windowinjected in every response - Path exclusion: Skip
/docs,/healthz, etc.
Honeypot Endpoints
- Registers fake routes like
/admin/config,/wp-admin,/.env - Returns 200 OK with fake content (doesn't alert the bot)
- Auto-bans the IP across ALL endpoints
- Integrates with audit logging
API Key Management
- 256-bit entropy keys via
secrets.token_urlsafe - Stored as SHA-256 hashes (raw key is never persisted)
- Scope-based authorization:
read,write,admin - Expiration support with configurable TTL
- Pluggable storage: implement the
APIKeyStorageprotocol with your database
JWT with Token Rotation
- Access + Refresh token pairs following OAuth2 best practices
- JTI-based revocation: each refresh token has a unique ID
- Replay attack detection: reusing a rotated refresh token triggers an alert
- Configurable TTLs: access (default 30min), refresh (default 7 days)
- Scope embedding in token claims
Secure Headers
| Header | Default Value |
|---|---|
Strict-Transport-Security |
max-age=31536000; includeSubDomains |
X-Content-Type-Options |
nosniff |
X-Frame-Options |
DENY |
X-XSS-Protection |
0 (disabled — modern best practice) |
Referrer-Policy |
strict-origin-when-cross-origin |
Content-Security-Policy |
Configurable |
Permissions-Policy |
Configurable |
Payload Sanitization
- 16 SQL injection patterns: UNION, DROP, blind injection, time-based, etc.
- 9 XSS patterns: script tags, JS URIs, event handlers, iframes
- Recursive scanning with configurable depth limit
- SQLi → block (400 response) · XSS → strip (bleach)
Encrypted Audit Logging
- AES-256-GCM authenticated encryption (confidentiality + integrity)
- PBKDF2-HMAC-SHA256 key derivation (480,000 iterations — OWASP 2023)
- Per-entry unique salt + nonce (no two entries share the same key material)
- Tamper detection: GCM authentication tag catches any modification
- Structured output via structlog
⚙️ Configuration
All settings support environment variables with the ARAXYS_ prefix:
export ARAXYS_SECRET_KEY="your-production-secret-key-here!"
export ARAXYS_REDIS_URL="redis://localhost:6379"
Or configure programmatically:
from araxys import AraxysConfig, RateLimitConfig, HoneypotConfig
config = AraxysConfig(
secret_key="...",
rate_limit=RateLimitConfig(
max_requests=200,
window_seconds=120,
ban_threshold=10,
ban_duration_seconds=600,
escalation_multiplier=3.0,
),
honeypot=HoneypotConfig(
paths=["/admin", "/wp-login.php", "/.git/config"],
ban_duration_seconds=7200,
),
jwt={"access_token_ttl_minutes": 15, "refresh_token_ttl_days": 30},
audit={"encrypt": True, "log_file": "/var/log/araxys/audit.log"},
)
🧪 Testing
# Run all tests
uv run pytest tests/ -v
# With coverage
uv run pytest tests/ --cov=araxys --cov-report=term-missing
63 tests covering all 7 modules — rate limiting, honeypots, API keys, JWT, headers, sanitization, and audit logging.
🏭 Production Recommendations
| Aspect | Recommendation |
|---|---|
| Backends | Use Redis (araxys[redis]) for multi-worker deployments |
| Secret Key | Generate with openssl rand -hex 32 — never hardcode |
| API Key Storage | Implement APIKeyStorage protocol with your database |
| Audit Logs | Enable encryption + write to a dedicated log file |
| Rate Limits | Tune max_requests and ban_threshold per endpoint |
| HTTPS | Always deploy behind TLS — HSTS headers expect it |
📁 Tech Stack
📄 License
MIT License — see LICENSE for details.
Built with 🛡️ by Samuel Esteban Urrego Valencia
"Security shouldn't be an afterthought — it should be a single import."
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file araxys-0.2.0.tar.gz.
File metadata
- Download URL: araxys-0.2.0.tar.gz
- Upload date:
- Size: 28.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dbf5d7b1f0a5b0b52ca781de13ce231a922840e14f9fb89bc19d961b431be0ae
|
|
| MD5 |
e9bc8ec665a28cd72ab795175727d7ce
|
|
| BLAKE2b-256 |
f92446a12f878766e4ffe8dd2da6c8213c249666b736d9ec42a80029766199bd
|
Provenance
The following attestation bundles were made for araxys-0.2.0.tar.gz:
Publisher:
publish.yml on Samuel-Urrego/Araxys
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
araxys-0.2.0.tar.gz -
Subject digest:
dbf5d7b1f0a5b0b52ca781de13ce231a922840e14f9fb89bc19d961b431be0ae - Sigstore transparency entry: 1548849229
- Sigstore integration time:
-
Permalink:
Samuel-Urrego/Araxys@040bca0c6206a607a13468e1d3143fc7d46ace4e -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/Samuel-Urrego
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@040bca0c6206a607a13468e1d3143fc7d46ace4e -
Trigger Event:
release
-
Statement type:
File details
Details for the file araxys-0.2.0-py3-none-any.whl.
File metadata
- Download URL: araxys-0.2.0-py3-none-any.whl
- Upload date:
- Size: 41.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
117d9e66b8d03175e9b9609caaabc4c8639b216ef74cc5db5d545cfc0d6c94c9
|
|
| MD5 |
28f544aafe8dcf102244b23d08772dfe
|
|
| BLAKE2b-256 |
e1bf340c779a18a767fe4b063ae0334283523e49c7a5f93041a86d48f5cf9619
|
Provenance
The following attestation bundles were made for araxys-0.2.0-py3-none-any.whl:
Publisher:
publish.yml on Samuel-Urrego/Araxys
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
araxys-0.2.0-py3-none-any.whl -
Subject digest:
117d9e66b8d03175e9b9609caaabc4c8639b216ef74cc5db5d545cfc0d6c94c9 - Sigstore transparency entry: 1548849551
- Sigstore integration time:
-
Permalink:
Samuel-Urrego/Araxys@040bca0c6206a607a13468e1d3143fc7d46ace4e -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/Samuel-Urrego
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@040bca0c6206a607a13468e1d3143fc7d46ace4e -
Trigger Event:
release
-
Statement type: