OpenID Connect: autorizarea aplicațiilor interne de la personalizate la standard

Acum câteva luni, implementam un server OpenID Connect pentru a gestiona accesul pentru sute de aplicații noastre interne. Din propriile noastre dezvoltări, convenabile la o scară mai mică, am trecut la un standard general acceptat. Accesul prin intermediul serviciului central simplifică foarte mult operațiunile monotone, reduce costurile de implementare a autorizațiilor, vă permite să găsiți multe soluții gata făcute și să nu vă deranjeze mintea atunci când dezvoltați altele noi. În acest articol, voi vorbi despre această tranziție și denivelările pe care am reușit să le umplem.

OpenID Connect: autorizarea aplicațiilor interne de la personalizate la standard

Cu mult timp în urmă... Cum a început totul

Acum câțiva ani, când erau prea multe aplicații interne pentru control manual, am scris o aplicație pentru controlul accesului în cadrul companiei. Era o aplicație simplă Rails care se conecta la o bază de date cu informații despre angajați, unde era configurat accesul la diverse funcționalități. Totodată, am ridicat primul SSO, care s-a bazat pe verificarea token-urilor din partea clientului și a serverului de autorizare, token-ul a fost transmis în formă criptată cu mai mulți parametri și verificat pe serverul de autorizare. Aceasta nu a fost cea mai convenabilă opțiune, deoarece fiecare aplicație internă trebuia să descrie un nivel considerabil de logică, iar bazele de date ale angajaților erau complet sincronizate cu serverul de autorizare.

După ceva timp, am decis să simplificăm sarcina de autorizare centralizată. SSO a fost transferat către echilibrator. Cu ajutorul OpenResty, la Lua a fost adăugat un șablon care verifica jetoanele, știa la ce aplicație se îndreaptă cererea și putea verifica dacă există acces acolo. Această abordare a simplificat foarte mult sarcina de a controla accesul la aplicațiile interne - în codul fiecărei aplicații, nu mai era necesar să se descrie o logică suplimentară. Drept urmare, am închis traficul extern, iar aplicația în sine nu știa nimic despre autorizare.

Cu toate acestea, o problemă a rămas nerezolvată. Dar aplicațiile care au nevoie de informații despre angajați? Era posibil să scrieți un API pentru serviciul de autorizare, dar apoi ar trebui să adăugați o logică suplimentară pentru fiecare astfel de aplicație. În plus, am vrut să scăpăm de dependența de una dintre aplicațiile noastre auto-scrise, care ulterior avea să fie tradusă în OpenSource, pe serverul nostru intern de autorizare. Vom vorbi despre asta altădată. Soluția la ambele probleme a fost OAuth.

la standarde comune

OAuth este un standard de autorizare de înțeles, general acceptat, dar, deoarece doar funcționalitatea sa nu este suficientă, au început imediat să ia în considerare OpenID Connect (OIDC). OIDC în sine este a treia implementare a standardului de autentificare deschisă, care a fost transformată într-un add-on peste protocolul OAuth 2.0 (un protocol de autorizare deschis). Această soluție închide problema lipsei de date despre utilizatorul final și, de asemenea, face posibilă schimbarea furnizorului de autorizare.

Cu toate acestea, nu am ales un anumit furnizor și am decis să adăugăm integrarea cu OIDC pentru serverul nostru de autorizare existent. În favoarea acestei decizii a fost faptul că OIDC este foarte flexibil în ceea ce privește autorizarea utilizatorului final. Astfel, a fost posibil să implementați suportul OIDC pe serverul dvs. de autorizare actual.

OpenID Connect: autorizarea aplicațiilor interne de la personalizate la standard

Modul nostru de a implementa propriul nostru server OIDC

1) Adus datele în forma dorită

Pentru a integra OIDC, este necesar să aduceți datele curente ale utilizatorului într-o formă înțeleasă de standard. În OIDC acest lucru se numește Revendicări. Revendicările sunt în esență câmpuri finale din baza de date a utilizatorilor (nume, e-mail, telefon etc.). Există lista standard de timbre, iar tot ceea ce nu este inclus în această listă este considerat personalizat. Prin urmare, primul punct la care trebuie să acordați atenție dacă doriți să alegeți un furnizor OIDC existent este posibilitatea personalizării convenabile a noilor mărci.

