Ihre Daten im Visier: Warum Authentifizierung in TypeScript kein Scherz ist
\n\nStellen Sie sich vor: Sie haben eine coole App in TypeScript erstellt. Sie läuft flüssig, die Typen sind streng, der Code ist schön. Aber es gibt ein kleines Detail – die Authentifizierung. Und hier wird es richtig interessant. Ein Fehler – und die Benutzerdaten fließen wie Wasser durch die Finger. Kommt Ihnen bekannt vor?
\n\nIm Jahr 2024 ist sichere Authentifizierung nicht einfach nur „einen Login anbauen". Es ist eine Wissenschaft für sich. Und TypeScript ist hier Ihr bester Freund. Es verhindert, dass Sie versehentlich den falschen Datentyp übergeben, zeigt Ihnen, wo Sie vergessen haben, einen Token zu überprüfen, und rettet Sie vor dummen Fehlern während der Kompilierung.
\n\nIn diesem Artikel werden wir durchgehen, wie man eine sichere Authentifizierung in TypeScript-Anwendungen von Grund auf aufbaut. Kein Blabla – nur echte Beispiele, Best Practices und eine Prise schwarzen Humors (wo kämen wir sonst hin).
\n\nJWT: Liebe auf den ersten Token
\n\nJSON Web Token (JWT) ist der De-facto-Standard für die Authentifizierung in modernen Webanwendungen. Aber wie Onkel Ben sagte: „Mit großer Macht kommt große Verantwortung". JWT kann sowohl ein Schild als auch eine Zeitbombe sein.
\n\nWie man es NICHT macht: Anti-Beispiel
\n\nDie häufigste Sünde von Anfängern ist es, den Token im localStorage zu speichern und offen zu übertragen. Ja, das funktioniert. Aber es ist, als würde man die Wohnungsschlüssel unter der Fußmatte lassen – bequem, aber jeder Passant kann hinein. Ein XSS-Angriff – und alle Ihre Token sind beim Angreifer.
\n\nRichtiger Umgang mit JWT in TypeScript
\n\nLassen Sie uns einen sicheren Wrapper für die Arbeit mit Tokens schreiben. TypeScript hilft uns hier, Typen nicht zu verwechseln und die Validierung nicht zu vergessen.
\n\nimport jwt from 'jsonwebtoken';\n\ninterface TokenPayload {\n userId: string;\n role: 'user' | 'admin';\n iat?: number;\n exp?: number;\n}\n\n// Token mit klarer Typisierung generieren\nfunction generateAccessToken(payload: TokenPayload): string {\n return jwt.sign(\n { ...payload },\n process.env.JWT_SECRET as string,\n { expiresIn: '15m' }\n );\n}\n\n// Verifizieren und sofort zu unserem Interface casten\nfunction verifyAccessToken(token: string): TokenPayload | null {\n try {\n return jwt.verify(\n token, \n process.env.JWT_SECRET as string\n ) as TokenPayload;\n } catch (error) {\n console.error('Token hat die Prüfung nicht bestanden:', error);\n return null;\n }\n}\n\nBeachten Sie: Wir überprüfen immer, dass JWT_SECRET existiert und ein String ist. TypeScript zwingt uns dazu – kein undefined zur Laufzeit!
Passwort-Hashing: bcrypt eilt zur Hilfe
\n\nPasswörter im Klartext zu speichern ist ein Verbrechen. Selbst wenn Ihre Datenbank besser geschützt ist als Fort Knox, ein einziger Einbruch – und Sie sind in den Nachrichten als der nächste „Passwort-Leak". Passwort-Hashing ist Ihr Rettungsanker.
\n\nWarum bcrypt und nicht MD5?
\n\nMD5 ist tot. SHA-256 ist auch keine Option. Moderne GPUs können Milliarden von Hashes pro Sekunde durchprobieren. Bcrypt hingegen wurde absichtlich langsam gemacht. Es verwendet Salt (zufällige Daten) und einen einstellbaren Cost-Faktor. Je höher der Cost, desto länger dauert die Hash-Berechnung. Und das ist gut so!
\n\nImplementierung in TypeScript
\n\nimport bcrypt from 'bcrypt';\n\nconst SALT_ROUNDS = 12; // Optimaler Wert im Jahr 2024\n\nasync function hashPassword(password: string): Promise<string> {\n const salt = await bcrypt.genSalt(SALT_ROUNDS);\n return bcrypt.hash(password, salt);\n}\n\nasync function comparePassword(\n password: string, \n hash: string\n): Promise<boolean> {\n return bcrypt.compare(password, hash);\n}\n\n// Typisierte Funktion für die Registrierung\ninterface CreateUserInput {\n email: string;\n password: string;\n name: string;\n}\n\nasync function createUser(input: CreateUserInput): Promise<Omit<User, 'passwordHash'>> {\n const passwordHash = await hashPassword(input.password);\n \n // In der DB speichern (hier Ihr C