Security
next-api-layer includes a comprehensive security system with multiple layers of protection. This page covers all security features and their configuration.
Overview#
The security system provides:
- CSRF Protection - Prevents cross-site request forgery attacks
- Rate Limiting - Protects against brute force and DDoS attacks
- XSS Sanitization - Cleans malicious content from responses
- Audit Logging - Tracks security events for compliance and debugging
CSRF Protection#
Cross-Site Request Forgery (CSRF) protection prevents malicious sites from making requests on behalf of authenticated users.
Configuration#
Strategies#
fetch-metadata
Uses Sec-Fetch-* headers (modern browsers only).
Validates:
Sec-Fetch-Site: Must besame-originorsame-siteSec-Fetch-Mode: Checked for navigation vs. API requests
Pros: No token management needed Cons: Not supported in older browsers
double-submit
Classic double-submit cookie pattern.
How it works:
- Server sets a CSRF cookie with a random token
- Client must send the same token in a header
- Server validates that cookie value matches header value
Client-side usage:
both
Combines both strategies for maximum compatibility.
Validates:
- First checks Sec-Fetch-* headers (if available)
- Then falls back to double-submit validation
Recommended for production.
Trust Same-Site#
When enabled, requests with Sec-Fetch-Site: same-origin skip CSRF validation.
Ignore Methods#
Safe methods that don't need CSRF protection.
Rate Limiting#
Protects your API from abuse by limiting the number of requests per time window.
Configuration#
Options#
windowMs
Time window in milliseconds.
maxRequests
Maximum requests allowed per window.
keyFn
Function to generate rate limit key. Defaults to IP address.
skipRoutes
Routes to exclude from rate limiting.
onRateLimited
Custom response when rate limited.
Headers#
Rate limit information is included in response headers:
XSS Sanitization#
The API client automatically sanitizes response data to prevent XSS attacks.
It follows the same philosophy as DOMPurify: remove dangerous nodes, do not
over-escape plain text. Modern frameworks (React/Vue/Angular) already escape
text at render time — the sanitizer only needs to remove tags the framework
would otherwise trust (inside dangerouslySetInnerHTML, v-html, [innerHTML]).
Configuration#
Modes#
| Mode | Behavior | Use case |
|---|---|---|
| strip (default) | Removes well-formed HTML tags; preserves plain text chars (', /, `, =, bare <, >, &). | Default for API responses rendered via JSX / templates. |
| escape | Escapes <, >, &, " to HTML entities. Leaves other chars untouched. | Strings going into raw HTML contexts (dangerouslySetInnerHTML, email templates). |
| allowList | Keeps only tags in allowedTags, strips the rest. | Rich-text / CMS content. |
Why strip is the new default#
Earlier versions defaulted to escape with an aggressive entity set (/, ',
`, = all escaped). That corrupted text like Kur'an Hediyesi into
Kur'an Hediyesi in the UI. The current defaults mirror how real-world
HTML sanitizers (DOMPurify, sanitize-html) behave: they operate at the tag level,
not at the character level.
How It Works#
All string values in API responses are sanitized:
Allowed Tags (for allowList mode)#
Skip Fields#
Fields that should not be sanitized (use with caution):
Audit Logging#
Track security-relevant events for compliance, debugging, and monitoring.
Configuration#
Event Types#
| Event | Description |
|---|---|
auth:success | User successfully authenticated |
auth:fail | Authentication failed |
auth:refresh | Token was refreshed |
auth:guest | Guest token was created |
access:denied | Access to protected route denied |
csrf:fail | CSRF validation failed |
rateLimit:exceeded | Rate limit exceeded |
error | An error occurred |
Event Structure#
Logger Examples#
Console Logger
Database Logger
External Service
Security Best Practices#
Cookie Configuration#
Environment-Specific Settings#
Protect Sensitive Routes#
Rate Limit Sensitive Endpoints#
Security Headers#
The proxy automatically sets security headers:
To customize: