auth/src/config.js

79 lines
3.2 KiB
JavaScript

// src/config.js
// === ADDED FOR RATE LIMITING ===
// Environment variables for rate limiting (used in middleware/rateLimitMiddleware.js):
// - REDIS_URL: Full Redis connection URL (e.g., redis://localhost:6379)
// OR use REDIS_HOST and REDIS_PORT separately
// - REDIS_HOST: Redis host (default: localhost)
// - REDIS_PORT: Redis port (default: 6379)
// - REDIS_PASSWORD: Redis password (optional)
// - OTP_REQ_PHONE_10MIN_LIMIT: Max OTP requests per phone per 10 min (default: 3)
// - OTP_REQ_PHONE_DAY_LIMIT: Max OTP requests per phone per 24 hours (default: 10)
// - OTP_REQ_IP_10MIN_LIMIT: Max OTP requests per IP per 10 min (default: 20)
// - OTP_REQ_IP_DAY_LIMIT: Max OTP requests per IP per 24 hours (default: 100)
// - OTP_VERIFY_MAX_ATTEMPTS: Max verification attempts per OTP (default: 5)
// - OTP_VERIFY_FAILED_PER_HOUR_LIMIT: Max failed verifications per phone per hour (default: 10)
// - OTP_TTL_SECONDS: OTP validity in seconds (default: 120, i.e., 2 minutes)
//
// === SECURITY HARDENING: JWT KEY ROTATION ===
// - JWT_ACTIVE_KEY_ID: Key ID to use for signing new tokens (default: '1')
// - JWT_KEYS_JSON: JSON object mapping key IDs to secrets, e.g. '{"1":"secret1","2":"secret2"}'
// OR use legacy: JWT_ACCESS_SECRET, JWT_REFRESH_SECRET
// - JWT_REFRESH_KEY_ID: Key ID for refresh tokens (default: same as active key)
// - JWT_ISSUER: Issuer claim (iss) for tokens (default: 'farm-auth-service')
// - JWT_AUDIENCE: Audience claim (aud) for tokens (default: 'mobile-app')
//
// === SECURITY HARDENING: IP/DEVICE RISK ===
// - BLOCKED_IP_RANGES: Comma-separated CIDR blocks to block (e.g., '10.0.0.0/8,172.16.0.0/12')
// - REQUIRE_OTP_ON_SUSPICIOUS_REFRESH: Require OTP re-verification on suspicious refresh (default: false)
//
// === SECURITY HARDENING: ACCESS TOKEN REPLAY MITIGATION ===
// - STEP_UP_OTP_WINDOW_MINUTES: Time window for "recent" OTP verification (default: 5)
//
// === SECURITY HARDENING: CORS ===
// - CORS_ALLOWED_ORIGINS: Comma-separated list of allowed origins (REQUIRED in production)
// Example: 'https://app.example.com,https://api.example.com'
// WARNING: Never use '*' when credentials or tokens are involved
require('dotenv').config();
const REQUIRED_ENV = [
'DATABASE_URL',
'JWT_ACCESS_SECRET',
'JWT_REFRESH_SECRET',
];
const missing = REQUIRED_ENV.filter((key) => !process.env[key]);
if (missing.length > 0) {
throw new Error(
`Missing required environment variables: ${missing.join(', ')}`
);
}
const corsAllowedOrigins = (process.env.CORS_ALLOWED_ORIGINS || '')
.split(',')
.map((origin) => origin.trim())
.filter(Boolean);
const isProduction = process.env.NODE_ENV === 'production';
const refreshMaxIdleMinutes = Number(
process.env.REFRESH_MAX_IDLE_MINUTES || 4320
);
if (isProduction && corsAllowedOrigins.length === 0) {
throw new Error(
'CORS_ALLOWED_ORIGINS must be set (comma-separated) in production'
);
}
module.exports = {
databaseUrl: process.env.DATABASE_URL,
jwtAccessSecret: process.env.JWT_ACCESS_SECRET,
jwtRefreshSecret: process.env.JWT_REFRESH_SECRET,
jwtAccessTtl: process.env.JWT_ACCESS_TTL || '15m',
jwtRefreshTtl: process.env.JWT_REFRESH_TTL || '7d',
corsAllowedOrigins,
isProduction,
refreshMaxIdleMinutes,
};