slogan3

Hoe kan ik een aangepaste middleware-oplossing implementeren in TypeScript voor {{middleware_type}}?

description

Door deze prompt te volgen, verbeteren gebruikers de architectuur van hun toepassing door effectieve middleware-implementatie, wat leidt tot betere onderhoudbaarheid, schaalbaarheid en codehergebruik.

prompt

try_prompt

Help me een aangepaste middleware-oplossing in TypeScript maken die {{middleware_type}} scenario's kan afhandelen. Geef gedetailleerde stappen, co ... more
generate_helper
disclaimerOnPageApi image_legal_disclaimer...

ai_answers

provider: openai
model: gpt-4.1-nano
Natuurlijk! Hieronder vind je een stapsgewijze handleiding om een flexibele en herbruikbare middleware-oplossing voor authenticatie in TypeScript te maken. Deze aanpak zorgt voor goede structuur, onderhoudbaarheid en hergebruik in je toepassing. --- ## 1. Structuur en Best Practices - **Modules scheiden**: Plaats authenticatie-logica, middleware en configuratie in aparte mappen/bestanden. - **Type-beheer**: Gebruik TypeScript types en interfaces voor duidelijkheid en type-veiligheid. - **Configuratie**: Maak gebruik van configuratiebestanden voor verschillende authenticatiescenario's. - **Herbruikbaarheid**: Bouw middleware die flexibel is en kan worden aangepast aan verschillende authenticatiescenario's. - **Error handling**: Zorg voor consistente en duidelijke foutmeldingen. --- ## 2. Stap-voor-stap implementatie ### a) Set-up project en dependencies Gebruik bijvoorbeeld een Node.js project met Express: ```bash npm init -y npm install express @types/express typescript ts-node ``` Maak een `tsconfig.json` voor TypeScript configuratie. --- ### b) Definieer types en interfaces Maak een bestand `types.ts`: ```typescript // src/types.ts export interface IUser { id: string; username: string; roles?: string[]; } export interface AuthenticatedRequest extends Express.Request { user?: IUser; } ``` --- ### c) Authentificatiemiddleware basis Maak een basis middleware `authMiddleware.ts`: ```typescript // src/middleware/authMiddleware.ts import { Request, Response, NextFunction } from 'express'; import { AuthenticatedRequest, IUser } from '../types'; type AuthFunction = (req: Request) => Promise<IUser | null>; export function createAuthMiddleware(authFn: AuthFunction) { return async (req: AuthenticatedRequest, res: Response, next: NextFunction) => { try { const user = await authFn(req); if (!user) { return res.status(401).json({ message: 'Niet geautoriseerd' }); } req.user = user; next(); } catch (error) { console.error('Authentatiefout:', error); res.status(500).json({ message: 'Serverfout tijdens authenticatie' }); } }; } ``` Deze factory maakt middleware met een custom authenticatiefunctie. --- ### d) Implementatie van authenticatiefuncties Voorbeeld 1: Token-gebaseerde authenticatie (bijv. JWT): ```typescript // src/auth/jwtAuth.ts import { Request } from 'express'; import jwt from 'jsonwebtoken'; import { IUser } from '../types'; const SECRET_KEY = 'jouw-secret'; export const jwtAuth = async (req: Request): Promise<IUser | null> => { const authHeader = req.headers['authorization']; if (!authHeader || !authHeader.startsWith('Bearer ')) return null; const token = authHeader.substring(7, authHeader.length); try { const payload = jwt.verify(token, SECRET_KEY) as any; return { id: payload.sub, username: payload.username, roles: payload.roles, }; } catch { return null; } }; ``` --- ### e) Middleware gebruiken In je server setup: ```typescript // src/server.ts import express from 'express'; import { createAuthMiddleware } from './middleware/authMiddleware'; import { jwtAuth } from './auth/jwtAuth'; const app = express(); const authMiddleware = createAuthMiddleware(jwtAuth); app.use('/api/protected', authMiddleware, (req: any, res) => { res.json({ message: `Welkom, ${req.user?.username}` }); }); app.listen(3000, () => console.log('Server draait op poort 3000')); ``` --- ## 3. Uitgebreide scenario's en best practices - **Meerdere authenticatiemethoden**: Maak verschillende `authFn` functies en combineer ze indien nodig. - **Rolgebaseerde toegang**: Voeg middleware toe die rollen controleert: ```typescript export function authorizeRoles(...allowedRoles: string[]) { return (req: AuthenticatedRequest, res: Response, next: NextFunction) => { const userRoles = req.user?.roles || []; const hasRole = allowedRoles.some(role => userRoles.includes(role)); if (!hasRole) { return res.status(403).json({ message: 'Toegang geweigerd' }); } next(); }; } ``` Gebruik dit na authenticatie: ```typescript app.use('/admin', authMiddleware, authorizeRoles('admin'), (req, res) => { res.send('Admin toegang'); }); ``` - **Herbruikbare middleware**: Maak combinaties, bijvoorbeeld: ```typescript app.use('/admin', authMiddleware, authorizeRoles('admin'), (req, res) => { ... }); ``` - **Logging en foutafhandeling**: Voeg logging toe voor debugging en monitoring. --- ## 4. Samenvatting - Gebruik een `createAuthMiddleware` factory voor herbruikbare authenticatie. - Scheid authenticatiefuncties per scenario (JWT, API key, etc.). - Voeg rol- of permissiecontrole toe als extra middleware. - Houd types strikt voor betere codekwaliteit. - Documenteer je middleware en gebruik consistente foutafhandeling. --- Mocht je nog meer specifieke scenario's of codevoorbeelden willen, laat het gerust weten!
provider: deepseek
model: deepseek-chat
Zeker! Ik help je een aangepaste middleware-oplossing voor authenticatie in TypeScript te bouwen. Hier is een complete handleiding met gedetailleerde stappen, codevoorbeelden en best practices. ## 1. Projectstructuur en Dependencies Eerst instellen we de basisstructuur: ``` src/ ├── middleware/ │ ├── auth.middleware.ts │ ├── types.ts │ └── index.ts ├── utils/ │ └── jwt.utils.ts ├── types/ │ └── express.ts └── app.ts ``` **Package.json dependencies:** ```json { "dependencies": { "express": "^4.18.0", "jsonwebtoken": "^9.0.0", "bcryptjs": "^2.4.3" }, "devDependencies": { "@types/express": "^4.17.0", "@types/jsonwebtoken": "^9.0.0", "@types/bcryptjs": "^2.4.0", "typescript": "^5.0.0" } } ``` ## 2. Type Definitions ```typescript // src/types/express.ts import { Request } from 'express'; export interface AuthenticatedUser { userId: string; email: string; roles: string[]; } declare global { namespace Express { interface Request { user?: AuthenticatedUser; } } } // src/middleware/types.ts export interface AuthConfig { secret: string; expiresIn: string; requiredRoles?: string[]; } export interface AuthMiddlewareOptions { requireAuth?: boolean; requiredRoles?: string[]; allowPublic?: boolean; } ``` ## 3. JWT Utility Functions ```typescript // src/utils/jwt.utils.ts import jwt from 'jsonwebtoken'; import { AuthenticatedUser } from '../types/express'; export class JWTUtils { private static readonly SECRET = process.env.JWT_SECRET || 'jouw-geheime-sleutel'; private static readonly EXPIRES_IN = '7d'; static generateToken(user: Omit<AuthenticatedUser, 'roles'> & { roles: string[] }): string { return jwt.sign( { userId: user.userId, email: user.email, roles: user.roles }, this.SECRET, { expiresIn: this.EXPIRES_IN } ); } static verifyToken(token: string): AuthenticatedUser | null { try { const decoded = jwt.verify(token, this.SECRET) as AuthenticatedUser; return decoded; } catch (error) { return null; } } static extractTokenFromHeader(authHeader: string | undefined): string | null { if (!authHeader || !authHeader.startsWith('Bearer ')) { return null; } return authHeader.substring(7); } } ``` ## 4. Hoofd Authenticatie Middleware ```typescript // src/middleware/auth.middleware.ts import { Request, Response, NextFunction } from 'express'; import { JWTUtils } from '../utils/jwt.utils'; import { AuthMiddlewareOptions } from './types'; export class AuthMiddleware { /** * Basis authenticatie middleware */ static authenticate(options: AuthMiddlewareOptions = {}) { return (req: Request, res: Response, next: NextFunction): void => { const { requireAuth = true, requiredRoles = [], allowPublic = false } = options; // Token extractie const token = JWTUtils.extractTokenFromHeader(req.headers.authorization); // Geen token gevonden if (!token) { if (allowPublic && !requireAuth) { return next(); } if (!requireAuth) { return next(); } return this.sendError(res, 401, 'Authenticatie vereist'); } // Token verifiëren const user = JWTUtils.verifyToken(token); if (!user) { return this.sendError(res, 401, 'Ongeldig of verlopen token'); } // Gebruiker toevoegen aan request req.user = user; // Rol-based autorisatie controleren if (requiredRoles.length > 0 && !this.hasRequiredRoles(user.roles, requiredRoles)) { return this.sendError(res, 403, 'Onvoldoende rechten'); } next(); }; } /** * Rol-specifieke middleware factory */ static requireRoles(roles: string[]) { return this.authenticate({ requiredRoles: roles, requireAuth: true }); } /** * Optionele authenticatie middleware */ static optionalAuth() { return this.authenticate({ requireAuth: false, allowPublic: true }); } /** * Admin-only middleware */ static requireAdmin() { return this.requireRoles(['admin']); } /** * Helper: Rol check */ private static hasRequiredRoles(userRoles: string[], requiredRoles: string[]): boolean { return requiredRoles.some(role => userRoles.includes(role)); } /** Helper: Error response */ private static sendError(res: Response, status: number, message: string): void { res.status(status).json({ success: false, error: { code: status, message: message } }); } } ``` ## 5. Aanvullende Security Middleware ```typescript // src/middleware/security.middleware.ts import { Request, Response, NextFunction } from 'express'; export class SecurityMiddleware { /** * Rate limiting middleware */ static rateLimit(requestsPerMinute: number = 100) { const requests = new Map<string, number[]>(); return (req: Request, res: Response, next: NextFunction): void => { const ip = req.ip || 'unknown'; const now = Date.now(); const windowStart = now - 60000; // 1 minuut // Oude requests opruimen const userRequests = requests.get(ip) || []; const recentRequests = userRequests.filter(time => time > windowStart); // Rate limit check if (recentRequests.length >= requestsPerMinute) { res.status(429).json({ success: false, error: { code: 429, message: 'Te veel requests' } }); return; } // Nieuwe request toevoegen recentRequests.push(now); requests.set(ip, recentRequests); next(); }; } /** * CORS middleware */ static cors(allowedOrigins: string[] = ['*']) { return (req: Request, res: Response, next: NextFunction): void => { const origin = req.headers.origin; if (allowedOrigins.includes('*') || (origin && allowedOrigins.includes(origin))) { res.header('Access-Control-Allow-Origin', origin || '*'); res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization'); res.header('Access-Control-Allow-Credentials', 'true'); } if (req.method === 'OPTIONS') { res.sendStatus(200); return; } next(); }; } } ``` ## 6. Middleware Export en Configuratie ```typescript // src/middleware/index.ts export { AuthMiddleware } from './auth.middleware'; export { SecurityMiddleware } from './security.middleware'; export type { AuthMiddlewareOptions } from './types'; ``` ## 7. Gebruik in Express Applicatie ```typescript // src/app.ts import express from 'express'; import { AuthMiddleware, SecurityMiddleware } from './middleware'; const app = express(); // Global middleware app.use(express.json()); app.use(SecurityMiddleware.cors(['http://localhost:3000'])); app.use(SecurityMiddleware.rateLimit(100)); // Routes met verschillende authenticatie niveaus app.get('/public', AuthMiddleware.optionalAuth(), (req, res) => { const userInfo = req.user ? `Ingelogd als: ${req.user.email}` : 'Anonieme gebruiker'; res.json({ message: 'Publieke route', user: userInfo }); }); app.get('/protected', AuthMiddleware.authenticate(), (req, res) => { res.json({ message: 'Beschermde route', user: req.user }); }); app.get('/admin', AuthMiddleware.requireAdmin(), (req, res) => { res.json({ message: 'Admin route', user: req.user }); }); app.get('/user-data', AuthMiddleware.requireRoles(['user', 'admin']), (req, res) => { res.json({ message: 'User data route', user: req.user }); }); // Error handling middleware app.use((error: Error, req: express.Request, res: express.Response, next: express.NextFunction) => { console.error('Middleware error:', error); res.status(500).json({ success: false, error: { code: 500, message: 'Interne serverfout' } }); }); const PORT = process.env.PORT || 3000; app.listen(PORT, () => { console.log(`Server draait op poort ${PORT}`); }); ``` ## 8. Gebruiksvoorbeeld met Login ```typescript // src/routes/auth.routes.ts import express from 'express'; import { JWTUtils } from '../utils/jwt.utils'; import bcrypt from 'bcryptjs'; const router = express.Router(); // Mock user database const mockUsers = [ { id: '1', email: 'admin@voorbeeld.nl', password: '$2a$10$voorbeeldhashedpassword', // "wachtwoord123" roles: ['admin', 'user'] } ]; router.post('/login', async (req, res) => { const { email, password } = req.body; // Validatie if (!email || !password) { return res.status(400).json({ success: false, error: 'Email en wachtwoord zijn vereist' }); } // User zoeken const user = mockUsers.find(u => u.email === email); if (!user) { return res.status(401).json({ success: false, error: 'Ongeldige inloggegevens' }); } // Wachtwoord verifiëren (in praktijk: bcrypt.compare) const isValidPassword = await bcrypt.compare(password, user.password); if (!isValidPassword) { return res.status(401).json({ success: false, error: 'Ongeldige inloggegevens' }); } // Token genereren const token = JWTUtils.generateToken({ userId: user.id, email: user.email, roles: user.roles }); res.json({ success: true, data: { token, user: { id: user.id, email: user.email, roles: user.roles } } }); }); export default router; ``` ## Best Practices en Aanbevelingen ### 1. **Security Best Practices** - Gebruik environment variables voor secrets - Implementeer token refresh mechanisme - Gebruik HTTPS in productie - Hash wachtwoorden met bcrypt - Implementeer CSRF protection ### 2. **Middleware Structuur** - Houd middleware focused en single-purpose - Gebruik factory pattern voor configureerbare middleware - Documenteer elk middleware component - Implementeer goede error handling ### 3. **TypeScript Best Practices** - Gebruik interfaces voor request extensies - Implementeer custom types voor auth data - Gebruik generics waar mogelijk - Valideer incoming data met libraries zoals Zod ### 4. **Performance Overwegingen** - Cache veelgebruikte auth checks - Implementeer connection pooling voor database - Gebruik efficiente token verification - Monitor middleware performance ### 5. **Testing Strategy** ```typescript // Voorbeeld test import request from 'supertest'; import { app } from '../app'; describe('Auth Middleware', () => { it('should block unauthorized access', async () => { const response = await request(app) .get('/protected') .expect(401); expect(response.body.error.message).toBe('Authenticatie vereist'); }); }); ``` Deze structuur biedt een solide basis voor authenticatie middleware die eenvoudig is uit te breiden, te testen en te onderhouden. Pas de configuratie aan naar jouw specifieke use case en security requirements.