Authentifizierung klingt im Alltag einfach: „Login mit Username und Passwort." In einer modernen Web-App ist das aber nur ein winziger Ausschnitt einer Architektur, die mehrere Entscheidungen trifft — welche Faktor-Klassen akzeptiert werden, ob Sessions oder Tokens genutzt werden, wie Re-Auth für sensible Aktionen aussieht. Dieser Artikel sortiert die Begriffe und legt die Grundlagen für die folgenden Kapitel zu Hashing, Cookies, JWT und OAuth.

Authentifizierung vs. Autorisierung

Die beiden Begriffe werden täglich verwechselt — auch im Code-Review, auch in Audits.

BegriffFrageBeispiel
Authentifizierung (AuthN)„Wer bist du?"Login mit Passwort, Passkey, OAuth-Provider
Autorisierung (AuthZ)„Was darfst du?"Darf User X den Datensatz Y editieren?
Audit„Was hast du gemacht?"Logging aller Aktionen für Forensik

Konkretes Beispiel:

Ein User loggt sich erfolgreich ein — AuthN passt. Dann versucht er, das Profil eines anderen Users zu bearbeiten — AuthZ muss separat prüfen, ob das erlaubt ist. Viele klassische Bugs (IDOR, BOLA) entstehen, weil AuthN passiert ist und der Code daraus fälschlich auf AuthZ schließt.

Konsequenz für die Architektur: Auth-Logik und Permission-Logik sollten getrennte Schichten sein. Auth-Middleware setzt den User-Kontext; Permission-Checks erfolgen pro Endpoint oder pro Ressource. Vertieft in Kap 15 Autorisierung-Grundlagen.

Die drei Faktor-Klassen

Authentifizierungs-Faktoren werden traditionell in drei Klassen eingeteilt:

KlasseWas es istBeispieleSchwächen
WissenEtwas, das du weißtPasswort, PIN, Sicherheits-FragenPhishable, ratbar, wiederverwendbar
BesitzEtwas, das du hastSmartphone, Hardware-Token, SmartcardVerlierbar, klonbar (SIM-Swap)
InhärenzEtwas, das du bistFingerabdruck, Gesicht, IrisNicht änderbar bei Kompromittierung, lokal verifiziert

Multi-Faktor-Authentifizierung (MFA) kombiniert mindestens zwei verschiedene Klassen — Passwort + SMS sind formal zwei Faktoren (Wissen + Besitz), aber SMS ist anfällig für SIM-Swapping und gilt nicht mehr als starker zweiter Faktor.

Moderner Konsens (Stand 2026):

  • Phishing-resistente MFA ist Pflicht für sensible Konten — das heißt WebAuthn/FIDO2-Passkeys oder Hardware-Tokens (YubiKey).
  • TOTP-Apps (Google Authenticator, Aegis, Raivo) sind besser als SMS, aber Phishing-anfällig (Adversary-in-the-Middle kann TOTP-Code in Echtzeit abfragen).
  • SMS-MFA ist veraltet — nur noch als Notlösung akzeptabel, niemals als einziger zweiter Faktor.
  • Passkeys (siehe webauthn-und-passkeys) sind die strukturelle Antwort: Phishing-resistent, Cross-Device-Sync, kein Passwort mehr.

Session-basiert vs. Token-basiert

Zwei dominante Architektur-Patterns für „User ist eingeloggt":

Session-basiert (klassisch):

HTTP session-based-auth.txt
# Login-Response setzt Cookie
Set-Cookie: sessionId=opaque-random-id; HttpOnly; Secure; SameSite=Lax

# Jeder Folge-Request schickt Cookie mit
Cookie: sessionId=opaque-random-id

# Server schlägt sessionId in Session-Store (DB/Redis) nach
# → User-Kontext, Berechtigungen

Token-basiert (stateless):

HTTP token-based-auth.txt
# Login-Response liefert Token
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6...
# (signiertes JWT mit User-Info im Payload)

# Jeder Folge-Request schickt Token im Header
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6...

