În orice companie mare, inclusiv X5 Retail Group, pe măsură ce evoluează, crește numărul proiectelor în care este necesară autentificarea utilizatorilor. Odată cu trecerea timpului, este necesar un transfer fără cusur al utilizatorilor dintr-o aplicație în alta, iar atunci apare necesitatea de a utiliza un server unic de autentificare Single-Sign-On (SSO). Dar ce să facem atunci când astfel de furnizori de identificare precum AD sau altele, care nu au atribute suplimentare, sunt deja folosiți în diferite proiecte. În ajutor vine o clasă de sisteme numită „brokeri de identificare”. Cele mai funcționale dintre acestea sunt reprezentate de soluții precum Keycloak, Gravitee Access Management și altele. Cel mai frecvent scenariile de utilizare pot fi variate: interacțiuni automate, participarea utilizatorilor și altele. Soluția trebuie să suporte o funcționalitate flexibilă și scalabilă, capabilă să reunească toate cerințele într-una singură, iar soluția noastră la acest moment este brokerul de identificare – Keycloak.

Keycloak este un produs open-source destinat autentificării și gestionării accesului, susținut de compania RedHat. Este baza pentru produsele companiilor care utilizează SSO – RH-SSO.
Concepturi de bază
Înainte de a începe să ne ocupăm de soluții și abordări, trebuie să ne clarificăm termenii și ordinea proceselor:

Identificare — este procedura de recunoaștere a subiectului prin identificatorul său (pe scurt, aceasta este definirea numelui, a loginului sau a numărului).
Autentificare — este procedura de verificare a autenticității (utilizatorul este verificat prin parolă, scrisoarea este verificată prin semnătură electronică etc.)
Autorizare — este furnizarea accesului la un anumit resursă (de exemplu, la e-mail).
Brokerul de identificare Keycloak
Keycloak — este o soluție pentru gestionarea identificării și accesului cu sursă deschisă, destinată utilizării în sisteme informaționale în care pot fi utilizate tipare de arhitectură microservicii.
Keycloak oferă funcții precum autentificare unică (SSO), identificare broker și autentificare socială, federarea utilizatorilor, adaptoare pentru clienți, consolă de administrare și consolă de gestionare a conturilor.
Funcționalitatea de bază susținută în Keycloak:
- Single-Sign On și Single-Sign Out pentru aplicații web.
- Suport pentru OpenID/OAuth 2.0/SAML.
- Identity Brokering – autentificare prin intermediul furnizorilor de identitate externi OpenID Connect sau SAML.
- Social Login – suport pentru Google, GitHub, Facebook, Twitter pentru identificarea utilizatorilor.
- User Federation – sincronizarea utilizatorilor din servere LDAP și Active Directory și alți furnizori de identitate.
- Kerberos bridge – utilizarea serverului Kerberos pentru autentificarea automată a utilizatorilor.
- Admin Console — pentru gestionarea centralizată a setărilor și parametrilor soluției prin intermediul Web.
- Account Management Console – pentru autogestionarea profilului utilizatorilor.
- Personalizarea soluției pe baza stilului de brand al companiei.
- 2FA Authentication – suport pentru TOTP/HOTP prin Google Authenticator sau FreeOTP.
- Login Flows – posibilitatea auto-înregistrării utilizatorilor, recuperarea și resetarea parolei și altele.
- Session Management – administratorii pot gestiona sesiunile utilizatorilor dintr-un singur loc.
- Token Mappers – corelarea atributelor utilizatorilor, rolurilor și altor atribute necesare în tokenuri.
- Gestionarea flexibilă a politicilor prin realm, aplicație și utilizatori.
- CORS Support – adaptoare client pentru a avea suport încorporat pentru CORS.
- Service Provider Interfaces (SPI) – un număr mare de SPI-uri care permit configurarea diferitelor aspecte ale funcționării serverului: fluxuri de autentificare, furnizori de identitate, maparea protocoalelor și multe altele.
- Adaptoare client pentru aplicații JavaScript, WildFly, JBoss EAP, Fuse, Tomcat, Jetty, Spring.
- Suport pentru lucrul cu diferite aplicații care folosesc biblioteca OpenID Connect Relying Party sau SAML 2.0 Service Provider Library.
- Posibilitatea extinderii prin utilizarea pluginurilor.
Pentru procesele CI/CD, precum și pentru automatizarea proceselor de gestionare în Keycloak, poate fi utilizată REST API/JAVA API. Documentația este disponibilă în format electronic:
REST API
JAVA API
Furnizori de identitate la nivel de întreprindere (On-Premise)
Posibilitatea autentificării utilizatorilor prin serviciile User Federation.

