Enterprise CORS middleware presets for FastAPI applications
Project description
netrun-cors
Enterprise CORS middleware presets for FastAPI applications.
Overview
netrun-cors provides standardized, production-ready CORS configurations for FastAPI applications. Instead of manually configuring CORS middleware for each project, use battle-tested presets that follow OWASP security best practices.
Key Features:
- 4 preset configurations:
development,staging,production,oauth - OWASP compliance validation (prevents wildcard + credentials vulnerability)
- OAuth platform support (Google, Twitter, LinkedIn, Facebook, TikTok, Instagram, Pinterest, Threads)
- Azure Container Apps integration
- Type-safe configuration with Pydantic
- Comprehensive test coverage (90%+)
Installation
pip install netrun-cors
Or with Poetry:
poetry add netrun-cors
Quick Start
Development (Local Development)
Permissive CORS for rapid iteration on localhost:
from fastapi import FastAPI
from netrun_cors import CORSPreset
app = FastAPI()
app.add_middleware(CORSPreset.development())
Configuration:
- Origins:
localhost:3000,localhost:5173,127.0.0.1:3000(HTTP) - Credentials: Enabled
- Methods: All (
*) - Headers: All (
*) - Max Age: 600s (10 minutes)
Production (Explicit Whitelist)
Strict origin whitelisting for production deployments:
from fastapi import FastAPI
from netrun_cors import CORSPreset
app = FastAPI()
app.add_middleware(
CORSPreset.production(
origins=[
"https://app.example.com",
"https://www.example.com"
]
)
)
Configuration:
- Origins: Explicit whitelist (HTTPS recommended)
- Credentials: Enabled
- Methods:
GET,POST,PUT,DELETE,OPTIONS,PATCH - Headers:
Authorization,Content-Type,Accept,X-Request-ID - Expose Headers:
X-Request-ID - Max Age: 3600s (1 hour)
Staging (Azure Container Apps)
Support for Azure Container Apps with wildcard environment hashes:
from fastapi import FastAPI
from netrun_cors import CORSPreset
app = FastAPI()
app.add_middleware(
CORSPreset.staging(
container_apps=["intirkast-frontend", "meridian-frontend"],
region="eastus2"
)
)
Configuration:
- Origins:
https://localhost:3000,5173+ Azure Container Apps wildcards - Credentials: Enabled
- Methods:
GET,POST,PUT,DELETE,OPTIONS,PATCH - Headers:
Authorization,Content-Type,Accept,X-Requested-With,X-Request-ID - Max Age: 1800s (30 minutes)
Optional Additional Origins:
app.add_middleware(
CORSPreset.staging(
container_apps=["test-app"],
additional_origins=["https://staging.example.com"]
)
)
OAuth (Social Platform Integration)
Whitelist OAuth callback domains for social login flows:
from fastapi import FastAPI
from netrun_cors import CORSPreset
app = FastAPI()
app.add_middleware(
CORSPreset.oauth(
app_origins=["https://app.intirkast.com"],
platforms=["google", "twitter", "linkedin", "facebook"]
)
)
Configuration:
- Origins: App origins + OAuth platform domains
- Credentials: Enabled
- Methods: All (
*) - Headers: All (
*) - Expose Headers: All (
*) - Max Age: 3600s (1 hour)
Supported Platforms:
| Platform | Domain |
|---|---|
google |
https://accounts.google.com |
twitter |
https://twitter.com |
linkedin |
https://www.linkedin.com |
facebook |
https://www.facebook.com |
tiktok |
https://www.tiktok.com |
instagram |
https://www.instagram.com |
pinterest |
https://www.pinterest.com |
threads |
https://www.threads.net |
Advanced Usage
Custom Configuration
If presets don't match your requirements, use CORSPreset.custom():
from netrun_cors import CORSPreset
app.add_middleware(
CORSPreset.custom(
allow_origins=["https://app.example.com"],
allow_credentials=True,
allow_methods=["GET", "POST"],
allow_headers=["Authorization", "Content-Type"],
expose_headers=["X-Request-ID"],
max_age=1200
)
)
OWASP Compliance Validation:
The custom preset validates against OWASP security guidelines:
# ❌ This will raise ValueError
app.add_middleware(
CORSPreset.custom(
allow_origins=["*"], # Wildcard
allow_credentials=True # Credentials enabled
)
)
# ValueError: OWASP Violation: Cannot use wildcard origins with credentials
Environment Variable Configuration
Use CORSConfig for environment-based configuration:
from netrun_cors import CORSConfig
config = CORSConfig()
# Reads from environment variables:
# CORS_ORIGINS=https://app.example.com,https://www.example.com
# CORS_ALLOW_CREDENTIALS=true
# CORS_MAX_AGE=3600
app.add_middleware(
CORSPreset.production(origins=config.CORS_ORIGINS)
)
.env file example:
CORS_ORIGINS=https://app.example.com,https://www.example.com
CORS_ALLOW_CREDENTIALS=true
CORS_ALLOW_METHODS=GET,POST,PUT,DELETE
CORS_ALLOW_HEADERS=Authorization,Content-Type
CORS_EXPOSE_HEADERS=X-Request-ID,X-Process-Time
CORS_MAX_AGE=3600
Migration Guide
Before: Manual CORS Configuration
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=[
"http://localhost:3000",
"http://localhost:5173",
"https://app.intirkast.com",
"https://intirkast-frontend.orangesmoke-f0fb748a.eastus2.azurecontainerapps.io",
"https://accounts.google.com", # Google OAuth
"https://twitter.com", # Twitter OAuth
"https://www.linkedin.com", # LinkedIn OAuth
],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
expose_headers=["X-Request-ID", "X-Process-Time"],
max_age=3600,
)
LOC: 18 lines
After: netrun-cors
from fastapi import FastAPI
from netrun_cors import CORSPreset
app = FastAPI()
app.add_middleware(
CORSPreset.oauth(
app_origins=["https://app.intirkast.com"],
platforms=["google", "twitter", "linkedin"]
)
)
LOC: 2 lines (89% reduction)
Security Best Practices
1. Production Origin Whitelisting
Always use explicit origin lists in production:
# ✅ Secure (explicit origins)
app.add_middleware(
CORSPreset.production(origins=["https://app.example.com"])
)
# ❌ Insecure (wildcard in production)
app.add_middleware(
CORSPreset.custom(allow_origins=["*"], allow_credentials=False)
)
2. HTTPS Only in Production
Use HTTPS origins for production deployments:
# ✅ Secure (HTTPS)
origins = [
"https://app.example.com",
"https://www.example.com"
]
# ❌ Insecure (HTTP in production)
origins = [
"http://app.example.com", # Vulnerable to MITM attacks
]
3. Minimize Exposed Headers
Only expose headers your frontend needs:
# ✅ Minimal (production)
expose_headers = ["X-Request-ID"]
# ⚠️ Permissive (development only)
expose_headers = ["*"]
4. Preflight Caching
Use appropriate max_age for preflight caching:
# Production: 1 hour (reduces preflight overhead)
app.add_middleware(CORSPreset.production(origins=[...])) # max_age=3600
# Development: 10 minutes (faster iteration)
app.add_middleware(CORSPreset.development()) # max_age=600
Testing
Run the test suite with pytest:
# Install dev dependencies
pip install -e ".[dev]"
# Run tests
pytest
# Run tests with coverage
pytest --cov=netrun_cors --cov-report=term-missing
# Run tests with verbose output
pytest -v
API Reference
CORSPreset
Factory class for standardized CORS middleware configurations.
Methods
development()
Permissive CORS for local development (localhost origins).
Returns: CORSMiddleware
Example:
app.add_middleware(CORSPreset.development())
staging(container_apps, region, additional_origins)
Azure Container Apps staging environment with wildcard support.
Parameters:
container_apps(List[str]): Azure Container App namesregion(str): Azure region (default:"eastus2")additional_origins(Optional[List[str]]): Additional origins to whitelist
Returns: CORSMiddleware
Example:
app.add_middleware(
CORSPreset.staging(
container_apps=["test-app"],
region="westus2"
)
)
production(origins)
Production deployment with explicit origin whitelisting.
Parameters:
origins(List[str]): List of allowed production origins
Returns: CORSMiddleware
Example:
app.add_middleware(
CORSPreset.production(origins=["https://app.example.com"])
)
oauth(app_origins, platforms)
OAuth-enabled applications with social platform callback domains.
Parameters:
app_origins(List[str]): Application originsplatforms(List[str]): OAuth platform identifiers
Returns: CORSMiddleware
Raises:
ValueError: If invalid platform identifier provided
Example:
app.add_middleware(
CORSPreset.oauth(
app_origins=["https://app.example.com"],
platforms=["google", "twitter"]
)
)
custom(**kwargs)
Custom CORS configuration with full control.
Parameters:
allow_origins(List[str]): List of allowed originsallow_credentials(bool): Allow credentials (default:True)allow_methods(Optional[List[str]]): Allowed HTTP methodsallow_headers(Optional[List[str]]): Allowed headersexpose_headers(Optional[List[str]]): Exposed headersmax_age(int): Preflight cache duration in seconds
Returns: CORSMiddleware
Raises:
ValueError: If wildcard origins combined with credentials
Example:
app.add_middleware(
CORSPreset.custom(
allow_origins=["https://app.example.com"],
allow_methods=["GET", "POST"],
max_age=1200
)
)
CORSConfig
Pydantic settings for type-safe CORS configuration with environment variable support.
Attributes:
CORS_ORIGINS(List[str]): Allowed origins (default: localhost)CORS_ALLOW_CREDENTIALS(bool): Allow credentials (default:True)CORS_ALLOW_METHODS(List[str]): Allowed methods (default:["*"])CORS_ALLOW_HEADERS(List[str]): Allowed headers (default:["*"])CORS_EXPOSE_HEADERS(List[str]): Exposed headers (default:["X-Request-ID", "X-Process-Time"])CORS_MAX_AGE(int): Preflight cache duration (default:3600)
Example:
from netrun_cors import CORSConfig
config = CORSConfig()
print(config.CORS_ORIGINS) # ['http://localhost:3000', 'http://localhost:5173']
Performance Considerations
Preflight Caching
CORS preflight requests (OPTIONS) can add latency. Use max_age to cache preflight responses:
| Environment | max_age | Rationale |
|---|---|---|
| Development | 600s (10 min) | Fast iteration, frequent changes |
| Staging | 1800s (30 min) | Balance between testing and performance |
| Production | 3600s (1 hour) | Maximum performance, stable configuration |
Origin Matching Performance
Explicit origin lists have O(n) lookup time. For large origin lists (100+), consider:
- Using a reverse proxy (Nginx, Cloudflare) for CORS
- Implementing origin caching in your application
- Grouping origins by environment (dev, staging, prod)
Troubleshooting
Common Issues
1. CORS Error: "No 'Access-Control-Allow-Origin' header"
Cause: Origin not whitelisted in CORS configuration
Solution: Add origin to allowed list:
app.add_middleware(
CORSPreset.production(
origins=[
"https://app.example.com",
"https://new-origin.example.com" # Add missing origin
]
)
)
2. CORS Error: "Wildcard with credentials"
Cause: Attempting to use allow_origins=["*"] with allow_credentials=True
Solution: Use explicit origins or disable credentials:
# Option 1: Explicit origins (recommended)
app.add_middleware(
CORSPreset.production(origins=["https://app.example.com"])
)
# Option 2: Disable credentials
app.add_middleware(
CORSPreset.custom(allow_origins=["*"], allow_credentials=False)
)
3. OAuth Callback Failure
Cause: OAuth platform domain not whitelisted
Solution: Use oauth preset with appropriate platforms:
app.add_middleware(
CORSPreset.oauth(
app_origins=["https://app.example.com"],
platforms=["google", "twitter", "linkedin"]
)
)
4. Azure Container Apps Staging Issues
Cause: Dynamic environment hash not matching
Solution: Use staging preset with wildcard support:
app.add_middleware(
CORSPreset.staging(
container_apps=["intirkast-frontend"],
region="eastus2"
)
)
Contributing
Contributions welcome! Please follow these guidelines:
- Fork the repository
- Create a feature branch (
git checkout -b feature/new-preset) - Write tests for new functionality
- Ensure tests pass (
pytest) - Run linters (
black,ruff,mypy) - Submit a pull request
License
MIT License - see LICENSE file for details.
Support
Issues: GitHub Issues Email: support@netrunsystems.com Documentation: GitHub Repository
Changelog
v1.0.0 (2025-11-25)
Initial Release:
- 4 preset configurations (development, staging, production, oauth)
- OWASP compliance validation
- 8 OAuth platform support
- Azure Container Apps integration
- Pydantic configuration support
- Comprehensive test suite (90%+ coverage)
Developed by Netrun Systems
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 netrun_cors-1.0.0.tar.gz.
File metadata
- Download URL: netrun_cors-1.0.0.tar.gz
- Upload date:
- Size: 14.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c52e33a8a5f9a0ffb89cdd8f023b66c1b451fe5d01f8dc3fd9f987cf4b507139
|
|
| MD5 |
bc0fd6361f22f2a3d7f66ed6fd8013bf
|
|
| BLAKE2b-256 |
1b8c338b9e45a380ac1588b83824f24be61e915545128f4fe7f9c5f39a18da9c
|
File details
Details for the file netrun_cors-1.0.0-py3-none-any.whl.
File metadata
- Download URL: netrun_cors-1.0.0-py3-none-any.whl
- Upload date:
- Size: 11.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a37551ad2df5156fa0c7fd6a75a56674c4923237c8340c63da09beeb1fc5006b
|
|
| MD5 |
b125b13c6a2095b686d535642d3087ab
|
|
| BLAKE2b-256 |
ba01a962fd0bdcf8f5bb024d1204e002a7672fbe751dfaff2b49f1854f6a6903
|