# Server validiert Signatur, liest Payload — kein DB-Lookup nötig
AspektSession-basiertToken-basiert (JWT)
StateServer-Side (Session-Store)Stateless (Token enthält State)
RevocationSofort (Eintrag löschen)Schwierig (Token bleibt valide bis exp)
SkalierungSession-Store ist Single PointBeliebige Backend-Instanzen
CSRF-SchutzCookie + CSRF-Token nötigHeader-basiert: Header sendet Browser nicht automatisch
XSS-AuswirkungCookie mit HttpOnly schützt vor JS-ZugriffToken meist in JS zugänglich → XSS = Token-Diebstahl
Mobile/SPAFunktioniert, etwas umständlichDefault-Pattern
Klassischer Web-LoginDefault-PatternMöglich, aber overkill

Konsequenzen für die Wahl:

  • Klassische Web-App mit Server-Render: Sessions sind einfacher und sicherer. CSRF-Schutz ist Standard-Pattern. Vertieft in session-cookies und Kap 12 CSRF.
  • SPA + API: Beides funktioniert. Mit HttpOnly-Cookies (auch für SPAs) hast du Sessions plus CSRF-Schutz; mit JWT in Authorization-Header hast du Stateless plus CORS-Komplexität.
  • Microservices / Service-to-Service: Token (JWT, mTLS) ist der Standard — Cookies funktionieren in B2B-Service-Calls nicht gut.
  • Mobile-App: Token ist Standard, weil Mobile-HTTP-Clients selten Cookie-Stores haben.

Vorsicht vor „JWT überall" als Default: JWT hat viele Spezial-Probleme (siehe jwt-stateless-tokens). Für klassische Web-Apps ist Session-basiert oft die bessere Wahl.

Login-Flow als Minimalbeispiel

Ein einfacher passwort-basierter Login-Flow zeigt die Grundbausteine:

JavaScript login-flow-minimal.js
const argon2 = require('argon2');
const crypto = require('crypto');

app.post('/login', async (req, res) => {
  const { email, password } = req.body;

  // 1. User aus DB laden (Konstante Zeit — Enumeration-Schutz)
  const user = await db.users.findOne({ email });

  // 2. Passwort-Hash vergleichen (auch wenn user null ist — Timing)
  const passwordHash = user?.passwordHash || DUMMY_HASH;
  const ok = await argon2.verify(passwordHash, password);

  if (!user || !ok) {
    // 3. Generische Fehlermeldung — keine Information über Existenz
    return res.status(401).json({ error: 'Invalid credentials' });
  }

  // 4. Session-ID erzeugen (kryptografisch zufällig)
  const sessionId = crypto.randomBytes(32).toString('base64url');
  await sessionStore.set(sessionId, {
    userId: user.id,
    createdAt: Date.now(),
    lastActivity: Date.now(),
  }, { ttlMs: 24 * 60 * 60 * 1000 });

  // 5. Cookie setzen
  res.cookie('sessionId', sessionId, {
    httpOnly: true,
    secure: true,
    sameSite: 'lax',
    maxAge: 24 * 60 * 60 * 1000,
  });

  // 6. Audit-Log
  logger.info('login.success', {
    userId: user.id,
    ip: req.ip,
    userAgent: req.get('user-agent'),
  });

  res.json({ ok: true });
});

Was hier alles steckt:

  • Hashing mit argon2id (siehe passwort-hashing).
  • Konstante-Zeit-Vergleich plus Dummy-Hash gegen User-Enumeration via Timing.
  • Generische Fehlermeldung — keine Unterscheidung „User existiert nicht" vs. „Passwort falsch" (siehe account-lifecycle).
  • Kryptografische Session-ID — 256 Bits Entropie, base64url-encoded.
  • Cookie-FlagsHttpOnly, Secure, SameSite=Lax (siehe session-cookies).
  • Audit-Log für Forensik.

Was hier noch fehlt:

  • Rate-Limiting — Brute-Force-Schutz (siehe brute-force-und-rate-limits).
  • MFA-Step — bei aktiviertem zweiten Faktor.
  • Anomalie-Detection — Login von ungewöhnlichem Standort/Gerät.
  • Re-Auth-Marker für sensitive Aktionen.

Re-Authentication