De asemenea, poate fi utilizată autentificarea unică — dacă utilizatorii se autentifică pe stațiile de lucru cu Kerberos (LDAP sau AD), atunci aceștia pot fi autentificați automat în Keycloak fără a fi necesar să își reintroducă numele de utilizator și parola.
Pentru autentificarea și autorizarea ulterioară a utilizatorilor, se poate utiliza o bază de date relațională, ceea ce este cel mai aplicabil pentru mediile de dezvoltare, deoarece nu necesită configurații și integrare extinsă în etapele incipiente ale proiectelor. În mod implicit, Keycloak folosește o bază de date încorporată pentru stocarea setărilor și datelor utilizatorilor.
Lista bazelor de date suportate este extinsă și include: MS SQL, Oracle, PostgreSQL, MariaDB, Oracle și altele. Cele mai testate până în prezent sunt Oracle 12C Release1 RAC și clusterul Galera 3.12 pentru MariaDB 10.1.19.
Furnizori de identificare - conectare socială
Este posibilă utilizarea autentificării prin rețele sociale. Pentru a activa posibilitatea de autentificare a utilizatorilor, se utilizează consola de administrare Keycloak. Nu sunt necesare modificări în codul aplicațiilor, iar această funcționalitate este disponibilă 'din cutie' și poate fi activată în orice etapă a implementării proiectului.

