Sync Token Pattern for Form Apps
@fastify/csrf-protection
For cookie-based session apps, @fastify/csrf-protection issues a token the browser must echo back on mutating requests, blocking cross-site form forgery.
What you'll learn
- Install @fastify/csrf-protection alongside cookies or sessions
- Issue a token on GET
- Verify tokens on POST, PUT, and DELETE
CSRF only matters when authentication is automatic — cookies and Basic Auth. If you carry a Bearer token in JS, attackers cannot forge requests cross-site. For form apps, you need a synchroniser token.
Install & Register
npm install @fastify/csrf-protection @fastify/cookie import cookie from '@fastify/cookie'
import csrf from '@fastify/csrf-protection'
await app.register(cookie)
await app.register(csrf, { cookieOpts: { signed: true } }) Issue a Token
Expose an endpoint your client can call to get a fresh token:
app.get('/csrf', async (req, reply) => {
return { token: reply.generateCsrf() }
}) The token is signed and stored in a cookie; the value is returned to the client to echo in a header or hidden field.
Verify on Mutating Routes
app.post(
'/transfer',
{ preHandler: app.csrfProtection },
async (req) => {
// ... handler runs only if the token verifies ...
return { ok: true }
},
) If the token is missing or wrong, the request is rejected with 403 before your handler runs. Apply it globally to all mutating routes — or to a route prefix.
@fastify/helmet →