Sari la conținut

Autentificare unică

Autentificarea unică permite unui furnizor de identitate (IdP) extern să decidă cine se poate autentifica pe serverul tău Control Center. Sunt acceptate două protocoale — SAML 2.0 și OpenID Connect — și ambele ajung în același loc: un credențial de dispozitiv proaspăt emis, imposibil de distins de o invitație sau de o asociere prin cod QR în tot restul lanțului.

Autentificările SAML sunt mediate de browser. IdP-ul nu deschide niciodată o conexiune către serverul tău; browserul utilizatorului duce totul:

browser ──> /saml/login ──> IdP ──POST SAMLResponse──> /saml/acs
│ verify
▼
provision user (maybe)
│
▼
browser handoff: device PSK in the URL
fragment (never a query parameter)

Deoarece browserul este curierul, un server aflat în spatele NAT funcționează fără probleme pentru autentificări: localhost, LAN, Tailscale, VPN sau un tunel sunt toate valabile — doar browserul utilizatorului trebuie să ajungă la URL-ul ACS. Releul WebSocket folosit de controlul remote de pe telefon nu poate transporta ciclul dus-întors HTTP, motiv pentru care punctele de intrare SSO vizează întotdeauna originea HTTP a serverului.

OpenID Connect urmează aceeași formă, cu un ciclu dus-întors de tip authorization-code + PKCE; revendicările sunt citite de la endpoint-ul de token al emitentului prin TLS, astfel încât browserul nu furnizează deloc date de identitate.

Control Center împarte responsabilitatea în mod deliberat:

Componentă Unde Deține
cc_saml native packages/cc_natives/native/saml/ verificarea XML-DSig, canonicalizarea, validarea profilului SAML — delegate către crate-ul saml pur-Rust fixat, în spatele unei ABI C fără stare
SamlService / OidcService cc_server_core starea autentificării (urmăritorii cererilor în așteptare, deduplicarea reluărilor), opțiunile de politică pentru validare, apelul de provisionare partajat
SsoProvisioner cc_server_core găsește-sau-creează utilizatorul, fixează subiectul furnizorului, acordă apartenențe conform politicii de membru automat
ScimService cc_server_core suprafața de push SCIM 2.0 (ciclul de viață de provisionare/deprovisionare)
SsoSettingsService cc_server_core rândurile de conexiune salvate, reaplicarea în direct, tokenul SCIM

Nu există în mod deliberat niciun fallback criptografic SAML pur-Dart: XML-DSig/canonicalizarea scrise de mână sunt exact locul în care trăiesc vulnerabilitățile de tip signature-wrapping, așa că o bibliotecă cc_saml lipsă refuză atât autentificarea SAML, cât și pornirea serverului. Componenta nativă este fără stare prin proiectare — starea care traversează cererile trăiește în serviciile Dart, de unică folosință și cu durată scurtă de viață.

În interiorul componentei native verificate și al serviciului, în ordine:

  1. semnătura aserțiunii (întotdeauna obligatorie; cea a plicului de răspuns este opțională, în funcție de configurare) — rezistentă structural la signature-wrapping, deoarece încărcătura validată este legată de elementul verificat,
  2. emitentul corespunde IdP-ului configurat,
  3. audiența numește acest furnizor de servicii,
  4. destinația este URL-ul nostru ACS,
  5. InResponseTo corespunde unui AuthnRequest în așteptare pe care l-am emis (răspunsurile nesolicitate, inițiate de IdP, sunt dezactivate implicit),
  6. ferestrele de durată de viață se încadrează în decalajul de ceas (implicit 90s) și
  7. id-ul aserțiunii nu a mai fost văzut niciodată (cache de reluare).

Eșecurile se întorc sub formă de coduri tipizate — signature, expired, audience, destination, issuer, request-match — iar endpoint-urile răspund cu erori generice, astfel încât un atacator nu află nimic despre motivul pentru care o falsificare a eșuat.

Prima autentificare SSO fixează pe cont subiectul imuabil al furnizorului (issuer plus NameID SAML / sub OIDC, sau externalId SCIM). De atunci înainte, subiectul — nu adresa de e-mail — identifică autentificarea. Dacă altcineva prezintă ulterior aceeași adresă de e-mail din partea aceluiași IdP sau a altuia, contul fixat îl refuză. Acesta este lucrul care împiedică o adresă de e-mail reciclată la un furnizor să devină o preluare de cont.

Provisionarea JIT are loc la autentificare (SsoProvisioner). SCIM este o suprafață de push separată (ScimService) care fixează același subiect pe rândul utilizatorului; ea nu acordă apartenențe la spații de lucru. Deprovisionarea — SCIM active: false sau DELETE — refuză dacă contul este proprietar de spațiu de lucru (transferă mai întâi). În caz contrar, revocă mai întâi fiecare credențial de dispozitiv (sesiunile cad în câteva secunde prin monitorizarea dispozitivelor), elimină fiecare apartenență la spații de lucru și marchează contul ca dezactivat. Rândul utilizatorului supraviețuiește: atribuirea este permanentă. Reactivarea restaurează autentificarea, dar nu reacordă niciodată apartenențele.

  • Maparea grup→rol are loc la autentificare, din atributele SAML / revendicările OIDC — grupurile trimise prin SCIM nu sunt stocate.
  • Rolul de proprietar este inaccesibil din SSO — nici ca rol implicit, nici printr-o mapare de grup.
  • Releul WebSocket nu este niciodată un canal SSO; telefoanele care ajung la server doar prin releu nu pot finaliza împotriva lui un ciclu dus-întors în browser.