Grupul de semne distinctive este combinat în următorul subset - Domeniu. În timpul autorizării, se solicită accesul nu la anumite mărci, ci la domenii, chiar dacă unele dintre mărcile din domeniu nu sunt necesare.

2) A implementat granturile necesare

Următoarea parte a integrării OIDC este selectarea și implementarea tipurilor de autorizare, așa-numitele granturi. Scenariul suplimentar de interacțiune între aplicația selectată și serverul de autorizare va depinde de grantul selectat. O schemă exemplară pentru alegerea subvenției potrivite este prezentată în figura de mai jos.

OpenID Connect: autorizarea aplicațiilor interne de la personalizate la standard

Pentru prima noastră cerere, am folosit cel mai comun grant, Codul de autorizare. Diferența sa față de ceilalți este că este în trei pași, adică. este supus unor teste suplimentare. Mai întâi, utilizatorul face o cerere de autorizare, primește un token - Cod de autorizare, apoi cu acest token, ca și cum ar avea un bilet de călătorie, solicită un token de acces. Toată interacțiunea principală a acestui script de autorizare se bazează pe redirecționări între aplicație și serverul de autorizare. Puteți citi mai multe despre acest grant aici.

OAuth aderă la conceptul conform căruia tokenurile de acces obținute după autorizare ar trebui să fie temporare și ar trebui să se schimbe, de preferință la fiecare 10 minute în medie. Acordarea Codului de Autorizare este o verificare în trei pași prin redirecționări, la fiecare 10 minute pentru a transforma un astfel de pas, sincer, nu este cea mai plăcută sarcină pentru ochi. Pentru a rezolva această problemă, există un alt grant - Refresh Token, pe care l-am folosit și în țara noastră. Totul este mai ușor aici. În timpul verificării dintr-un alt grant, pe lângă tokenul de acces principal, se emite un altul - Refresh Token, care poate fi folosit o singură dată și durata de viață a acestuia este de obicei mult mai lungă. Cu acest Token de reîmprospătare, când se termină TTL (Time to Live) al jetonului de acces principal, cererea pentru un nou jeton de acces va ajunge la punctul final al unei alte granturi. Tokenul de reîmprospătare utilizat este resetat imediat la zero. Această verificare este în două etape și poate fi efectuată în fundal, imperceptibil pentru utilizator.

3) Configurați formate personalizate de ieșire a datelor

După implementarea granturilor selectate, autorizarea funcționează, merită menționat obținerea de date despre utilizatorul final. OIDC are un punct final separat pentru aceasta, unde puteți solicita date despre utilizator cu simbolul de acces actual și dacă este actualizat. Și dacă datele utilizatorului nu se schimbă atât de des și trebuie să le urmați pe cele actuale de multe ori, puteți ajunge la o astfel de soluție precum jetoanele JWT. Aceste jetoane sunt, de asemenea, acceptate de standard. Token-ul JWT în sine constă din trei părți: antet (informații despre token), sarcină utilă (orice date necesare) și semnătură (semnătură, jetonul este semnat de server și puteți verifica ulterior sursa semnăturii sale).

În implementarea OIDC, jetonul JWT se numește id_token. Poate fi solicitat împreună cu un token de acces obișnuit și tot ce rămâne este să verifici semnătura. Serverul de autorizare are un punct final separat pentru aceasta, cu o grămadă de chei publice în format J.W.K.. Și vorbind despre asta, merită menționat că există un alt punct final, care, bazat pe standard RFC5785 reflectă configurația curentă a serverului OIDC. Conține toate adresele punctelor finale (inclusiv adresa inelului de chei publice utilizate pentru semnare), mărci și domenii acceptate, algoritmi de criptare utilizați, granturi acceptate etc.

De exemplu pe Google:

