Overview
Thecsrf middleware protects against Cross-Site Request Forgery attacks by generating and validating tokens. It ensures that form submissions originate from your application, not from malicious sites.
Use it when you have:
- HTML forms that modify data
- Server-rendered applications
- Any POST/PUT/DELETE endpoints accessed via browser
Installation
Quick Start
Configuration
Options
| Option | Type | Default | Description |
|---|---|---|---|
Secret | []byte | required | Secret key for token generation |
TokenLength | int | 32 | Length of random token |
TokenLookup | string | "header:X-CSRF-Token" | Where to find token in request |
CookieName | string | "_csrf" | Name of CSRF cookie |
CookiePath | string | "/" | Cookie path |
CookieMaxAge | int | 86400 | Cookie max age in seconds |
CookieSecure | bool | false | Secure cookie flag |
CookieHTTPOnly | bool | true | HTTPOnly cookie flag |
SameSite | http.SameSite | Lax | SameSite cookie attribute |
ErrorHandler | func(*mizu.Ctx, error) error | - | Custom error handler |
SkipPaths | []string | - | Paths to skip CSRF validation |
TokenLookup Format
TheTokenLookup option uses "source:name" format:
| Source | Example | Description |
|---|---|---|
header | "header:X-CSRF-Token" | Read from request header |
form | "form:_csrf" | Read from form field |
query | "query:csrf" | Read from query parameter |
Examples
Basic Form Protection
Using Template Field Helper
JavaScript AJAX Requests
Skip API Routes
Custom Error Handler
Multiple Token Sources
Development vs Production
API Reference
Functions
Token Functions
Error Types
How It Works
- Token Generation: On GET requests, a token is generated and stored in a cookie
- Token Validation: On POST/PUT/DELETE requests, the token must be included
- Double Submit: The cookie token must match the request token
- HMAC Signature: Tokens are signed to prevent tampering
Technical Details
Token Generation
The middleware generates cryptographically secure tokens using the following process:- Random Bytes: Generates random bytes of specified length (default 32) using
crypto/rand - HMAC Signature: Creates an HMAC-SHA256 signature of the random bytes using the secret key
- Encoding: Encodes both the token and signature using base64 URL encoding
- Format: Combines them as
token.signaturefor tamper detection
Token Validation
Validation follows a multi-step process to ensure security:- Constant-Time Comparison: Uses
subtle.ConstantTimeCompareto prevent timing attacks - Cookie-Request Match: Verifies the cookie token exactly matches the request token
- Signature Verification: Decodes and validates the HMAC signature
- HMAC Equality: Uses
hmac.Equalfor secure signature comparison
Safe vs Unsafe Methods
The middleware distinguishes between HTTP methods:- Safe Methods (GET, HEAD, OPTIONS, TRACE): Generate or reuse tokens, no validation required
- Unsafe Methods (POST, PUT, DELETE, PATCH): Require valid token in both cookie and request
Context Storage
Tokens are stored in the request context using a privatecontextKey type to prevent collisions with other middleware or application code. This allows retrieval via the Token() function throughout the request lifecycle.
Path Skipping
TheSkipPaths option uses a map for O(1) lookup performance, allowing specific routes (like webhooks or public APIs) to bypass CSRF validation entirely.
Security Considerations
- Secret Key - Use a strong, random 32-byte secret
- Cookie Settings - Use
Secure,HttpOnly, andSameSitein production - Token Rotation - Tokens are per-session, not per-request
- HTTPS Required - Always use HTTPS in production
Recommended Production Settings
Best Practices
- Always include CSRF protection for forms
- Use secure cookies in production
- Skip CSRF for API endpoints using Bearer auth
- Regenerate token after login/logout
- Set appropriate cookie expiration
Testing
The CSRF middleware includes comprehensive test coverage for all functionality:| Test Case | Description | Expected Behavior |
|---|---|---|
| Basic Functionality | ||
| Sets cookie on GET | GET request to protected endpoint | CSRF cookie is set with generated token |
| Rejects POST without token | POST request without CSRF token | Returns 403 Forbidden |
| Accepts POST with valid token | POST with matching cookie and header token | Request succeeds with 200 OK |
| Rejects POST with invalid token | POST with mismatched tokens | Returns 403 Forbidden |
| Token Lookup Sources | ||
| Form token lookup | POST with token in form field | Token extracted from form and validated |
| Query token lookup | POST with token in query parameter | Token extracted from query and validated |
| Header token lookup | POST with token in header (default) | Token extracted from header and validated |
| Path Skipping | ||
| Skips listed path | POST to path in SkipPaths | Request bypasses CSRF validation |
| Protects non-listed path | POST to path not in SkipPaths | CSRF validation required |
| Error Handling | ||
| Custom error handler | POST without token with ErrorHandler set | Custom error handler called with error |
| Default error handler | POST without token, no ErrorHandler | Returns 403 with error text |
| Helper Functions | ||
| TemplateField generation | Calling TemplateField() with context | Returns HTML hidden input with token |
| Protect middleware | Creating middleware with Protect() | Secure cookies enabled by default |
| ProtectDev middleware | Creating middleware with ProtectDev() | Insecure cookies for development |
| GenerateSecret uniqueness | Generating multiple secrets | Each secret is unique and 32 bytes |
| Validation Logic | ||
| Valid token validation | Validating matching tokens with correct secret | Returns true |
| Mismatched tokens | Validating different tokens | Returns false |
| Invalid signature | Validating token with wrong secret | Returns false |
| Malformed token | Validating token without signature separator | Returns false |
| Token Generation | ||
| Token format | Generated token structure | Contains random bytes and HMAC signature separated by ”.” |
| Token uniqueness | Generating 100 tokens | All tokens are unique |
| Configuration Validation | ||
| Panics without secret | Creating middleware with empty secret | Panics with error message |
| Panics with invalid TokenLookup | Creating middleware with malformed TokenLookup | Panics with error message |