Configuration: Environment-Specific Security
Different environments need different strictness. Configure in .env:
# .env (Development)
BEARER_VERIFY_DOMAINS=false # Flexible for testing
QUEUE_CONNECTION=sync # Logging immediate
APP_DEBUG=true # Show errors
CACHE_DRIVER=redis # Real cache
RATE_LIMIT_PER_TOKEN=1000 # High limit
# .env (Production)
BEARER_VERIFY_DOMAINS=true # Enforce domains
QUEUE_CONNECTION=redis # Async logging
APP_DEBUG=false # Hide errors
CACHE_DRIVER=redis # Required
RATE_LIMIT_PER_TOKEN=60 # Strict
CORS_ALLOWED_ORIGINS=https://example.com
SHOULD_BE_ENCRYPTED=true # Encrypt jobs
Configure rate limits per environment:
// config/rate-limiting.php
RateLimiter::for('api-token', function (Request $request) {
$limit = config('app.env') === 'production' ? 60 : 1000;
return Limit::perMinute($limit)->by($request->bearerToken() ?: $request->ip());
});
Configure CORS origins:
CORS_ALLOWED_ORIGINS=https://example.com,https://trusted-partner.com
Cache Backend Selection
Redis is essential for production rate limiting. Database caching is too slow for thousands of requests/sec:
// config/cache.php
'default' => env('CACHE_DRIVER', 'redis'),
'stores' => [
'redis' => ['driver' => 'redis', 'connection' => 'cache'],
'file' => ['driver' => 'file'], // Dev only
],
When NOT to Use These Patterns
Know your constraints:
Domain Validation: Use when multiple partners with different credentials exist and token theft is critical. Skip for internal APIs with short-lived tokens.
Per-Token Rate Limiting: Use when clients have different needs or you charge by usage. Skip if all clients are equal.
Token Caching: Use when tokens are looked up frequently and you tolerate revocation delays. Skip if instant revocation is required.
Async Logging: Use for high-traffic APIs where logging latency matters. Skip for synchronous audit trail requirements.
Bearer Tokens: Use for service-to-service auth. Skip for multi-user SPAs (use Sanctum instead).
Tighten constraints when: Security incidents happen (reduce TTL, enable all validations), traffic spikes (optimize caching), or compliance requires it (add encryption, retention).
Security isn't one-size-fits-all. Measure and adjust.
Summary: Security Isn't Optional
Security isn't something you add later. It's baked in from the start. Here's your security checklist:
Authentication:
- [X] Use Bearer tokens, not sessions
- [X] Cache tokens to avoid database hits (with appropriate cache TTL)
- [X] Expire tokens regularly
- [X] Allow revocation of compromised tokens
- [X] Never store plain tokens in logs (sanitize before logging)
Validation:
- [X] Validate all input at the boundary
- [X] Use FormRequest classes
- [X] Create custom rules for custom logic
- [X] Reject invalid data immediately
- [X] Never trust client-side validation
Rate Limiting:
- [X] Implement per-token rate limits (not just per IP)
- [X] Return 429 when exceeded
- [X] Expose rate limit headers for proactive clients
- [X] Monitor for abuse patterns
Error Handling:
- [X] Consistent error format for all endpoints
- [X] Appropriate HTTP status codes
- [X] Never expose internal details in production
- [X] Log errors for debugging (without sensitive data)
- [X] Include requestID/traceID for debugging
SQL Injection Prevention:
- [X] Use Eloquent ORM (not raw SQL)
- [X] Use parameterized queries (Eloquent does this automatically)
- [X] Never concatenate user input into queries
- [X] Use placeholder bindings:
where✓ vswhereRaw✗
Access Control:
- [X] Use HTTPS only (enforce in production with HSTS headers)
- [X] Implement CORS correctly (explicit origins, no wildcards for sensitive APIs)
- [X] Check token domain restrictions
- [X] Log all authentication failures for monitoring
- [X] Implement IP whitelisting if operating in controlled environment
Secrets Management:
- [X] Use environment variables for all secrets (tokens, API keys, passwords)
- [X] Never hardcode secrets or commit to version control
- [X] Use
.env.examplefor documentation, never with real values - [X] Rotate secrets regularly (especially tokens)
- [X] Use secrets management service (AWS Secrets Manager, HashiCorp Vault) in production
- [X] Never log secrets or tokens
Production Guidelines:
- [X] Enable HTTPS with valid SSL certificates
- [X] Set security headers:
Strict-Transport-Security,X-Content-Type-Options,X-Frame-Options - [X] Regular security audits with tools like
composer audit(checks dependencies) - [X]Keep all dependencies updated:
composer updatemonthly minimum - [X] Monitor for vulnerability advisories (follows CVE databases)
- [X] Use Web Application Firewall (WAF) in critical environments
- [X] Implement request signing for sensitive operations
- [X] Log all security events (failed auth, rate limit violations, etc.)
Pro Tips:
- Use
composer auditto check for known vulnerabilities in dependencies - Set up GitHub Security Alerts to auto-detect vulnerable packages
- Implement CI/CD checks: run security tests before deployment
- Consider using Laravel Telescope in development (builtin debugging tool)
- Use Larastan/PHPStan for static analysis (catches type errors, security issues)
- Test authentication with penetration testing in staging environment
- Implement request signing for truly sensitive operations
Security is an ongoing process, not a one-time checklist. The landscape changes constantly. New vulnerabilities appear regularly. Your job is to stay informed, update dependencies promptly, and maintain healthy paranoia about your data. Keep your dependencies updated, monitor for vulnerabilities, and never trust anything from the client without validation.