{
 "issuer": "https://accounts.google.com",
 "authorization_endpoint": "https://accounts.google.com/o/oauth2/v2/auth",
 "device_authorization_endpoint": "https://oauth2.googleapis.com/device/code",
 "token_endpoint": "https://oauth2.googleapis.com/token",
 "userinfo_endpoint": "https://openidconnect.googleapis.com/v1/userinfo",
 "revocation_endpoint": "https://oauth2.googleapis.com/revoke",
 "jwks_uri": "https://www.googleapis.com/oauth2/v3/certs",
 "response_types_supported": [
  "code",
  "token",
  "id_token",
  "code token",
  "code id_token",
  "token id_token",
  "code token id_token",
  "none"
 ],
 "subject_types_supported": [
  "public"
 ],
 "id_token_signing_alg_values_supported": [
  "RS256"
 ],
 "scopes_supported": [
  "openid",
  "email",
  "profile"
 ],
 "token_endpoint_auth_methods_supported": [
  "client_secret_post",
  "client_secret_basic"
 ],
 "claims_supported": [
  "aud",
  "email",
  "email_verified",
  "exp",
  "family_name",
  "given_name",
  "iat",
  "iss",
  "locale",
  "name",
  "picture",
  "sub"
 ],
 "code_challenge_methods_supported": [
  "plain",
  "S256"
 ],
 "grant_types_supported": [
  "authorization_code",
  "refresh_token",
  "urn:ietf:params:oauth:grant-type:device_code",
  "urn:ietf:params:oauth:grant-type:jwt-bearer"
 ]
}

Astfel, folosind id_token, puteți transfera toate semnele distinctive necesare în sarcina utilă a jetonului și nu contactați serverul de autorizare de fiecare dată pentru a solicita datele utilizatorului. Dezavantajul acestei abordări este că modificarea datelor utilizatorului de pe server nu vine imediat, ci împreună cu un nou token de acces.

Rezultatele implementarii

Deci, după implementarea propriului nostru server OIDC și configurarea conexiunilor la acesta din partea aplicației, am rezolvat problema transferului de informații despre utilizatori.
Deoarece OIDC este un standard deschis, avem opțiunea de a alege un furnizor existent sau o implementare de server. Am încercat Keycloak, care s-a dovedit a fi foarte convenabil de configurat, după configurarea și modificarea configurațiilor de conexiune din partea aplicației, este gata de funcționare. În ceea ce privește aplicația, tot ce rămâne este să schimbați configurațiile conexiunii.

Vorbind despre soluțiile existente

În cadrul organizației noastre, ca prim server OIDC, am asamblat propria noastră implementare, care a fost completată după cum a fost necesar. După o revizuire detaliată a altor soluții gata făcute, putem spune că acesta este un punct discutabil. În favoarea deciziei de a implementa propriul server, au existat îngrijorări din partea furnizorilor cu privire la absența funcționalității necesare, precum și prezența unui sistem vechi în care existau diferite autorizații personalizate pentru unele servicii și destul de multe de date despre angajați a fost deja stocată. Cu toate acestea, în implementările gata făcute, există facilități pentru integrare. De exemplu, Keycloak are propriul sistem de gestionare a utilizatorilor și datele sunt stocate direct în el și nu va fi dificil să-ți depășești utilizatorii acolo. Pentru a face acest lucru, Keycloak are un API care vă va permite să efectuați pe deplin toate acțiunile de transfer necesare.

Un alt exemplu de implementare certificată, interesantă, după părerea mea, este Ory Hydra. Este interesant pentru că este format din diferite componente. Pentru integrare, va trebui să vă conectați serviciul de gestionare a utilizatorilor la serviciul de autorizare al acestora și să vă extindeți după cum este necesar.

Keycloak și Ory Hydra nu sunt singurele soluții disponibile. Cel mai bine este să alegeți o implementare certificată de OpenID Foundation. Aceste soluții au de obicei o insignă de certificare OpenID.

OpenID Connect: autorizarea aplicațiilor interne de la personalizate la standard

De asemenea, nu uitați de furnizorii plătiți existenți dacă nu doriți să vă păstrați serverul OIDC. Astăzi există multe opțiuni bune.

Ce urmează

În viitorul apropiat, vom închide traficul către serviciile interne într-un mod diferit. Intenționăm să transferăm SSO-ul nostru actual pe echilibrator utilizând OpenResty la un proxy bazat pe OAuth. Există deja multe soluții gata făcute aici, de exemplu:
github.com/bitly/oauth2_proxy
github.com/ory/oathkeeper
github.com/keycloak/keycloak-gatekeeper

Materiale suplimentare

jwt.io – serviciu bun pentru validarea jetoanelor JWT
openid.net/developers/certified - lista implementărilor certificate OIDC

Sursa: www.habr.com

Adauga un comentariu