Security Best Practices
Guidelines for keeping your HiveForge application secure.
Authentication & Authorization
Use Strong Passwords
Enforce password requirements:
- Minimum 12 characters
- Mix of letters, numbers, symbols
- Not in common password lists
// Configure in Supabase Dashboard
// Authentication > Settings > Password requirementsEnable MFA
Multi-factor authentication for sensitive accounts:
const { data, error } = await supabase.auth.mfa.enroll({
factorType: 'totp',
})Secure Session Management
- Use HTTP-only cookies
- Set appropriate session expiry
- Implement refresh token rotation
// middleware.ts
const session = await supabase.auth.getSession()
if (!session || isExpired(session)) {
await supabase.auth.refreshSession()
}Implement RBAC
Use role-based access control:
function ProtectedAction() {
const { hasPermission } = usePermissions()
if (!hasPermission('organizations.delete')) {
return null
}
return <DeleteButton />
}Data Security
Row-Level Security (RLS)
Always enable RLS on tables:
ALTER TABLE organizations ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Users view own organizations"
ON organizations FOR SELECT
USING (
id IN (
SELECT organization_id
FROM organization_members
WHERE user_id = auth.uid()
)
);Input Validation
Validate all user input:
import { z } from 'zod'
const organizationSchema = z.object({
name: z.string().min(1).max(100),
slug: z.string().regex(/^[a-z0-9-]+$/),
tier: z.enum(['free', 'pro', 'enterprise']),
})
// Validate input
const validated = organizationSchema.parse(input)SQL Injection Prevention
Use parameterized queries:
# Bad - SQL injection risk
query = f"SELECT * FROM users WHERE email = '{email}'"
# Good - parameterized
result = await db.from_("users").select("*").eq("email", email).execute()XSS Prevention
Sanitize user-generated content:
import DOMPurify from 'isomorphic-dompurify'
const sanitized = DOMPurify.sanitize(userInput)API Security
Rate Limiting
Implement rate limits:
from slowapi import Limiter
from slowapi.util import get_remote_address
limiter = Limiter(key_func=get_remote_address)
@app.get("/api/endpoint")
@limiter.limit("100/minute")
async def endpoint():
return {"status": "ok"}CORS Configuration
Restrict origins:
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(
CORSMiddleware,
allow_origins=["https://yourdomain.com"],
allow_credentials=True,
allow_methods=["GET", "POST", "PUT", "DELETE"],
allow_headers=["*"],
)API Key Security
- Hash API keys before storing
- Use prefixes for identification
- Implement scopes
- Set expiration dates
import hashlib
def hash_api_key(key: str) -> str:
return hashlib.sha256(key.encode()).hexdigest()
# Store hash, not raw key
await db.from_("api_keys").insert({
"key_hash": hash_api_key(key),
"key_prefix": key[:10],
})Infrastructure
Environment Variables
- Never commit secrets to git
- Use different keys per environment
- Rotate secrets regularly
- Use secret management (Vault, AWS Secrets Manager)
# .gitignore
.env
.env.local
.env.productionHTTPS Only
Force HTTPS in production:
// middleware.ts
if (process.env.NODE_ENV === 'production' && !request.url.startsWith('https')) {
return NextResponse.redirect(
`https://${request.headers.get('host')}${request.url}`
)
}Security Headers
Set security headers:
// next.config.js
const securityHeaders = [
{
key: 'X-DNS-Prefetch-Control',
value: 'on'
},
{
key: 'Strict-Transport-Security',
value: 'max-age=63072000; includeSubDomains; preload'
},
{
key: 'X-Frame-Options',
value: 'SAMEORIGIN'
},
{
key: 'X-Content-Type-Options',
value: 'nosniff'
},
{
key: 'X-XSS-Protection',
value: '1; mode=block'
},
{
key: 'Referrer-Policy',
value: 'strict-origin-when-cross-origin'
},
{
key: 'Content-Security-Policy',
value: "default-src 'self'; script-src 'self' 'unsafe-eval' 'unsafe-inline';"
}
]Monitoring & Logging
Audit Logging
Log security-relevant events:
async def log_security_event(
user_id: str,
action: str,
resource: str,
ip_address: str
):
await db.from_("audit_logs").insert({
"user_id": user_id,
"action": action,
"resource_type": resource,
"ip_address": ip_address,
"created_at": datetime.now()
}).execute()Error Handling
Don't leak sensitive info in errors:
# Bad - exposes internal details
raise HTTPException(
status_code=500,
detail=f"Database error: {str(db_error)}"
)
# Good - generic message
logger.error(f"Database error: {str(db_error)}")
raise HTTPException(
status_code=500,
detail="Internal server error"
)Webhooks
Verify Signatures
Always verify webhook signatures:
import hmac
import hashlib
def verify_webhook_signature(
payload: bytes,
signature: str,
secret: str
) -> bool:
expected = hmac.new(
secret.encode(),
payload,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(signature, expected)Dependencies
Regular Updates
Keep dependencies updated:
# Check for updates
pnpm outdated
# Update dependencies
pnpm update
# Check for security vulnerabilities
pnpm auditDependabot
Enable Dependabot for automatic security updates:
# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"Compliance
GDPR
- Get user consent for data processing
- Allow data export
- Implement right to be forgotten
- Document data processing
Data Encryption
- Encrypt data at rest
- Use TLS for data in transit
- Encrypt sensitive fields
- Use encryption for backups
Incident Response
Security Checklist
When security incident occurs:
- Isolate affected systems
- Rotate all secrets
- Review audit logs
- Notify affected users
- Document incident
- Fix vulnerability
- Deploy fix
- Post-mortem
Key Rotation
Rotate secrets regularly:
# Rotate JWT secret
# 1. Generate new secret
openssl rand -base64 32
# 2. Update environment variables
# 3. Restart services
# 4. Invalidate old sessionsTesting Security
Security Tests
// Test authorization
test('rejects unauthorized access', async () => {
const response = await fetch('/api/admin/users', {
headers: { Authorization: 'Bearer invalid-token' }
})
expect(response.status).toBe(401)
})
// Test RLS
test('user cannot access other orgs', async () => {
const { data } = await supabase
.from('organizations')
.select('*')
.eq('id', 'other-org-id')
expect(data).toHaveLength(0)
})Security Checklist
- Enable RLS on all tables
- Validate all user input
- Use HTTPS in production
- Set security headers
- Implement rate limiting
- Hash API keys
- Verify webhook signatures
- Enable audit logging
- Regular dependency updates
- Strong password policy
- MFA for admins
- Error handling doesn't leak info
- CORS properly configured
- Secrets not in code
- Regular security audits
Resources
- OWASP Top 10 (opens in a new tab)
- Supabase Security (opens in a new tab)
- Next.js Security (opens in a new tab)
- FastAPI Security (opens in a new tab)