Pentru autentificarea utilizatorilor, este posibilă utilizarea furnizorilor de identitate OpenID/SAML.
Scenarii tipice de autorizare utilizând OAuth2 în Keycloak
Fluxul codului de autorizare — este utilizat cu aplicațiile server-side. Este unul dintre cele mai frecvent întâlnite tipuri de permisiune pentru autorizare, deoarece se potrivește bine aplicațiilor server-side, în care codul sursă al aplicației și datele clientului nu sunt accesibile terților. Procesul se bazează pe redirecționare. Aplicația trebuie să poată interacționa cu agentul utilizatorului, cum ar fi un browser web - pentru a obține coduri de autorizare API redirecționate prin agentul utilizatorului.
Fluxul implicit — este utilizat de aplicațiile mobile sau web (aplicații care funcționează pe dispozitivul utilizatorului).
Tipul implicit de autorizare este utilizat de aplicațiile mobile și web unde confidențialitatea utilizatorului nu poate fi garantată. Tipul de autorizare implicit folosește, de asemenea, redirecționarea agentului utilizatorului, iar tokenul de acces este transmis agentului utilizatorului pentru utilizare ulterioară în aplicație. Acest lucru face ca tokenul să fie disponibil pentru utilizator și pentru alte aplicații de pe dispozitivul utilizatorului. În acest tip de autorizare nu se realizează autentificarea legitimității aplicației, iar întregul proces se bazează pe URL-ul de redirecționare (înregistrat anterior în serviciu).
Fluxul Implicit nu acceptă tokenuri de actualizare a tokenului de acces (refresh tokens).
Fluxul Client Credentials Grant — este utilizat atunci când aplicația accesează API-ul. Acest tip de autorizare este de obicei folosit pentru interacțiuni „server-server”, care trebuie să se desfășoare în fundal, fără interacțiune imediată cu utilizatorul. Fluxul de furnizare a acreditivului client permite unui serviciu web (client confidential) să folosească propriile sale acreditive în loc să se presupună identitatea utilizatorului pentru autentificare atunci când apelează un alt serviciu web. Pentru un nivel mai ridicat de securitate, este posibil ca serviciul apelant să folosească un certificat (în locul secretului comun) ca acreditive.
Specificarea OAuth2 este descrisă în
Tokenul JWT și avantajele sale
JWT (JSON Web Token) este un standard deschis (), care definește o modalitate compactă și autonomă de transmitere securizată a informațiilor între părți sub formă de obiect JSON.
Potrivit standardului, un token este compus din trei părți în format base-64, separate prin puncte. Prima parte se numește header, care conține tipul tokenului și numele algoritmului de hash pentru obținerea semnăturii digitale. A doua parte stochează informația principală (utilizator, atribute etc.). A treia parte este semnătura digitală.
..
Nu salvați niciodată tokenul în baza dvs. de date. Deoarece un token valid este echivalent cu o parolă, a salva un token este la fel cu a salva o parolă în clar.
Token de acces — este un token care oferă proprietarului său acces la resursele protejate ale serverului. De obicei, are o durată de viață scurtă și poate conține informații suplimentare, cum ar fi adresa IP a părții care solicită acest token.
Token de refresh — este un token care permite clienților să solicite noi token-uri de acces după expirarea duratei lor de viață. Aceste token-uri sunt de obicei emise pe o perioadă lungă.
Principalele avantaje ale utilizării în arhitectura microservicii:
- Posibilitatea de a accesa diverse aplicații și servicii prin autentificare unică.
- În absența unui număr de atribute necesare în profilul utilizatorilor, este posibilă îmbogățirea acestuia cu date ce pot fi adăugate în payload, inclusiv automatizat și „în timp real”.
- Nu este necesară stocarea informațiilor despre sesiunile active, aplicația de server trebuie doar să verifice semnătura.
- O gestionare mai flexibilă a accesului prin intermediul atributelor suplimentare în payload.
- Utilizarea semnăturii token-ului pentru headere și payload îmbunătățește securitatea soluției în ansamblu.
Token JWT — structură
Titlu — în mod implicit, header-ul conține doar tipul de token și algoritmul utilizat pentru criptare.
Tipul token-ului este stocat în cheia „typ”. Cheia „typ” este ignorată în JWT. Dacă cheia „typ” este prezentă, valoarea sa trebuie să fie JWT, pentru a indica faptul că acest obiect este un JSON Web Token.
Al doilea cheie „alg” definește algoritmul utilizat pentru criptarea token-ului. În mod implicit, acesta trebuie să fie setat la HS256. Header-ul este codificat în base64.
{ "alg": "HS256", "typ": "JWT"}
Payload (conținut) — în payload se stochează orice informație care trebuie verificată. Fiecare cheie din payload este cunoscută sub numele de „declarație”. De exemplu, în aplicație se poate intra doar pe invitație (promoție închisă). Atunci când dorim să invităm pe cineva să participe, îi trimitem un e-mail cu invitația. Este important să verificăm că adresa de e-mail îi aparține persoanei care acceptă invitația, așa că vom include această adresă în payload, salvând-o în cheia „e-mail”
{ "email": "example@x5.ru" }
Cheile din payload pot fi arbitrare. Cu toate acestea, există câteva rezervate:
- iss (Issuer) — definește aplicația din care este trimis token-ul.
- sub (Subiect) — definește tema token-ului.
- aud (Public) – un array de șiruri sensibile la case sau URI, care reprezintă lista destinatari ai acestui token. Când partea care primește JWT cu această cheie, trebuie să verifice dacă se regăsește în destinatari — altfel, să ignore token-ul.
- exp (Timp de Expirare) — indică momentul când expiră termenul de valabilitate al token-ului. Standardul JWT necesită ca în toate implementările sale, token-urile expirate să fie respinse. Cheia exp trebuie să fie un timestamp în format unix.
- nbf (Nu Începe Înainte) — este timpul în format unix, care definește momentul în care token-ul devine valid.
- iat (Emis La) — această cheie reprezintă momentul în care token-ul a fost emis și poate fi folosit pentru a determina vechimea JWT. Cheia iat trebuie să fie un timestamp în format unix.
- jti (ID JWT) — un șir care definește un identificator unic al acestui token, având în vedere case.
Este important să înțelegem că payload-ul nu este transmis sub formă criptată (deși, token-urile pot fi imbricate și atunci este posibil să se transmită date criptate). De aceea, nu este bine să stocăm informații sensibile aici. La fel ca și antetul, payload-ul este codificat în base64.
Semnătură — când avem antetul și payload-ul, putem calcula semnătura.
Se iau antetul și payload-ul, codificate în base64, și se combină într-un șir printr-un punct. Apoi, acest șir și cheia secretă sunt introduse în algoritmul de criptare specificat în antet (cheia „alg”). Cheia poate fi orice șir. Șirurile mai lungi sunt preferate, deoarece necesită mai mult timp pentru a fi descifrate.
{"alg":"RSA1_5","payload":"A128CBC-HS256"}
Construirea arhitecturii de cluster Keycloak rezistent la erori
Atunci când se utilizează un singur cluster pentru toate proiectele, cerințele pentru soluția SSO cresc. Atunci când numărul de proiecte este mic, aceste cerințe nu sunt atât de percepute de toate proiectele, însă, pe măsură ce numărul utilizatorilor și integrațiilor crește, cerințele pentru disponibilitate și performanță cresc.
Creșterea riscurilor de eșec al SSO-ului unic ridică cerințele pentru arhitectura soluției și metodele de rezervare a componentelor utilizate, conducând la un SLA foarte strict. În acest context, deseori, în fazele de dezvoltare sau implementare timpurie a soluțiilor, proiectele dispun de o infrastructură care nu este toleranta la erori. Pe măsură ce se dezvoltă, este necesar să se prevadă posibilitățile de dezvoltare și scalare. Cel mai flexibil mod de a construi un cluster tolerant la erori este utilizarea virtualizării în containere sau a unei abordări hibride.
Pentru a funcționa în modul Active/Active și Active/Passive, clusterul trebuie să asigure consistența datelor în baza de date relațională — ambele noduri ale bazei de date trebuie să fie replicări sincronizate între diferitele centre de date geografice.
Cel mai simplu exemplu de instalare tolerantă la erori.