Eine wichtige, oft vergessene Schicht: Re-Auth für sensitive Aktionen.

Selbst wenn der User „eingeloggt" ist, sollten kritische Operationen (Passwort ändern, E-Mail-Adresse ändern, Zahlungs-Methode anpassen, Account löschen) erneute Authentifizierung verlangen. Gründe:

  • Schutz gegen aktive Session-Hijacks — Angreifer hat zwar Session, aber kein aktuelles Passwort.
  • Schutz gegen Schulter-Surfen — Account, der eingeloggt ist, soll trotzdem nicht spontan löschbar sein.
  • Audit-Trail — Re-Auth-Events sind separat geloggt, klare Spuren.

Implementierungs-Pattern:

JavaScript re-auth-pattern.js
// Marker in Session: wann zuletzt Re-Auth gemacht?
session.lastReAuthAt = Date.now();

// Middleware für sensitive Endpoints
function requireFreshAuth(maxAgeMs = 5 * 60 * 1000) {
  return (req, res, next) => {
    const lastReAuth = req.session.lastReAuthAt || req.session.createdAt;
    if (Date.now() - lastReAuth > maxAgeMs) {
      return res.status(403).json({ error: 'Re-Authentication required' });
    }
    next();
  };
}

app.post('/account/delete', requireFreshAuth(), async (req, res) => {
  // ...
});

Faustregel: Innerhalb von 5–15 Minuten nach letzter Authentifizierung gelten sensible Aktionen als erlaubt; danach Re-Auth verlangen.

Anonymisierte und Service-Accounts

Nicht jeder Auth-Kontext ist ein menschlicher User.

Anonyme Sessions:

Ein User kann eine anonyme Session haben (Warenkorb vor Login). Diese hat eine Session-ID, aber kein userId. Beim Login wird die anonyme Session mit dem User-Account gemergt — der Warenkorb bleibt erhalten. Vorsicht: Session-Fixation-Schutz (siehe session-cookies) muss eine neue Session-ID nach Login generieren, sonst kann ein Angreifer eine anonyme Session vorbereiten und auf das Login warten.

Service-Accounts / API-Keys:

Wenn nicht ein User, sondern ein anderer Service Auth braucht (Microservice-Aufruf, externes System mit API-Zugang):

  • API-Keys — langlebige Bearer-Tokens, simpel, gefährlich bei Leak.
  • mTLS — Client-Zertifikate, robust, höherer Setup-Aufwand.
  • OAuth-Client-Credentials-Flow — JWT-basiert, mit Scope-Beschränkung.

Vertieft in Kap 18 api-keys-vs-tokens.

Was Auth NICHT löst

Ein verbreiteter Trugschluss: „Wir haben Auth, also sind wir sicher." Auth löst nur einen Ausschnitt:

  • Auth identifiziert den User — sagt aber nichts darüber, ob seine Aktionen erlaubt sind (AuthZ).
  • Auth verhindert nicht XSS — wenn der User-Code im Browser geknackt wird, kann der Angreifer im Namen des Users handeln (siehe Kap 11).
  • Auth verhindert nicht CSRF — eingeloggter User kann von fremden Sites ausgenutzt werden, wenn keine CSRF-Token gesetzt sind (siehe Kap 12).
  • Auth verhindert nicht IDOR — eingeloggter User A kann auf Daten von User B zugreifen, wenn Resource-Owner-Checks fehlen (siehe Kap 15 idor-und-bola).
  • Auth verhindert nicht Account-Übernahme — Phishing, Password-Reuse, SIM-Swap, Recovery-Lücken bleiben Vektoren.

Auth ist eine Schicht — nicht die Sicherheit.

Standards und Frameworks

Für Web-Auth gibt es etablierte Standards und Library-Familien:

