Skip to main content

api-security-best-practices

Implement secure API design patterns including authentication, authorization, input validation, rate limiting, and protection against common API vulnerabilities

Aller à l'installation

Informations de source

Dépôt
JantonioFC/skillsbank
Dernière activité de la source
4 août 2026 à 03:07
Langue détectée de SKILL.md
anglais
Étoiles
6
Forks
0

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
name
api-security-best-practices
description
Implement secure API design patterns including authentication, authorization, input validation, rate limiting, and protection against common API vulnerabilities
risk
safe
source
community
date_added
2026-02-27
license
MIT
> [!IMPORTANT] # API Security Best Practices ## Overview Guide developers in building secure APIs by implementing authentication, authorization, input validation, rate limiting, and protection against common vulnerabilities. This skill covers security patterns for REST, GraphQL, and WebSocket APIs. ## When to Use This Skill - Use when designing new API endpoints - Use when securing existing APIs - Use when implementing authentication and authorization - Use when protecting against API attacks (injection, DDoS, etc.) - Use when conducting API security reviews - Use when preparing for security audits - Use when implementing rate limiting and throttling - Use when handling sensitive data in APIs ## How It Works ### Step 1: Authentication & Authorization I'll help you implement secure authentication: - Choose authentication method (JWT, OAuth 2.0, API keys) - Implement token-based authentication - Set up role-based access control (RBAC) - Secure session management - Implement multi-factor authentication (MFA) ### Step 2: Input Validation & Sanitization Protect against injection attacks: - Validate all input data - Sanitize user inputs - Use parameterized queries - Implement request schema validation - Prevent SQL injection, XSS, and command injection ### Step 3: Rate Limiting & Throttling Prevent abuse and DDoS attacks: - Implement rate limiting per user/IP - Set up API throttling - Configure request quotas - Handle rate limit errors gracefully - Monitor for suspicious activity ### Step 4: Data Protection Secure sensitive data: - Encrypt data in transit (HTTPS/TLS) - Encrypt sensitive data at rest - Implement proper error handling (no data leaks) - Sanitize error messages - Use secure headers ### Step 5: API Security Testing Verify security implementation: - Test authentication and authorization - Perform penetration testing - Check for common vulnerabilities (OWASP API Top 10) - Validate input handling - Test rate limiting ## Examples ### Example 1: Implementing JWT Authentication ```markdown ## Secure JWT Authentication Implementation ### Authentication Flow 1. User logs in with credentials 2. Server validates credentials 3. Server generates JWT token 4. Client stores token securely 5. Client sends token with each request 6. Server validates token ### Implementation #### 1. Generate Secure JWT Tokens \`\`\`javascript // auth.js const jwt = require('jsonwebtoken'); const bcrypt = require('bcrypt'); // Login endpoint app.post('/api/auth/login', async (req, res) => { try { const { email, password } = req.body; // Validate input if (!email || !password) { return res.status(400).json({ error: 'Email and password are required' }); } // Find user const user = await db.user.findUnique({ where: { email } }); if (!user) { // Don't reveal if user exists return res.status(401).json({ error: 'Invalid credentials' }); } // Verify password const validPassword = await bcrypt.compare( password, user.passwordHash ); if (!validPassword) { return res.status(401).json({ error: 'Invalid credentials' }); } // Generate JWT token const token = jwt.sign( { userId: user.id, email: user.email, role: user.role }, process.env.JWT_SECRET, { expiresIn: '1h', issuer: 'your-app', audience: 'your-app-users' } ); // Generate refresh token const refreshToken = jwt.sign( { userId: user.id }, process.env.JWT_REFRESH_SECRET, { expiresIn: '7d' } ); // Store refresh token in database await db.refreshToken.create({ data: { token: refreshToken, userId: user.id, expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000) } }); res.json({ token, refreshToken, expiresIn: 3600 }); } catch (error) { console.error('Login error:', error); res.status(500).json({ error: 'An error occurred during login' }); } }); \`\`\` #### 2. Verify JWT Tokens (Middleware) \`\`\`javascript // middleware/auth.js const jwt = require('jsonwebtoken'); function authenticateToken(req, res, next) { // Get token from header const authHeader = req.headers['authorization']; const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN if (!token) { return res.status(401).json({ error: 'Access token required' }); } // Verify token jwt.verify( token, process.env.JWT_SECRET, { issuer: 'your-app', audience: 'your-app-users' }, (err, user) => { if (err) { if (err.name === 'TokenExpiredError') { return res.status(401).json({ error: 'Token expired' }); } return res.status(403).json({ error: 'Invalid token' }); } // Attach user to request req.user = user; next(); } ); } module.exports = { authenticateToken }; \`\`\` #### 3. Protect Routes \`\`\`javascript const { authenticateToken } = require('./middleware/auth'); // Protected route app.get('/api/user/profile', authenticateToken, async (req, res) => { try { const user = await db.user.findUnique({ where: { id: req.user.userId }, select: { id: true, email: true, name: true, // Don't return passwordHash } }); res.json(user); } catch (error) { res.status(500).json({ error: 'Server error' }); } }); \`\`\` #### 4. Implement Token Refresh \`\`\`javascript app.post('/api/auth/refresh', async (req, res) => { const { refreshToken } = req.body; if (!refreshToken) { return res.status(401).json({ error: 'Refresh token required' }); } try { // Verify refresh token const decoded = jwt.verify( refreshToken, process.env.JWT_REFRESH_SECRET ); // Check if refresh token exists in database const storedToken = await db.refreshToken.findFirst({ where: { token: refreshToken, userId: decoded.userId, expiresAt: { gt: new Date() } } }); if (!storedToken) { return res.status(403).json({ error: 'Invalid refresh token' }); } // Generate new access token const user = await db.user.findUnique({ where: { id: decoded.userId } }); const newToken = jwt.sign( { userId: user.id, email: user.email, role: user.role }, process.env.JWT_SECRET, { expiresIn: '1h' } ); res.json({ token: newToken, expiresIn: 3600 }); } catch (error) { res.status(403).json({ error: 'Invalid refresh token' }); } }); \`\`\` ### Security Best Practices - ✅ Use strong JWT secrets (256-bit minimum) - ✅ Set short expiration times (1 hour for access tokens) - ✅ Implement refresh tokens for long-lived sessions - ✅ Store refresh tokens in database (can be revoked) - ✅ Use HTTPS only - ✅ Don't store sensitive data in JWT payload - ✅ Validate token issuer and audience - ✅ Implement token blacklisting for logout ``` ### Example 2: Input Validation and SQL Injection Prevention ```markdown ## Preventing SQL Injection and Input Validation ### The Problem **❌ Vulnerable Code:** \`\`\`javascript // NEVER DO THIS - SQL Injection vulnerability app.get('/api/users/:id', async (req, res) => { const userId = req.params.id; // Dangerous: User input directly in query const query = \`SELECT * FROM users WHERE id = '\${userId}'\`; const user = await db.query(query); res.json(user); }); // Attack example: // GET /api/users/1' OR '1'='1 // Returns all users! \`\`\` ### The Solution #### 1. Use Parameterized Queries \`\`\`javascript // ✅ Safe: Parameterized query app.get('/api/users/:id', async (req, res) => { const userId = req.params.id; // Validate input first if (!userId || !/^\d+$/.test(userId)) { return res.status(400).json({ error: 'Invalid user ID' }); } // Use parameterized query const user = await db.query( 'SELECT id, email, name FROM users WHERE id = $1', [userId] ); if (!user) { return res.status(404).json({ error: 'User not found' }); } res.json(user); }); \`\`\` #### 2. Use ORM with Proper Escaping \`\`\`javascript // ✅ Safe: Using Prisma ORM app.get('/api/users/:id', async (req, res) => { const userId = parseInt(req.params.id); if (isNaN(userId)) { return res.status(400).json({ error: 'Invalid user ID' }); } const user = await prisma.user.findUnique({ where: { id: userId }, select: { id: true, email: true, name: true, // Don't select sensitive fields } }); if (!user) { return res.status(404).json({ error: 'User not found' }); } res.json(user); }); \`\`\` #### 3. Implement Request Validation with Zod \`\`\`javascript const { z } = require('zod'); // Define validation schema const createUserSchema = z.object({ email: z.string().email('Invalid email format'), password: z.string() .min(8, 'Password must be at least 8 characters') .regex(/[A-Z]/, 'Password must contain uppercase letter') .regex(/[a-z]/, 'Password must contain lowercase letter') .regex(/[0-9]/, 'Password must contain number'), name: z.string() .min(2, 'Name must be at least 2 characters') .max(100, 'Name too long'), age: z.number() .int('Age must be an integer') .min(18, 'Must be 18 or older') .max(120, 'Invalid age') .optional() }); // Validation middleware function validateRequest(schema) { return (req, res, next) => { try { schema.parse(req.body); next(); } catch (error) { res.status(400).json({ error: 'Validation failed', details: error.errors }); } }; } // Use validation app.post('/api/users', validateRequest(createUserSchema), async (req, res) => { // Input is validated at this point const { email, password, name, age } = req.body; // Hash password const passwordHash = await bcrypt.hash(password, 10); // Create user const user = await prisma.user.create({ data: { email, passwordHash, name, age } }); // Don't return password hash const { passwordHash: _, ...userWithoutPassword } = user; res.status(201).json(userWithoutPassword); } ); \`\`\` #### 4. Sanitize Output to Prevent XSS \`\`\`javascript const DOMPurify = require('isomorphic-dompurify'); app.post('/api/comments', authenticateToken, async (req, res) => { const { content } = req.body; // Validate if (!content || content.length > 1000) { return res.status(400).json({ error: 'Invalid comment content' }); } // Sanitize HTML to prevent XSS const sanitizedContent = DOMPurify.sanitize(content, { ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a'], ALLOWED_ATTR: ['href'] });
Voir sur GitHub
Ce SKILL.md est tres volumineux, SkillsMP affiche donc ici seulement la premiere section. Voir sur GitHub