@opensourceframework/next-csrf
v0.3.1
Published
CSRF protection for Next.js applications - Maintained fork of next-csrf
Maintainers
Readme
@opensourceframework/next-csrf
CSRF protection for Next.js applications
This is a maintained fork of the original next-csrf package by Juan Olvera (j0lv3r4). The original package was last updated in April 2023 and has been archived. This fork continues maintenance with updates for Next.js 14-16 support and TypeScript improvements.
Attribution
- Original Author: Juan Olvera
- Original Repository: https://github.com/j0lv3r4/next-csrf
- Original License: MIT
Features
- Synchronizer Token Pattern: Implements CSRF mitigation using the Synchronizer Token Pattern
- Signed Cookies: Optional cookie signing for enhanced security
- Next.js Integration: Works with both Pages Router (API routes, getServerSideProps) and App Router
- TypeScript Support: Full TypeScript support with type definitions
- Customizable: Configurable token keys, error messages, and cookie options
Installation
# npm
npm install @opensourceframework/next-csrf
# yarn
yarn add @opensourceframework/next-csrf
# pnpm
pnpm add @opensourceframework/next-csrfQuick Start
1. Create a CSRF configuration file
// lib/csrf.ts
import { nextCsrf } from '@opensourceframework/next-csrf';
const { csrf, setup } = nextCsrf({
// Required: A secret key for signing cookies (use environment variable in production)
secret: process.env.CSRF_SECRET,
// Optional: Customize the token cookie name (default: 'XSRF-TOKEN')
tokenKey: 'XSRF-TOKEN',
// Optional: Custom error message (default: 'Invalid CSRF token')
csrfErrorMessage: 'Invalid CSRF token',
// Optional: Methods to ignore (default: ['GET', 'HEAD', 'OPTIONS'])
ignoredMethods: ['GET', 'HEAD', 'OPTIONS'],
// Optional: Cookie options
cookieOptions: {
httpOnly: true,
path: '/',
sameSite: 'lax',
secure: process.env.NODE_ENV === 'production',
},
});
export { csrf, setup };2. Set up tokens on initial page load
For Pages Router:
// pages/login.tsx
import { setup } from '../lib/csrf';
function LoginPage() {
const handleSubmit = async (event) => {
event.preventDefault();
const response = await fetch('/api/protected', {
method: 'POST',
});
if (response.ok) {
console.log('Request succeeded with CSRF protection');
}
};
return (
<form onSubmit={handleSubmit}>
<button type="submit">Submit</button>
</form>
);
}
// Setup CSRF tokens on this page
export const getServerSideProps = setup(async ({ req, res }) => {
return { props: {} };
});
export default LoginPage;3. Protect API routes
// pages/api/protected.ts
import { csrf } from '../../lib/csrf';
import type { NextApiRequest, NextApiResponse } from 'next';
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
return res.status(200).json({
message: 'This API route is protected with CSRF!'
});
};
export default csrf(handler);API Reference
nextCsrf(options)
Creates CSRF middleware functions.
Parameters:
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| secret | string | - | Secret key for signing cookies. Recommended for production. |
| tokenKey | string | 'XSRF-TOKEN' | Name of the CSRF token cookie. |
| csrfErrorMessage | string | 'Invalid CSRF token' | Error message for invalid tokens. |
| ignoredMethods | string[] | ['GET', 'HEAD', 'OPTIONS'] | HTTP methods to skip CSRF validation. |
| cookieOptions | CookieSerializeOptions | See below | Cookie serialization options. |
Default Cookie Options:
{
httpOnly: true,
path: '/',
sameSite: 'lax',
secure: process.env.NODE_ENV === 'production',
}Returns:
An object with two middleware functions:
setup- Middleware to create and set CSRF tokenscsrf- Middleware to validate CSRF tokens
setup(handler)
Middleware that creates CSRF secret and token cookies.
- Works with both API routes (
req, res) andgetServerSideProps(context) - Creates two cookies:
csrfSecretand the token cookie (default:XSRF-TOKEN) - If
secretoption is provided, the token is signed
csrf(handler)
Middleware that validates CSRF tokens on incoming requests.
- Skips validation for ignored methods (default: GET, HEAD, OPTIONS)
- Validates token against secret
- Verifies signed tokens if
secretwas provided - Generates a new token after successful validation
HttpError
Custom error class for CSRF-related HTTP errors.
import { HttpError } from '@opensourceframework/next-csrf';
throw new HttpError(403, 'Custom error message');Migration from next-csrf
If you're migrating from the original next-csrf package:
1. Update imports
- import { nextCsrf } from 'next-csrf';
+ import { nextCsrf } from '@opensourceframework/next-csrf';2. Update package.json
- "next-csrf": "^0.2.1"
+ "@opensourceframework/next-csrf": "^0.2.2"3. No code changes required
The API is fully compatible with the original package.
Security Considerations
Always use a secret in production: Set
secretto a cryptographically secure random string.Use HTTPS in production: Set
secure: truein cookie options for production environments.Regenerate tokens: The middleware automatically regenerates tokens after each validated request.
Session invalidation: If you change the
secret, all existing sessions will be invalidated.Cookie settings: The default settings (
httpOnly: true,sameSite: 'lax') provide good baseline security.
Compatibility
- Next.js: 12.x, 13.x, 14.x, 15.x, 16.x
- Node.js: 18.x or higher
- TypeScript: 5.x
How It Works
The package implements the Synchronizer Token Pattern:
Setup Phase: When a user visits a page with CSRF setup, the middleware:
- Generates a unique CSRF secret
- Creates a token from the secret
- Stores both in HTTP-only cookies
- Optionally signs the token with your secret
Validation Phase: When a user submits a request:
- The middleware extracts the token from cookies
- If signed, it verifies the signature
- It validates the token against the secret
- If valid, it generates a new token for the next request
Development
# Install dependencies
pnpm install
# Build the package
pnpm build
# Run tests
pnpm test
# Run tests with coverage
pnpm test:coverage
# Type checking
pnpm typecheckLicense
MIT License - See LICENSE for details.
Credits
- Original implementation by Juan Olvera
- Maintained by the OpenSource Framework team
Contributing
Contributions are welcome! Please read the contributing guidelines first.
