How to Fix CSRF Token Missing or Invalid Error
In this tutorial, you'll learn about How to Fix CSRF Token Missing or Invalid Error. We cover key concepts, practical examples, and best practices.
The Problem
Your form submission or API request returns:
CSRF token missing or incorrect
Or:
Invalid CSRF token: The security token submitted with this request is invalid or expired.
The server requires a CSRF (Cross-Site Request Forgery) token that the client did not provide, or the provided token is invalid or expired.
Quick Fix
1. Include the CSRF token in forms
For HTML forms with a server-rendered template:
<!-- Wrong — no CSRF token -->
<form action="/transfer" method="POST">
<input name="amount" value="100">
<button type="submit">Send</button>
</form>
<!-- Right — include CSRF token -->
<form action="/transfer" method="POST">
<input type="hidden" name="_csrf" value="{{csrfToken}}">
<input name="amount" value="100">
<button type="submit">Send</button>
</form>
2. Set CSRF token in AJAX requests
// Fetch the token from a cookie or meta tag
const csrfToken = document.querySelector('meta[name="csrf-token"]').content
// Wrong — no CSRF header
fetch('/api/transfer', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ amount: 100 })
})
// Right — include CSRF token header
fetch('/api/transfer', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': csrfToken
},
body: JSON.stringify({ amount: 100 })
})
3. Check the server-side CSRF middleware
// Express.js with csurf — ensure the middleware is configured
const csrf = require('csurf')
// Wrong — cookie not configured
app.use(csrf())
// Right — configure cookie
const csrfProtection = csrf({
cookie: {
httpOnly: true,
secure: true,
sameSite: 'strict'
}
})
app.use(csrfProtection)
4. Use double-submit cookie pattern
If using an SPA without server-rendered forms, set the token in a non-httpOnly cookie:
// Server sets a CSRF cookie (readable by JavaScript)
app.get('/api/csrf-token', (req, res) => {
const token = crypto.randomBytes(32).toString('hex')
res.cookie('csrf-token', token, {
httpOnly: false, // JavaScript needs to read it
secure: true,
sameSite: 'strict'
})
res.json({ csrfToken: token })
})
// Client reads the cookie and sends it as a header
5. Use SameSite cookies as an additional defense
// Set SameSite to 'strict' or 'lax'
res.cookie('session', token, {
httpOnly: true,
secure: true,
sameSite: 'strict' // Prevents CSRF for most cases
})
6. Exempt public endpoints from CSRF
// Exempt webhook endpoints that cannot provide CSRF tokens
app.use('/api/webhooks', (req, res, next) => {
req.csrfToken = () => '' // skip CSRF for webhooks
next()
})
Prevention
- Always include CSRF tokens in state-changing requests (POST, PUT, DELETE).
- Use SameSite cookies to prevent CSRF in modern browsers.
- Use framework-provided CSRF protection (Rails, Django, Spring).
- Set CSRF tokens in every form rendered by the server.
- Rotate CSRF tokens on login and logout.
Common Mistakes with token missing
- Forgetting
deriving (Show, Eq)on custom data types needed for debugging - Placing the wildcard pattern first in case expressions, making all subsequent patterns unreachable
- Using
headandtailinstead of pattern matching, causing runtime errors on empty lists
These mistakes appear frequently in real-world CSRF code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.
Practice Exercise
Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.
This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.
FAQ
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro