8.9 KiB
trigger
| trigger |
|---|
| always_on |
Security Patterns for GoodGo Microservices
When to Use This Skill
Use this skill when:
- Implementing authentication and authorization in any service
- Protecting sensitive data (PII, credentials, tokens)
- Validating user inputs and file uploads
- Implementing rate limiting and DDoS protection
- Setting up audit logging and security monitoring
- Encrypting data at rest and in transit
- Managing secrets and credentials
- Implementing security testing
- Handling security incidents
- Designing secure API endpoints
Core Security Principles
- Defense in Depth: Multiple layers of security controls
- Least Privilege: Grant minimum required permissions
- Fail Secure: Default to deny access
- Separation of Duties: Critical operations require multiple approvals
- Audit Everything: Log all security-relevant events
- Encrypt Sensitive Data: PII, tokens, credentials must be encrypted
- Validate All Inputs: Never trust user input
- Principle of Least Exposure: Minimize attack surface
- Secure by Default: Security built-in, not bolted on
- Assume Breach: Design for detection and response
Authentication & Authorization
JWT Token Validation
Extract tokens from Authorization header or cookies, verify with jwtService.verifyAccessToken(), and attach user payload to request. Return 401 for missing/invalid tokens.
// Key pattern - see references/REFERENCE.md for full implementation
const authHeader = req.headers.authorization;
const token = authHeader?.startsWith('Bearer ') ? authHeader.substring(7) : req.cookies?.access_token;
const payload = await jwtService.verifyAccessToken(token);
req.user = { id: payload.sub, roles: payload.roles || [], permissions: payload.permissions || [] };
Role-Based Authorization (RBAC)
Use requireRole() middleware for role checks and requirePermission() for fine-grained access control with resource:action format.
// Usage pattern
router.post('/api/v1/users', authenticate(), requirePermission('users', 'create'), userController.create);
router.delete('/api/v1/admin', authenticate(), requireRole('admin', 'superadmin'), adminController.delete);
Resource Ownership
Validate users can only access their own resources using requireOwnership() middleware.
Data Protection
Encryption
- Use AES-256-GCM for encrypting PII at rest
- Store encrypted data as
iv:tag:ciphertextformat - Require 32+ character ENCRYPTION_KEY
Password Hashing
- Always use bcrypt with cost factor 12 in production
- Never log passwords - sanitize before logging
Token Storage
- Hash tokens with SHA-256 before database storage
- Use
crypto.randomBytes(32)for secure token generation
Input Validation
Zod Schema Validation
Always validate inputs with Zod schemas before processing:
const CreateUserDto = z.object({
email: z.string().email(),
password: z.string().min(8).regex(/[A-Z]/).regex(/[a-z]/).regex(/[0-9]/).regex(/[^A-Za-z0-9]/),
phone: z.string().regex(/^\+[1-9]\d{1,14}$/).optional(),
name: z.string().min(1).max(255)
});
// In controller
const dto = CreateUserDto.parse(req.body);
File Upload Validation
- Check file size (max 10MB default)
- Validate MIME type against whitelist
- Verify content with
file-typelibrary to prevent MIME spoofing
SQL Injection Prevention
Always use Prisma parameterized queries - never string concatenation for queries.
Rate Limiting
Configure Redis-backed rate limiting for all endpoints:
| Limiter Type | Window | Max Requests | Use Case |
|---|---|---|---|
| Standard | 15 min | 100 | General API endpoints |
| Strict | 1 hour | 10 | Sensitive operations |
| Login | 15 min | 5 | Authentication endpoints |
router.post('/api/v1/auth/login', loginLimiter, authController.login);
Security Headers
Use Helmet middleware with CSP, HSTS, and additional headers:
X-Content-Type-Options: nosniffX-Frame-Options: DENYX-XSS-Protection: 1; mode=blockReferrer-Policy: strict-origin-when-cross-origin
CORS Configuration
- Whitelist allowed origins from environment variables
- Enable credentials for authenticated requests
- Set
maxAge: 86400(24 hours) for preflight caching
Secrets Management
- Never hardcode secrets - use environment variables
- Validate secrets with Zod schema at startup
- Use secret managers in production (AWS Secrets Manager, Vault, etc.)
- Rotate secrets quarterly
const secretsSchema = z.object({
JWT_SECRET: z.string().min(32),
DATABASE_URL: z.string().url(),
ENCRYPTION_KEY: z.string().min(32).optional()
});
Audit Logging
Log all security-relevant events with sanitized details:
await auditService.logSecurityEvent('LOGIN_SUCCESS', user.id, { email: user.email }, req);
await auditService.logSecurityEvent('PERMISSION_DENIED', user.id, { resource, action }, req);
Sanitize sensitive fields: password, token, secret, ssn, creditCard.
Error Handling
- Log full errors internally
- Never expose user existence (use generic "Invalid credentials")
- Show stack traces only in development
- Return sanitized error codes in production
Security Testing
Write tests for:
- SQL injection prevention
- XSS attack prevention
- Authentication enforcement
- Authorization enforcement
- Rate limiting effectiveness
Best Practices
- All endpoints require authentication (except public)
- Authorization checks at every protected route
- Input validation with Zod on all user input
- Rate limiting on all endpoints
- Error messages sanitized in production
- PII encrypted at rest with AES-256-GCM
- Passwords hashed with bcrypt (cost 12+)
- Tokens hashed before database storage
- HTTPS enforced (TLS 1.2+)
- Security headers via Helmet
- Audit logging for security events
- Dependencies scanned for vulnerabilities
- File uploads validated (size, type, content)
Common Mistakes
1. Weak Password Hashing
// BAD: Low cost factor
const hash = await bcrypt.hash(password, 8);
// GOOD: Use cost 12
const hash = await bcrypt.hash(password, 12);
2. Hardcoded Secrets
// BAD
const JWT_SECRET = "my-secret-key";
// GOOD
const JWT_SECRET = process.env.JWT_SECRET;
if (!JWT_SECRET) throw new Error('JWT_SECRET required');
3. Missing Input Validation
// BAD
const user = await prisma.user.findUnique({ where: { id: req.params.id } });
// GOOD
const { id } = z.object({ id: z.string().cuid() }).parse(req.params);
const user = await prisma.user.findUnique({ where: { id } });
4. Logging Sensitive Data
// BAD
logger.info('User login', { email, password });
// GOOD
logger.info('User login', { email, password: '[REDACTED]' });
5. Exposing User Existence
// BAD
if (!user) throw new Error('User not found');
// GOOD
if (!user || !await bcrypt.compare(password, user.passwordHash)) {
throw new Error('Invalid credentials');
}
Quick Reference
| Security Area | Implementation |
|---|---|
| Password hashing | bcrypt.hash(password, 12) |
| JWT Access Token | 15 minutes expiry |
| JWT Refresh Token | 7 days expiry |
| Rate limiting | Standard: 100/15min, Strict: 10/hour, Login: 5/15min |
| Encryption | AES-256-GCM for PII |
| Input validation | Zod schemas, always parse before use |
| SQL injection | Use Prisma (parameterized by default) |
| Security headers | helmet middleware |
| CORS | Whitelist origins, credentials: true |
Essential Imports:
import bcrypt from 'bcrypt';
import helmet from 'helmet';
import rateLimit from 'express-rate-limit';
import { z } from 'zod';
import { jwtService } from '@goodgo/auth-sdk';
Security Checklist
Before deploying any service:
- All endpoints require authentication (except public)
- Authorization checks implemented (RBAC/ABAC)
- Input validation with Zod schemas
- Rate limiting configured
- Error messages sanitized (no info disclosure)
- PII encrypted at rest
- Passwords hashed with bcrypt (cost 12+)
- Tokens hashed before storing
- Secrets in environment variables (never hardcoded)
- HTTPS enforced (TLS 1.2+)
- CORS configured correctly
- Security headers set (helmet)
- Audit logging enabled
- SQL injection prevented (use Prisma)
- XSS prevention (input sanitization)
- File upload validation
- Security tests passing
- Dependencies scanned for vulnerabilities
- Secrets rotation plan in place
Resources
- Detailed Code Examples - Full implementation examples
- OWASP Top 10
- OWASP API Security Top 10
- Node.js Security Best Practices
- Express Security Best Practices