Standard / LibWas es löstWann nutzen
NIST SP 800-63BDigital Identity GuidelinesCompliance-Anforderungen, MFA-Level (AAL1/2/3)
OAuth 2.1 / RFC 9700Delegated AuthorizationDrittanbieter-Zugriff, Login-with-X
OIDC 1.0Identity-Layer auf OAuthSSO, Login-with-X mit User-Info
WebAuthn L3Phishing-resistente AuthPasskeys, Hardware-Keys
SAML 2.0XML-basiertes SSOEnterprise-SSO, Legacy
Passport.jsNode.js-Auth-MiddlewareExpress/Fastify-Apps mit Multi-Strategy-Login
DeviseRails-Auth-LibraryRails-Apps
Django authBuilt-inDjango-Apps
NextAuth.js / Auth.jsNext.js AuthNext.js-Apps mit OAuth-Providers
Keycloak / Ory / AutheliaStandalone Identity-ProviderMicroservices-Stacks, Self-Hosted SSO
Auth0 / Okta / ClerkSaaS-Identity-ProviderWenn Auth nicht selbst betrieben werden soll

Empfehlung: Auth-Kern niemals selbst implementieren. Für klassische Web-Apps eine etablierte Library nutzen (Django, Devise, Passport, NextAuth). Für Microservices ein Identity-Provider (Keycloak, Ory) oder ein SaaS (Auth0). Die meisten Auth-CVEs entstehen in selbst-gebautem Code.

Interessantes

NIST SP 800-63B Authentication Assurance Levels (AAL)

Die NIST-Klassifizierung unterteilt Auth in drei Sicherheits-Stufen: AAL1 (mindestens ein Faktor), AAL2 (zwei verschiedene Faktoren, MFA-Pflicht), AAL3 (Hardware-basierter zweiter Faktor, Phishing-resistent — also FIDO2/WebAuthn oder vergleichbar). Compliance-Anforderungen (z. B. NIST SP 800-63B) referenzieren diese Stufen direkt.

Passkeys sind die kommende Default-Methode

Apple, Google und Microsoft haben Passkey-Support flächendeckend ausgerollt; passkeys.dev dokumentiert den Stack. 2025/2026 ist der Konsens: passwort-basierte Logins ergänzen, nicht ersetzen — aber neu gebaute Auth-Flows sollten Passkeys von Anfang an unterstützen, nicht nachrüsten. Vertieft in webauthn-und-passkeys.

"Magic Link" als passwortloser Workflow

Statt Passwort: User gibt E-Mail an, bekommt Link in der Mail, klickt — eingeloggt. Beispiele: Slack, Notion, Medium. Vorteile: kein Passwort-Storage, kein Reset-Flow. Nachteile: Mail-Account-Sicherheit wird zum Single Point, Link-Hijacking bei Mail-Konto-Übernahme. Sinnvoll als zusätzliche Methode neben Passkey/Passwort, selten als einzige.

Login as User für Support — fast immer falsch implementiert

Support-Teams brauchen manchmal einen „Impersonate User"-Modus. Klassisches Pattern: Admin-User generiert eine kurzfristige Token, die einen anderen User-Kontext bekommt. Fallen: (1) keine Trennung des Logging-Kontexts (Aktion erscheint als vom echten User), (2) keine Re-Auth, (3) keine Zeitbegrenzung, (4) keine Zustimmung des Endusers. Saubere Implementierung: separater Session-Flag „impersonated_by", expliziter Audit-Log, kurzer Time-Limit, idealerweise mit User-Notification.

OWASP ASVS als praktischer Checklist-Standard

Der OWASP ASVS (Application Security Verification Standard) hat in Kapitel V2/V3 detaillierte Auth-Anforderungen pro Sicherheits-Level. Praktisch für: Selbst-Audit, Lasten-/Pflichtenheft, Security-Reviews mit dem Team. Stand 2026: ASVS 5.0.

Account-Linking ist eine eigene Klasse

Wenn ein User mit Google-Login UND mit Passwort einloggen kann — wer „besitzt" den Account? Klassische Lücke: Angreifer registriert mit Passwort auf Mail-Adresse des Opfers, Opfer macht später Google-Login, beide landen im selben Account — Angreifer hat Zugriff. Saubere Implementierung: E-Mail-Verifikation vor Account-Aktivierung, kein automatisches Linking ohne explizite User-Aktion.

Weiterführende Ressourcen

Externe Quellen

/ Weiter

Zurück zu Authentifizierung (Entwickler)

Zur Übersicht