@ordojs/security
Version:
Security package for OrdoJS with XSS, CSRF, and injection protection
255 lines (194 loc) • 6.9 kB
Markdown
# CSRF Protection Module
This module provides comprehensive Cross-Site Request Forgery (CSRF) protection for OrdoJS
applications. It implements both session-based token validation and the double-submit cookie pattern
to protect against CSRF attacks.
## Features
- **Session-based CSRF tokens**: Secure token generation and validation tied to user sessions
- **Double-submit cookie pattern**: Alternative protection method using matching cookie and header
tokens
- **Automatic token injection**: Client-side JavaScript for automatic form and AJAX request
protection
- **Flexible configuration**: Customizable token expiry, cookie settings, and header names
- **Express.js integration**: Ready-to-use middleware for Express applications
- **TypeScript support**: Full type safety with comprehensive interfaces
## Quick Start
```typescript
import { CSRFManager } from '@ordojs/security';
// Initialize CSRF protection
const csrfManager = new CSRFManager({
secret: 'your-secret-key-here',
tokenExpiry: 60 * 60 * 1000, // 1 hour
});
// Generate a token for a user session
const sessionId = 'user-session-123';
const token = csrfManager.generateToken(sessionId);
// Validate the token
const isValid = csrfManager.validateToken(token.value, sessionId);
console.log('Token valid:', isValid.valid);
```
## Configuration
```typescript
interface CSRFConfig {
secret: string; // Required: Secret key for token signing
tokenExpiry?: number; // Token expiration (default: 1 hour)
cookieName?: string; // Cookie name (default: '__csrf-token')
headerName?: string; // Header name (default: 'X-CSRF-Token')
fieldName?: string; // Form field name (default: '_csrf')
secureCookie?: boolean; // Use secure cookies (default: true)
httpOnlyCookie?: boolean; // Use httpOnly cookies (default: true)
sameSite?: 'strict' | 'lax' | 'none'; // SameSite attribute (default: 'strict')
}
```
## Usage Patterns
### 1. Session-based Protection
Best for traditional server-rendered applications with user sessions:
```typescript
// Generate token for user session
const token = csrfManager.generateToken(sessionId);
// Add to form
const formHTML = `
<form method="POST" action="/submit">
${csrfManager.generateFormField(sessionId)}
<input type="text" name="data" />
<button type="submit">Submit</button>
</form>
`;
// Validate on form submission
const request = {
headers: { 'X-CSRF-Token': tokenFromRequest },
sessionId: userSessionId,
};
const validation = csrfManager.validateRequest(request);
if (!validation.valid) {
throw new Error('CSRF validation failed');
}
```
### 2. Double-Submit Cookie Pattern
Best for stateless applications or APIs:
```typescript
// Set up double-submit protection
const response = csrfManager.setupDoubleSubmitProtection(sessionId);
// Send cookie and header to client
res.cookie(response.cookies[0].name, response.cookies[0].value, response.cookies[0].options);
res.header('X-CSRF-Token', response.headers['X-CSRF-Token']);
// Validate matching tokens
const request = {
headers: { 'X-CSRF-Token': headerToken },
cookies: { '__csrf-token': cookieToken },
};
const validation = csrfManager.validateDoubleSubmit(request);
```
### 3. Client-side Integration
Automatic protection for forms and AJAX requests:
```html
<!DOCTYPE html>
<html>
<head>
<meta name="csrf-token" content="your-token-here" />
</head>
<body>
<!-- Forms will automatically get CSRF tokens -->
<form method="POST" action="/api/data">
<input type="text" name="value" />
<button type="submit">Submit</button>
</form>
<script>
// Include the generated client script
${csrfManager.generateClientScript(sessionId)}
</script>
</body>
</html>
```
### 4. Express.js Middleware
```typescript
import express from 'express';
import { CSRFManager } from '@ordojs/security';
const app = express();
const csrfManager = new CSRFManager({ secret: 'your-secret' });
// CSRF protection middleware
app.use((req, res, next) => {
if (req.method === 'GET') return next();
const validation = csrfManager.validateRequest({
headers: req.headers,
body: req.body,
cookies: req.cookies,
sessionId: req.session.id,
});
if (!validation.valid) {
return res.status(403).json({ error: validation.error });
}
next();
});
// Generate token endpoint
app.get('/csrf-token', (req, res) => {
const token = csrfManager.generateToken(req.session.id);
res.json({ token: token.value });
});
```
## Security Considerations
### Token Security
- Tokens are cryptographically signed using HMAC-SHA256
- Constant-time comparison prevents timing attacks
- Tokens include expiration timestamps
- Random data prevents token prediction
### Session Management
- Tokens are tied to specific sessions
- Automatic cleanup of expired tokens
- Session isolation prevents cross-session attacks
### Cookie Security
- Secure flag for HTTPS-only transmission
- HttpOnly flag prevents JavaScript access
- SameSite attribute prevents cross-site requests
- Configurable expiration times
## Best Practices
1. **Use HTTPS**: Always use HTTPS in production to protect tokens in transit
2. **Rotate secrets**: Regularly rotate your secret keys
3. **Short expiry**: Use reasonable token expiration times (1-2 hours)
4. **Validate origin**: Consider additional origin/referer validation
5. **Monitor failures**: Log and monitor CSRF validation failures
## API Reference
### CSRFManager
#### Methods
- `generateToken(sessionId: string): CSRFToken`
- `validateToken(tokenValue: string, sessionId: string): CSRFValidationResult`
- `setupDoubleSubmitProtection(sessionId: string): CSRFResponse`
- `validateDoubleSubmit(request: CSRFRequest): CSRFValidationResult`
- `validateRequest(request: CSRFRequest): CSRFValidationResult`
- `generateFormField(sessionId: string): string`
- `generateClientScript(sessionId?: string): string`
- `consumeToken(sessionId: string, tokenValue: string): boolean`
- `removeSession(sessionId: string): boolean`
- `getStats(): { totalSessions: number; totalTokens: number; activeSessions: number }`
- `destroy(): void`
### Types
See `types.ts` for complete type definitions including:
- `CSRFConfig`
- `CSRFToken`
- `CSRFRequest`
- `CSRFResponse`
- `CSRFValidationResult`
- `CSRFSession`
## Testing
The module includes comprehensive tests covering:
- Token generation and validation
- Session management
- Double-submit cookie pattern
- Request validation
- Client script generation
- Error handling
- Configuration options
Run tests with:
```bash
npm test src/csrf/csrf-manager.test.ts
```
## Performance
- Efficient in-memory token storage
- Automatic cleanup of expired tokens
- Constant-time cryptographic operations
- Minimal overhead for validation
- Configurable cleanup intervals
## Compatibility
- Node.js 16+
- Express.js 4+
- Modern browsers (ES2018+)
- TypeScript 4.5+