Single Sign-on
Single Sign-on lässt einen externen Identitätsanbieter (IdP) entscheiden, wer sich an deinem Control Center-Server anmelden darf. Zwei Protokolle werden unterstützt — SAML 2.0 und OpenID Connect — und beide landen an derselben Stelle: frisch ausgestellte Geräteanmeldedaten, die sich danach nirgends von einer Einladung oder einer QR-Kopplung unterscheiden lassen.
So läuft eine Anmeldung
Abschnitt betitelt „So läuft eine Anmeldung“SAML-Anmeldungen sind über den Browser vermittelt. Der IdP öffnet nie selbst eine Verbindung zu deinem Server; der Browser der anmeldenden Person trägt alles:
browser ──> /saml/login ──> IdP ──POST SAMLResponse──> /saml/acs │ verify ▼ provision user (maybe) │ ▼ browser handoff: device PSK in the URL fragment (never a query parameter)Weil der Browser der Bote ist, funktioniert ein Server hinter NAT für Anmeldungen problemlos: localhost, LAN, Tailscale, VPN oder ein Tunnel reichen alle — nur der Browser der Person muss die ACS-URL erreichen. Das WebSocket-Relay der Telefon-Fernsteuerung kann den HTTP-Roundtrip nicht tragen. Deshalb zielen die SSO-Einstiegspunkte immer auf den HTTP-Origin des Servers.
OpenID Connect folgt derselben Form, mit einem Roundtrip aus Authorization Code und PKCE. Die Claims liest der Server über TLS vom Token-Endpunkt des Issuers, der Browser liefert also überhaupt keine Identitätsdaten.
Die Adapter
Abschnitt betitelt „Die Adapter“Control Center teilt die Verantwortung bewusst auf:
| Baustein | Ort | Verantwortet |
|---|---|---|
Native-Bibliothek cc_saml |
packages/cc_natives/native/saml/ |
Prüfung von XML-DSig, Kanonisierung, Validierung des SAML-Profils — delegiert an die gepinnte Crate saml in reinem Rust hinter einem zustandslosen C-ABI |
SamlService / OidcService |
cc_server_core |
Anmeldezustand (Tracker für offene Requests, Replay-Deduplizierung), Stellschrauben der Validierungsrichtlinie, der gemeinsame Provisionierungsaufruf |
SsoProvisioner |
cc_server_core |
den User finden oder anlegen, das Subject des Anbieters festschreiben, Mitgliedschaften nach der Auto-Member-Richtlinie vergeben |
ScimService |
cc_server_core |
die Push-Oberfläche von SCIM 2.0 (Lebenszyklus von Provisionierung und Deprovisionierung) |
SsoSettingsService |
cc_server_core |
die gespeicherten Verbindungszeilen, das sofortige erneute Anwenden, das SCIM-Token |
Absichtlich gibt es keinen SAML-Krypto-Fallback in reinem Dart: von Hand
geschriebene XML-DSig- und Kanonisierungslogik ist genau der Ort, an dem
Signature-Wrapping-Lücken sitzen. Fehlt die Bibliothek cc_saml, lehnt der
Server sowohl die SAML-Anmeldung als auch den Start ab. Das Native ist
absichtlich zustandslos — Zustand über Requests hinweg liegt in den
Dart-Services, einmal verwendbar und kurzlebig.
Was eine Anmeldung prüft
Abschnitt betitelt „Was eine Anmeldung prüft“Im geprüften Native und im Service, in dieser Reihenfolge:
- die Signatur der Assertion (immer erforderlich; die des Antwort-Umschlags ist je nach Konfiguration optional) — strukturell gegen Signature Wrapping geschützt, weil die geprüfte Nutzlast an das verifizierte Element gebunden ist,
- der Issuer dem konfigurierten IdP entspricht,
- die Audience diesen Service Provider nennt,
- die Destination unsere ACS-URL ist,
InResponseTozu einem offenen AuthnRequest passt, den wir ausgestellt haben (unaufgeforderte, vom IdP initiierte Antworten sind standardmäßig aus),- die Gültigkeitsfenster innerhalb der Zeitabweichung halten (Vorgabe 90 s) und
- die Assertion-ID noch nie gesehen wurde (Replay-Cache).
Fehler kommen als typisierte Codes zurück — signature, expired, audience, destination, issuer, request-match — und die Endpunkte antworten mit allgemeinen Fehlern. Ein Angreifer erfährt also nichts darüber, warum eine Fälschung gescheitert ist.
Konten und das Festschreiben des Subjects
Abschnitt betitelt „Konten und das Festschreiben des Subjects“Die erste SSO-Anmeldung schreibt das unveränderliche Subject des Anbieters
(issuer plus SAML-NameID / OIDC-sub oder SCIM-externalId) am Konto fest.
Danach identifiziert das Subject die Anmeldung, nicht die E-Mail. Legt später
jemand dieselbe E-Mail vom selben oder einem anderen IdP vor, lehnt das
festgeschriebene Konto ab. Genau das verhindert, dass eine beim Anbieter
wiedervergebene E-Mail zur Kontoübernahme wird.
Provisionierung und Deprovisionierung
Abschnitt betitelt „Provisionierung und Deprovisionierung“Die JIT-Provisionierung passiert bei der Anmeldung (SsoProvisioner). SCIM
ist eine eigene Push-Oberfläche (ScimService), die dasselbe Subject an der
User-Zeile festschreibt; Mitgliedschaften im Arbeitsbereich vergibt sie
nicht. Die Deprovisionierung — SCIM active: false oder DELETE — lehnt ab,
wenn das Konto Eigentümer eines Arbeitsbereichs ist (zuerst übertragen).
Sonst widerruft sie zuerst alle Geräteanmeldedaten (Sitzungen fallen
innerhalb von Sekunden über die Geräteüberwachung weg), entfernt jede
Mitgliedschaft im Arbeitsbereich und stempelt das Konto als deaktiviert. Die
User-Zeile bleibt: die Zuordnung ist dauerhaft. Eine Reaktivierung stellt die
Anmeldung wieder her, vergibt Mitgliedschaften aber nie erneut.
Was außen vor bleibt
Abschnitt betitelt „Was außen vor bleibt“- Die Zuordnung Gruppe→Rolle passiert bei der Anmeldung aus den SAML-Attributen bzw. den OIDC-Claims — per Push gelieferte SCIM-Gruppen werden nicht gespeichert.
- Die Rolle Eigentümer ist über SSO nicht erreichbar — weder als Standardrolle noch über eine Gruppenzuordnung.
- Das WebSocket-Relay ist nie ein SSO-Kanal. Telefone, die den Server nur über das Relay erreichen, können darüber keinen Browser-Roundtrip zu Ende bringen.