Authentication mit Claude Code: JWT, OAuth, Sessions 2026

Authentication falsch implementieren hat fatale Konsequenzen: Session Hijacking, Token-Leaks, Brute-Force-Angriffe. Claude Code kennt die Sicherheits-Best-Practices und implementiert sie korrekt — nicht wie Stack-Overflow-Snippets die 5 Jahre alt sind.

Warum Authentication für KI besonders geeignet ist

Authentication hat etablierte Patterns (OWASP, RFC 6749, NIST SP 800-63). Claude Code kennt sie alle — und warnt aktiv wenn du etwas Unsicheres implementieren willst. Das ist wertvoller als ein Kollege der einfach was zusammenhackt.

Claude Code warnt proaktiv wenn du es bittest unsichere Patterns zu implementieren: MD5 für Passwörter, JWT ohne Expiry, HTTP-Cookies ohne Secure-Flag. Das ist Feature, kein Bug.

JWT Authentication vollständig implementieren

JWT mit Refresh-Token Rotation

# Prompt für komplettes JWT-System: # "Implementiere JWT-Auth mit: # - Access Token (15 Min TTL), Refresh Token (7 Tage) # - Refresh Token Rotation (alter Token wird invalidiert) # - Token-Blacklist in Redis (für Logout) # - bcrypt für Passwörter (cost factor 12)" const jwt = require('jsonwebtoken'); const bcrypt = require('bcrypt'); const crypto = require('crypto'); const redis = require('ioredis'); const BCRYPT_COST = 12; // Nicht weniger! const ACCESS_TTL = 15 * 60; // 15 Minuten const REFRESH_TTL = 7 * 24 * 3600; // 7 Tage class AuthService { async register(email, password) { // NIEMALS Plaintext in DB const passwordHash = await bcrypt.hash(password, BCRYPT_COST); return await db.users.create({ email, passwordHash }); } async login(email, password) { const user = await db.users.findByEmail(email); // Timing-Attack-sicher: immer vergleichen, auch wenn user nicht existiert const dummyHash = '$2b$12$invalid.hash.for.timing.attack.prevention'; const valid = await bcrypt.compare(password, user?.passwordHash ?? dummyHash); if (!user || !valid) throw new Error('Invalid credentials'); return await this.generateTokenPair(user.id); } async generateTokenPair(userId) { const accessToken = jwt.sign( { sub: userId }, process.env.JWT_ACCESS_SECRET, { expiresIn: ACCESS_TTL } ); // Refresh Token: zufälliger String (kein JWT — nicht signierbar ohne Lookup) const refreshToken = crypto.randomBytes(64).toString('hex'); const refreshHash = await bcrypt.hash(refreshToken, 10); await db.refreshTokens.create({ userId, hash: refreshHash, expiresAt: new Date(Date.now() + REFRESH_TTL * 1000) }); return { accessToken, refreshToken }; } async refresh(oldRefreshToken) { const tokens = await db.refreshTokens.findValid(); // Token Rotation: altes Token suchen und löschen for (const stored of tokens) { if (await bcrypt.compare(oldRefreshToken, stored.hash)) { await db.refreshTokens.delete(stored.id); return await this.generateTokenPair(stored.userId); } } throw new Error('Invalid refresh token'); } async logout(accessToken) { // Access Token blacklisten bis er abläuft const decoded = jwt.decode(accessToken); const ttl = decoded.exp - Math.floor(Date.now() / 1000); if (ttl > 0) await redis.setex(`blacklist:${accessToken}`, ttl, '1'); } }

OAuth 2.0 mit Claude Code

Google OAuth Integration

# Prompt: # "Implementiere Google OAuth 2.0 Login mit Passport.js: # - Google Strategy, User anlegen falls nicht existiert # - State-Parameter gegen CSRF # - Nach OAuth: JWT ausgeben (kein Session-Cookie)" const passport = require('passport'); const { Strategy: GoogleStrategy } = require('passport-google-oauth20'); passport.use(new GoogleStrategy({ clientID: process.env.GOOGLE_CLIENT_ID, clientSecret: process.env.GOOGLE_CLIENT_SECRET, callbackURL: `${process.env.APP_URL}/auth/google/callback`, scope: ['email', 'profile'] }, async (accessToken, refreshToken, profile, done) => { try { let user = await db.users.findByGoogleId(profile.id); if (!user) { user = await db.users.create({ googleId: profile.id, email: profile.emails[0].value, name: profile.displayName, avatar: profile.photos[0]?.value }); } done(null, user); } catch (err) { done(err); } })); // Routes app.get('/auth/google', passport.authenticate('google', { state: crypto.randomBytes(16).toString('hex') }) ); app.get('/auth/google/callback', passport.authenticate('google', { session: false, failureRedirect: '/login' }), async (req, res) => { // JWT ausgeben, kein Cookie const { accessToken } = await authService.generateTokenPair(req.user.id); res.redirect(`${process.env.FRONTEND_URL}/auth/callback?token=${accessToken}`); } );

Security Checklist für Authentication

  • Passwörter: bcrypt mit cost factor ≥12 oder Argon2id. Niemals MD5/SHA1/SHA256 ohne Salt.
  • JWT Secrets: Mindestens 256 Bit Entropie. Separate Secrets für Access und Refresh Token.
  • Token Storage: AccessToken in Memory (nicht localStorage!), RefreshToken in httpOnly Cookie.
  • Timing Attacks: Passwort-Vergleich immer mit bcrypt.compare (constant-time), nie String-Vergleich.
  • Rate Limiting: Login-Endpoint: max 5 Versuche/IP/15 Min. Account Lockout nach 10 Fehlversuchen.
  • Niemals: Passwörter loggen, in URLs übergeben oder in GET-Parametern senden.
  • Niemals: "Remember Me" als unsignierter Cookie mit User-ID.
Claude Code Security-Prompt: Wenn du Auth implementierst, füge immer hinzu: "Prüfe die Implementierung auf OWASP Authentication Cheat Sheet Compliance. Liste Sicherheitsprobleme explizit auf."

Session-Management Alternative

# Wann Sessions statt JWT: # - Server-Side Rendering (keine SPA) # - Einfacheres Logout (Session einfach löschen) # - Weniger Client-Komplexität const session = require('express-session'); const RedisStore = require('connect-redis'); app.use(session({ store: new RedisStore({ client: redisClient }), secret: process.env.SESSION_SECRET, resave: false, saveUninitialized: false, cookie: { secure: process.env.NODE_ENV === 'production', // HTTPS only in Prod! httpOnly: true, // Kein JavaScript-Zugriff sameSite: 'strict', // CSRF-Schutz maxAge: 7 * 24 * 60 * 60 * 1000 // 7 Tage } }));

Authentication-Modul im Kurs

Im Claude Code Mastery Kurs gibt es ein vollständiges Authentication-Modul: JWT + Refresh-Token-Rotation, OAuth 2.0 (Google, GitHub), Session-Management, 2FA-Implementierung — mit OWASP-geprüftem Code.

14 Tage kostenlos testen →