@tadacafe/security
v1.0.3
Published
Framework-agnostic security utilities for web applications including HMAC generation, origin validation, and client-side security helpers
Maintainers
Readme
@tadacafe/security
Framework-agnostic security utilities for web applications including HMAC generation, origin validation, and client-side security helpers.
Features
- 🔒 HMAC Generation & Verification - Cryptographically secure signatures with configurable algorithms
- 🌐 Origin Validation - Request origin validation for CORS and CSRF protection
- 🛡️ Client Security - Secure form data preparation with timestamps and nonces
- ⏰ Timestamp Validation - Prevent replay attacks with configurable time windows
- 🔧 Framework Agnostic - Works in Node.js, browsers, and Cloudflare Workers
- 📝 TypeScript First - Complete type safety with comprehensive interfaces
Installation
npm install @tadacafe/securityQuick Start
HMAC Operations
import { generateHMAC, verifyHMAC } from '@tadacafe/security';
// Generate HMAC signature
const signature = await generateHMAC('my data', {
secret: 'my-secret-key',
algorithm: 'SHA-256',
});
// Verify HMAC signature
const isValid = await verifyHMAC('my data', signature, {
secret: 'my-secret-key',
algorithm: 'SHA-256',
});Origin Validation
import { isValidOrigin } from '@tadacafe/security';
const isValid = isValidOrigin(request, {
allowedOrigins: 'https://example.com,https://www.example.com',
allowRefererFallback: true,
enableDebugLogging: true,
});
if (!isValid) {
return new Response('Forbidden', { status: 403 });
}Secure Form Data
import { prepareSecureFormData } from '@tadacafe/security';
const secureData = await prepareSecureFormData(
{ name: 'John', email: '[email protected]' },
{ formSecret: 'my-secret-key' }
);
// Result includes original data plus timestamp, nonce, and hmac
console.log(secureData);
// {
// name: 'John',
// email: '[email protected]',
// timestamp: 1634567890123,
// nonce: 'a1b2c3d4e5f6789012345678901234567890abcd',
// hmac: '...'
// }API Reference
Cryptographic Functions
generateNonce(length?: number): string
Generate a cryptographically secure nonce.
- length: Length of the nonce in bytes (default: 16)
- Returns: Hexadecimal string representation of the nonce
generateHMAC(data: string, config: HMACConfig): Promise<string>
Generate HMAC signature for data.
- data: The data to sign
- config: HMAC configuration
- Returns: Promise resolving to hexadecimal HMAC signature
verifyHMAC(data: string, hmac: string, config: HMACConfig): Promise<boolean>
Verify HMAC signature using constant-time comparison.
- data: The original data that was signed
- hmac: The HMAC signature to verify
- config: HMAC configuration
- Returns: Promise resolving to verification result
isValidTimestamp(timestamp: number, config?: TimestampValidationConfig): boolean
Validate request timestamp to prevent replay attacks.
- timestamp: The timestamp to validate (in milliseconds)
- config: Configuration for timestamp validation
- Returns: True if timestamp is valid
Origin Validation Functions
isValidOrigin(request: Request, config: OriginValidationConfig): boolean
Validate request origin against allowed origins list.
- request: The incoming HTTP request
- config: Origin validation configuration
- Returns: True if request origin is valid
isValidOriginFromEnv(request: Request, options?): boolean
Convenience function for validating origin using environment variables configured in options or process environment.
- options: (Optional) Additional options or overrides for environment-based configuration
- Returns: True if request origin is valid based on environment configuration
Client Security
prepareSecureFormData<T>(formData: T, config: SecureFormConfig): Promise<T & SecuredFormData>
Prepare secure form data by adding timestamp, nonce, and HMAC signature.
createSecureFormPreparer(defaultConfig: SecureFormConfig): Function
Create a reusable secure form preparation function with pre-configured settings.
getFormSecret(sources: object, fallback?: string): string
Utility to resolve form secret from various sources with fallback.
Configuration Interfaces
HMACConfig
interface HMACConfig {
secret: string;
algorithm?: 'SHA-1' | 'SHA-256' | 'SHA-384' | 'SHA-512'; // default: 'SHA-256'
}OriginValidationConfig
interface OriginValidationConfig {
allowedOrigins: string | string[];
allowRefererFallback?: boolean; // default: true
enableDebugLogging?: boolean; // default: false
}TimestampValidationConfig
interface TimestampValidationConfig {
maxAgeMinutes?: number; // default: 10
maxClockSkewMs?: number; // default: 60000 (1 minute)
}SecureFormConfig
interface SecureFormConfig {
formSecret: string;
hmacConfig?: Omit<HMACConfig, 'secret'>;
}Environment Support
This package works in multiple environments:
- Node.js: Full support for all features
- Browser: Full support with Web Crypto API
- Cloudflare Workers: Full support in Worker runtime
- Vite/Webpack: Compatible with modern bundlers
Security Best Practices
HMAC Secrets
- Use cryptographically strong secrets (minimum 32 characters)
- Store secrets securely (environment variables, secret managers)
- Rotate secrets regularly
- Never expose secrets in client-side code
Origin Validation Best Practices
- Always validate origins for sensitive operations
- Use HTTPS origins only in production
- Consider both Origin and Referer headers for maximum compatibility
- Enable debug logging in development, disable in production
Timestamp Validation
- Use reasonable time windows (5-10 minutes)
- Account for clock skew between client and server
- Implement proper time synchronization
- Log suspicious timestamp patterns
Usage Examples
Cloudflare Workers
import {
isValidOriginFromEnv,
verifyHMAC,
isValidTimestamp,
} from '@tadacafe/security';
export default {
async fetch(request, env) {
// Validate origin
if (!isValidOriginFromEnv(request, env, { enableDebugLogging: true })) {
return new Response('Forbidden', { status: 403 });
}
// Parse and verify form data
const data = await request.json();
const { timestamp, nonce, hmac, ...formData } = data;
// Validate timestamp
if (!isValidTimestamp(timestamp, { maxAgeMinutes: 10 })) {
return new Response('Request expired', { status: 400 });
}
// Verify HMAC
const dataToVerify = JSON.stringify({ ...formData, timestamp, nonce });
const isValidHMAC = await verifyHMAC(dataToVerify, hmac, {
secret: env.CONTACT_FORM_SECRET,
});
if (!isValidHMAC) {
return new Response('Invalid signature', { status: 400 });
}
// Process valid request...
},
};React Component
import { prepareSecureFormData, getFormSecret } from '@tadacafe/security';
function ContactForm() {
const handleSubmit = async (formData) => {
const formSecret = getFormSecret({
vite: import.meta.env.VITE_CONTACT_FORM_SECRET,
});
const secureData = await prepareSecureFormData(formData, { formSecret });
const response = await fetch('/api/contact', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(secureData),
});
};
}License
MIT