Ce avantaje oferă utilizarea unui cluster unic:
- Disponibilitate și performanță ridicate.
- Suport pentru moduri de operare: Active/Active, Active/Passive.
- Capacitatea de scalare dinamică — prin utilizarea virtualizării în containere.
- Posibilitatea de gestionare și monitorizare centralizată.
- O abordare unică pentru identificarea/autentificarea/autorizarea utilizatorilor în proiecte.
- Interacțiune mai transparentă între diferitele proiecte fără implicarea utilizatorilor.
- Posibilitatea reutilizării tokenului JWT în diverse proiecte.
- Un singur punct de încredere.
- Lansare mai rapidă a proiectelor folosind microservicii/virtualizare în containere (fără a fi necesară ridicarea și configurarea de componente suplimentare).
- Posibilitate de achiziție a suportului comercial de la furnizor.
Ce merită luat în considerare atunci când se planifică un cluster
Baza de date relațională
Keycloak folosește un sistem de gestionare a bazelor de date pentru a păstra: realm-uri, clienți, utilizatori etc.
Se suportă o gamă largă de baze de date: MS SQL, Oracle, MySQL, PostgreSQL. Keycloak vine cu propria bază de date relațională încorporată. Este recomandat pentru medii nesolicitate - cum ar fi mediile de dezvoltare.
Pentru a funcționa în modul Active/Active și Active/Passive, clusterul trebuie să asigure consistența datelor în baza de date relațională, iar ambele noduri ale clusterului de baze de date sunt replicări sincronizate între centrele de date.
Cache distribuit (Infinspan)
Pentru funcționarea corectă a clusterului, este necesară sincronizarea suplimentară a următoarelor tipuri de cache, utilizând JBoss Data Grid:
Sesiuni de autentificare — utilizate pentru a salva datele în timpul autentificării unui utilizator specific. Cererile din acest cache includ de obicei doar browserul și serverul Keycloak, nu și aplicația.
Token-uri de acțiune — folosite pentru scenarii în care utilizatorul trebuie să confirme o acțiune asincron (prin email). De exemplu, în timpul fluxului de recuperare a parolei, cache-ul actionTokens Infinispan este folosit pentru a urmări metadatele legate de token-urile de acțiune deja utilizate, astfel încât acestea să nu poată fi reutilizate.
Cache și invalidarea datelor persistente – utilizat pentru a cache-ui datele permanente, pentru a evita solicitările inutile către baza de date. Când un server Keycloak actualizează datele, toate celelalte servere Keycloak din toate centrele de date trebuie să fie la curent.
Work — utilizat doar pentru a trimite mesaje de invalidare între nodurile clusterului și centrele de date.
Sesiuni de utilizator — utilizate pentru a păstra date despre sesiunile utilizatorilor, care sunt valabile pe durata sesiunii browser-ului utilizatorului. Cache-ul trebuie să gestioneze cererile HTTP de la utilizatorul final și de la aplicație.
Protecția împotriva atacurilor brute — utilizată pentru a urmări datele despre încercările eșuate de autentificare.
Încărcarea echilibrată
Load balancer-ul este un singur punct de intrare în keycloak și trebuie să suporte sesiuni sticky.
Servere de aplicații
Sunt utilizate pentru a controla interacțiunea componentelor între ele și pot fi virtualizate sau containerizate utilizând instrumentele de automatizare disponibile și scalarea dinamică a infrastructurii. Cele mai frecvente scenarii de implementare sunt în OpenShift, Kubernetes, Rancher.
Aceasta a fost prima parte – partea teoretică – finalizată. În următoarele serii de articole vor fi discutate exemple de integrare cu diferiți furnizori de identitate și exemple de configurări.
Sursa: habr.com
