Sichere Authentifizierung in TypeScript: Profi-Guide

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Ihre Daten im Visier: Warum Authentifizierung in TypeScript kein Scherz ist

\n\n

Stellen 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\n

Im 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\n

In 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\n

JWT: Liebe auf den ersten Token

\n\n

JSON 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\n

Wie man es NICHT macht: Anti-Beispiel

\n\n

Die 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\n

Richtiger Umgang mit JWT in TypeScript

\n\n

Lassen 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\n
import 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\n

Beachten Sie: Wir überprüfen immer, dass JWT_SECRET existiert und ein String ist. TypeScript zwingt uns dazu – kein undefined zur Laufzeit!

\n\n

Passwort-Hashing: bcrypt eilt zur Hilfe

\n\n

Passwö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\n

Warum bcrypt und nicht MD5?

\n\n

MD5 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\n

Implementierung in TypeScript

\n\n
import 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                

Blogs

Buchempfehlungen