@csrf-armor/core
Version:
Framework-agnostic CSRF protection core functionality
169 lines (168 loc) • 5.74 kB
text/typescript
import { CsrfAdapter, CsrfConfig } from "./types.mjs";
//#region src/csrf.d.ts
declare class CsrfProtection<TRequest = unknown, TResponse = unknown> {
private readonly config;
private readonly adapter;
/**
* Creates a new CSRF protection instance.
*
* @param adapter - Framework-specific adapter for request/response handling
* @param userConfig - Optional configuration overrides
*/
constructor(adapter: CsrfAdapter<TRequest, TResponse>, userConfig?: CsrfConfig);
/**
* Checks if a request should be excluded from CSRF protection.
*
* @param request - The CSRF request to check
* @returns true if the request should be skipped
* @internal
*/
private shouldSkipProtection;
/**
* Attempts to reuse existing CSRF tokens if they are still valid.
*
* @param request - The CSRF request containing potential existing tokens
* @returns Token data if reuse is possible, null otherwise
* @internal
*/
private attemptTokenReuse;
/**
* Builds the CSRF response with headers and cookies.
*
* @param tokenData - The token data to include in the response
* @returns The CSRF response object
* @internal
*/
private buildCsrfResponse;
/**
* Protects a request/response pair against CSRF attacks.
*
* This is the main method that applies CSRF protection to incoming requests.
* It handles both token generation for safe methods (GET, HEAD, OPTIONS) and
* token validation for state-changing methods (POST, PUT, DELETE, etc.).
*
* The method:
* 1. Extracts request data using the framework adapter
* 2. Checks if the request should be excluded or skipped
* 3. For safe methods: generates and sets new CSRF tokens
* 4. For unsafe methods: validates existing tokens using the configured strategy
* 5. Applies response data (headers, cookies) using the adapter
*
* @param request - Framework-specific request object
* @param response - Framework-specific response object
* @returns Promise resolving to protection result with success status and modified response
*
* @example
* ```typescript
* // Basic usage in middleware
* const result = await csrf.protect(req, res);
* if (!result.success) {
* return res.status(403).json({
* error: 'CSRF validation failed',
* reason: result.reason
* });
* }
*
* // Token is available for safe methods
* if (result.token) {
* console.log('Generated CSRF token:', result.token);
* }
*
* // Continue with the modified response
* return result.response;
* ```
*
* @example
* ```typescript
* // Error handling with specific reasons
* const result = await csrf.protect(req, res);
* if (!result.success) {
* switch (result.reason) {
* case 'Invalid token':
* return res.status(403).json({ error: 'CSRF token is invalid' });
* case 'Token expired':
* return res.status(403).json({ error: 'CSRF token has expired' });
* case 'Origin mismatch':
* return res.status(403).json({ error: 'Request origin not allowed' });
* default:
* return res.status(403).json({ error: 'CSRF validation failed' });
* }
* }
* ```
*/
protect(request: TRequest, response: TResponse): Promise<{
success: boolean;
response: TResponse;
token?: string;
reason?: string;
}>;
private generateTokensForStrategy;
}
/**
* Factory function to create a CSRF protection instance.
*
* Convenient alternative to using the CsrfProtection constructor directly.
* This function is the recommended way to create CSRF protection instances
* as it provides better type inference and a cleaner API.
*
* @public
* @template TRequest - Framework-specific request type
* @template TResponse - Framework-specific response type
* @param adapter - Framework adapter implementing CsrfAdapter interface
* @param config - Optional CSRF configuration (uses secure defaults if not provided)
* @returns Configured CSRF protection instance ready for use
*
* @example
* ```typescript
* import { createCsrfProtection } from '@csrf-armor/core';
* import { ExpressAdapter } from '@csrf-armor/express';
*
* // Basic setup with defaults
* const csrf = createCsrfProtection(new ExpressAdapter());
*
* // Custom configuration
* const csrf = createCsrfProtection(new ExpressAdapter(), {
* strategy: 'signed-double-submit',
* secret: process.env.CSRF_SECRET,
* token: {
* expiry: 7200, // 2 hours
* fieldName: 'authenticity_token'
* },
* excludePaths: ['/api/public'],
* allowedOrigins: ['https://yourdomain.com']
* });
*
* // Use in middleware
* app.use(async (req, res, next) => {
* const result = await csrf.protect(req, res);
* if (result.success) {
* next();
* } else {
* res.status(403).json({ error: result.reason });
* }
* });
* ```
*
* @example
* ```typescript
* // Framework-specific usage
*
* // Express.js
* import { ExpressAdapter } from '@csrf-armor/express';
* const expressCsrf = createCsrfProtection(new ExpressAdapter(), config);
*
* // Next.js
* import { NextjsAdapter } from '@csrf-armor/nextjs';
* const nextCsrf = createCsrfProtection(new NextjsAdapter(), config);
*
* // Custom framework
* class MyAdapter implements CsrfAdapter<MyRequest, MyResponse> {
* // Implementation...
* }
* const customCsrf = createCsrfProtection(new MyAdapter(), config);
* ```
*/
declare function createCsrfProtection<TRequest = unknown, TResponse = unknown>(adapter: CsrfAdapter<TRequest, TResponse>, config?: CsrfConfig): CsrfProtection<TRequest, TResponse>;
//#endregion
export { CsrfProtection, createCsrfProtection };
//# sourceMappingURL=csrf.d.mts.map