Security Hardening #1

This commit is contained in:
Koncept Kit
2026-01-07 14:15:50 +07:00
parent d818d847bc
commit a74f161efa

111
server.py
View File

@@ -808,6 +808,53 @@ async def get_config():
"max_file_size_mb": int(max_file_size_mb) "max_file_size_mb": int(max_file_size_mb)
} }
@api_router.get("/diagnostics/cors")
async def cors_diagnostics(request: Request):
"""
CORS Diagnostics Endpoint
Shows current CORS configuration and request details for debugging
Use this to verify:
1. What origins are allowed
2. What origin is making the request
3. Whether CORS is properly configured
"""
cors_origins_env = os.environ.get('CORS_ORIGINS', '')
if cors_origins_env:
configured_origins = [origin.strip() for origin in cors_origins_env.split(',')]
cors_status = "✅ CONFIGURED"
else:
configured_origins = [
"http://localhost:3000",
"http://localhost:8000",
"http://127.0.0.1:3000",
"http://127.0.0.1:8000"
]
cors_status = "⚠️ NOT CONFIGURED (using defaults)"
request_origin = request.headers.get('origin', 'None')
origin_allowed = request_origin in configured_origins
return {
"cors_status": cors_status,
"environment": ENVIRONMENT,
"cors_origins_env_variable": cors_origins_env or "(not set)",
"allowed_origins": configured_origins,
"request_origin": request_origin,
"origin_allowed": origin_allowed,
"diagnosis": {
"cors_configured": bool(cors_origins_env),
"origin_matches": origin_allowed,
"issue": None if origin_allowed else f"Origin '{request_origin}' is not in allowed origins list"
},
"fix_instructions": None if origin_allowed else (
f"Add to backend .env file:\n"
f"CORS_ORIGINS={request_origin}"
f"{(',' + ','.join(configured_origins)) if cors_origins_env else ''}"
)
}
# User Profile Routes # User Profile Routes
@api_router.get("/users/profile", response_model=UserResponse) @api_router.get("/users/profile", response_model=UserResponse)
async def get_profile(current_user: User = Depends(get_current_user)): async def get_profile(current_user: User = Depends(get_current_user)):
@@ -6254,35 +6301,15 @@ async def stripe_webhook(request: Request, db: Session = Depends(get_db)):
# Include the router in the main app # Include the router in the main app
app.include_router(api_router) app.include_router(api_router)
# CORS Configuration # ============================================================================
cors_origins = os.environ.get('CORS_ORIGINS', '') # MIDDLEWARE CONFIGURATION
if cors_origins: # ============================================================================
# Use explicitly configured origins # IMPORTANT: In FastAPI, middleware is executed in REVERSE order of addition
allowed_origins = [origin.strip() for origin in cors_origins.split(',')] # Last added = First executed
else: # So we add them in this order: Security Headers -> CORS
# Default to common development origins if not configured # Execution order will be: CORS -> Security Headers
allowed_origins = [
"http://localhost:3000",
"http://localhost:8000",
"http://127.0.0.1:3000",
"http://127.0.0.1:8000"
]
print(f"⚠️ WARNING: CORS_ORIGINS not set. Using defaults: {allowed_origins}")
print("⚠️ For production, set CORS_ORIGINS in .env file!")
print(f"✓ CORS allowed origins: {allowed_origins}") # Security Headers Middleware (Added first, executes second)
app.add_middleware(
CORSMiddleware,
allow_credentials=True,
allow_origins=allowed_origins,
allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"],
allow_headers=["*"],
expose_headers=["*"],
max_age=600, # Cache preflight requests for 10 minutes
)
# Security Headers Middleware
@app.middleware("http") @app.middleware("http")
async def add_security_headers(request: Request, call_next): async def add_security_headers(request: Request, call_next):
response = await call_next(request) response = await call_next(request)
@@ -6319,3 +6346,31 @@ async def add_security_headers(request: Request, call_next):
return response return response
print(f"✓ Security headers configured (Production: {IS_PRODUCTION})") print(f"✓ Security headers configured (Production: {IS_PRODUCTION})")
# CORS Configuration (Added second, executes first)
cors_origins = os.environ.get('CORS_ORIGINS', '')
if cors_origins:
# Use explicitly configured origins
allowed_origins = [origin.strip() for origin in cors_origins.split(',')]
else:
# Default to common development origins if not configured
allowed_origins = [
"http://localhost:3000",
"http://localhost:8000",
"http://127.0.0.1:3000",
"http://127.0.0.1:8000"
]
print(f"⚠️ WARNING: CORS_ORIGINS not set. Using defaults: {allowed_origins}")
print("⚠️ For production, set CORS_ORIGINS in .env file!")
print(f"✓ CORS allowed origins: {allowed_origins}")
app.add_middleware(
CORSMiddleware,
allow_credentials=True,
allow_origins=allowed_origins,
allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"],
allow_headers=["*"],
expose_headers=["*"],
max_age=600, # Cache preflight requests for 10 minutes
)