Fünf Schritte von „Anmelden klicken" bis zum signierten JWT in der Relying Party. Der IdP vermittelt Identität; das Passwort verlässt nie den Browser; unterwegs sind ausschließlich kurzlebige, signierte Tokens.
Fünf Hops · Passwort verlässt nie den Browser · kein Cookie gesetzt
Browser → IdP
01 / Authorize
Die PKCE-Challenge
Der Nutzer klickt Anmelden. Der Browser erzeugt einen zufälligen Code Verifier, hasht ihn zu einer Code Challenge, legt beide im sessionStorage ab und leitet auf /oidc.ashx?action=authorize mit Challenge und einem CSRF-state-Token weiter.
Browser → IdP
02 / Login
Nur HA1, niemals Klartext
/login.html zeigt ein Formular. Der Browser berechnet MD5(user:realm:password) und sendet ausschließlich diesen Hash per POST. Der Server vergleicht konstant-zeitig gegen den gespeicherten HA1. Das Klartext-Passwort verlässt nie den Browser; der Server sieht es selbst bei vollständigem Request-Log nicht.
IdP → Browser → RP
03 / Code
Einmal-Auth-Code
Bei HA1-Übereinstimmung erzeugt der IdP einen 60-Sekunden-Einmal-Auth-Code und leitet den Browser auf Ihre redirect_uri mit ?code=...&state=... um. Cookie-frei: Der IdP setzt oder liest kein Session-Cookie — der Code wandert ausschließlich in der URL.
RP → IdP
04 / Token
Code + Verifier tauschen
Ihre Anwendung prüft state und sendet dann Code plus PKCE-Code Verifier per POST an /oidc.ashx?action=token. Der IdP bestätigt, dass der Verifier zur ursprünglichen Challenge hasht, verbrennt den Code und liefert drei JWTs zurück.
IdP → RP
05 / Tokens
Access + ID + Refresh
Drei RS256-signierte JWTs. access_token (1 Stunde) für API-Aufrufe. id_token (1 Stunde) trägt Identitäts-Claims (sub, role, email). refresh_token (4 Stunden, einmalig rotierend) kauft das nächste Access-Token. Ihre Anwendung prüft die Signaturen gegen das JWKS unter /.well-known/jwks.json.
RP → Nutzer
06 / Angemeldet
Sie entscheiden, wie es weitergeht
Aus dem geprüften id_token haben Sie sub (den Benutzernamen) und role (admin / user / siponly / guest). Legen Sie den Nutzer in Ihre authentifizierte Sitzung ab. Brauchen Sie weitere Profilfelder, rufen Sie /userinfo mit dem Access-Token auf.
Was der IdP sieht vs. was er speichert
Der Job des IdP ist Identitätsprüfung, keine Überwachung. Jede Anfrage erhält das Minimum an Daten, das genau diese eine Aufgabe erfordert, und nichts wird über das hinaus persistiert, was Audit und Token-Validierung verlangen.
Sieht pro Anfrage: den behaupteten Benutzernamen, den HA1-Hash (nie den Klartext), client_id und redirect_uri der Relying Party, die Quell-IP fürs Rate-Limit.
Persistiert auf Festplatte: eine JSONL-Audit-Zeile pro Anmeldeversuch (erfolgreich oder nicht) in App_Data/<tenant>/logs/codeb-oidc-YYYY-MM-DD.log. Bedeutsame Ereignisse landen zusätzlich im Windows-Event-Log unter der Quelle CodeBOIDC.
Persistiert nur im Speicher: Auth-Codes (60 s), Refresh-Tokens (4 h). Ein Recycling des Worker-Prozesses wischt sie weg — Nutzer mit aktivem Refresh-Token müssen sich neu anmelden.
Speichert nie: Klartext-Passwörter, ID-Tokens, Access-Tokens, die Antwort der RP an den Nutzer. Keine Tracking-Cookies, keine tenant-übergreifende Korrelation.
Wo die Vertrauensgrenzen verlaufen
Ein OIDC-Ablauf hat drei Akteure (Nutzer, IdP, Relying Party). Vertrauen ist beidseitig und begrenzt:
Der Nutzer vertraut dem IdP den HA1-Hash an (der für SIP REGISTER Passwort-Äquivalent ist — entsprechend zu behandeln). HTTPS + HSTS sichert die Leitung; das konstant-zeitige Vergleichen im IdP verhindert das Byte-für-Byte-Timing-Leak.
Die RP vertraut der Signatur des IdP. Jedes Token ist RS256 mit dem tenant-eigenen privaten Schlüssel signiert. Die RP prüft gegen das veröffentlichte JWKS, kontrolliert iss auf Übereinstimmung mit dem IdP, aud auf Übereinstimmung mit der RP, und dass exp noch nicht abgelaufen ist.
Der IdP vertraut der vorab registrierten Redirect-URI. Auth-Codes wandern ausschließlich an URIs, die der Betreiber zeichenweise freigegeben hat. Das verhindert, dass ein Angreifer einen eigenen Callback einfügt, um Tokens abzufangen.
Der Browser ist der gefährliche Punkt. XSS in den Seiten der RP erlaubt es einem Angreifer, die Tokens im sessionStorage auszulesen; deshalb haben Refresh-Tokens nur 4 Stunden Laufzeit, rotieren bei jeder Nutzung und werden in dem Moment widerrufen, in dem ein wiederverwendetes Token erkannt wird.
Mandanten-Isolation im Ablauf
Die Mandanten-Identität ist der Request-Host. Das Diagramm oben läuft pro Mandant einmal, ohne gemeinsamen Zustand zwischen Mandanten:
Eigene Signier-Schlüssel. Jeder Mandant hat seinen eigenen 2048-Bit-RSA-Schlüssel unter App_Data/<tenant>/oidc/private-key.xml. Ein in Mandant A geprägtes Token scheitert in Mandant B an der Signaturprüfung.
Eigene Credential-Speicher. Die HA1-Prüfung in Schritt 2 liest aus App_Data/<tenant>/sip-credentials/<tenant-slug>.json. Benutzernamen über Mandanten hinweg kollidieren nicht.
Eigene Audit-Logs. Jedes Ereignis ist auf App_Data/<tenant>/logs/ begrenzt. Mandantenübergreifender Log-Zugriff ist aus dem IdP heraus unmöglich.
Eigene Issuer-URLs. Der iss-Claim in jedem Token ist https://<jener-tenant-host>. Server, die das Token prüfen, MÜSSEN iss mit der erwarteten URL vergleichen.
Gegenüber dem Medien-Datenfluss
Der Medien-Datenfluss ist Peer-to-Peer: Video und Audio berühren den Server nie, nur das Signaling. OIDC hat die entgegengesetzte Form — alles geht über den IdP, weil Identität per Definition zentralisiert ist. Gemeinsam ist beiden, was NICHT gespeichert wird: Der IdP behält Tokens nach Ausgabe nicht; der Signaling-Server behält Medien-Frames nach Weiterleitung der SDP nicht.