In ogni grande azienda, e X5 Retail Group non fa eccezione, con lo sviluppo aumenta il numero di progetti dove è richiesta l'autenticazione degli utenti. Con il passare del tempo, diventa necessario un passaggio senza soluzione di continuità per gli utenti da un'applicazione all'altra e quindi si presenta la necessità di utilizzare un server unico di Single-Sign-On (SSO). Ma come fare quando provider di identificazione come AD o altri, che non possiedono attributi aggiuntivi, sono già utilizzati in vari progetti. A soccorrerci arriva una classe di sistemi chiamata

Keycloak è un prodotto open source, progettato per l'autenticazione e il controllo degli accessi, supportato da RedHat. È alla base dei prodotti della società che utilizzano SSO – RH-SSO.
Concetti di base
Prima di iniziare a comprendere le soluzioni e gli approcci, è necessario chiarire i termini e la sequenza dei processi:

Identificazione — è la procedura di riconoscimento di un soggetto tramite il suo identificatore (in altre parole, è la determinazione del nome, login o numero).
Autenticazione – è la procedura di autenticazione (l'utente viene verificato tramite password, la lettera viene verificata tramite firma elettronica, ecc.).
Autenticazione – è la fornitura di accesso a una risorsa (ad esempio, alla posta elettronica).
Broker di identità Keycloak
Keycloak — è una soluzione per la gestione dell'identità e degli accessi open source, progettata per essere utilizzata in sistemi informativi dove possono essere utilizzati schemi di architettura a microservizi.
Keycloak offre funzionalità come il single sign-on (SSO), l'identificazione broker e l'accesso sociale, la federazione degli utenti, adattatori del client, console di amministrazione e console di gestione degli account.
Le funzionalità di base supportate in Keycloak:
- Single-Sign On e Single-Sign Out per applicazioni basate su browser.
- Supporto per OpenID/OAuth 2.0/SAML.
- Identity Brokering – autenticazione tramite provider di identità esterni OpenID Connect o SAML.
- Social Login – supporto per Google, GitHub, Facebook, Twitter per l'identificazione degli utenti.
- User Federation – sincronizzazione degli utenti da server LDAP e Active Directory e altri provider di identità.
- Kerberos bridge – uso del server Kerberos per l'autenticazione automatica degli utenti.
- Admin Console — per la gestione unificata delle impostazioni e delle configurazioni della soluzione tramite il Web.
- Account Management Console – per la gestione autonoma del profilo degli utenti.
- Personalizzazione della soluzione in base allo stile aziendale.
- 2FA Authentication – supporto per TOTP/HOTP tramite Google Authenticator o FreeOTP.
- Login Flows – è possibile la registrazione autonoma degli utenti, il recupero e il ripristino della password e altro ancora.
- Session Management – gli amministratori possono gestire le sessioni degli utenti da un'unica posizione.
- Token Mappers – associazione degli attributi degli utenti, dei ruoli e di altri attributi richiesti nei token.
- Gestione flessibile delle politiche tramite realm, applicazioni e utenti.
- CORS Support – gli adattatori client hanno supporto CORS integrato.
- Service Provider Interfaces (SPI) – un gran numero di SPI che consentono di configurare vari aspetti del funzionamento del server: flussi di autenticazione, provider di identità, mappatura dei protocolli e molto altro.
- Adattatori client per applicazioni JavaScript, WildFly, JBoss EAP, Fuse, Tomcat, Jetty, Spring.
- Supporto per vari applicativi che utilizzano OpenID Connect Relying Party library o SAML 2.0 Service Provider Library.
- Possibilità di estensione tramite plugin.
Per i processi CI/CD, così come per l'automazione dei processi di gestione in Keycloak, è possibile utilizzare REST API/JAVA API. La documentazione è disponibile in formato elettronico:
REST API
JAVA API
Provider di identità di livello aziendale (On-Premise)
Possibilità di autenticazione degli utenti tramite servizi di User Federation.

È possibile utilizzare anche l'autenticazione trasversale: se gli utenti si autenticano su postazioni di lavoro con Kerberos (LDAP o AD), possono essere autenticati automaticamente su Keycloak senza la necessità di fornire nuovamente nome utente e password.
Per l'autenticazione e la successiva autorizzazione degli utenti, è possibile utilizzare un database relazionale, il che è particolarmente utile per gli ambienti di sviluppo, in quanto non comporta lunghe configurazioni e integrazioni nelle fasi iniziali dei progetti. Per impostazione predefinita, Keycloak utilizza un database integrato per memorizzare le impostazioni e i dati sugli utenti.
L'elenco dei database supportati è ampio e include: MS SQL, Oracle, PostgreSQL, MariaDB, Oracle e altri. Attualmente, i più testati sono Oracle 12C Release1 RAC e Galera 3.12 cluster per MariaDB 10.1.19.
Provider di identità — accesso tramite social
È possibile utilizzare le credenziali dei social media. Per attivare la possibilità di autenticare gli utenti, si utilizza la console di amministrazione di Keycloak. Non sono necessarie modifiche al codice delle applicazioni e questa funzionalità è disponibile 'out of the box' e può essere attivata in qualsiasi fase di implementazione del progetto.

Per l'autenticazione degli utenti è possibile utilizzare provider di identità OpenID/SAML.
Scenari tipici di autorizzazione usando OAuth2 in Keycloak
Authorization Code Flow — utilizzato con applicazioni server-side. È uno dei tipi più comuni di autorizzazione, poiché è ben adatto per applicazioni server dove il codice sorgente dell'applicazione e i dati del client non sono accessibili da terzi. In questo caso, il processo si basa sulla redirezione. L'applicazione deve essere in grado di interagire con l'agent utente, come un browser web, per ricevere i codici di autorizzazione API reindirizzati attraverso l'agent utente.
Implicit Flow — utilizzato da applicazioni mobili o web (applicazioni che funzionano sul dispositivo dell'utente).
Il tipo implicito di autorizzazione è utilizzato da applicazioni mobili e web, dove la riservatezza del cliente non può essere garantita. Il tipo implicito di autorizzazione utilizza anche il reindirizzamento dell'agente utente, con il token di accesso che viene passato all'agente utente per ulteriori utilizzi nell'applicazione. Questo rende il token disponibile per l'utente e per altre applicazioni sul dispositivo dell'utente. Con questo tipo di autorizzazione non viene eseguita l'autenticazione dell'applicazione, e l'intero processo si basa sull'URL di reindirizzamento (registrato in precedenza nel servizio).
Il Flusso Implicito non supporta i token di aggiornamento del token di accesso (refresh tokens).
Flusso di concessione delle credenziali del client — utilizzato quando un'applicazione accede a un'API. Questo tipo di autorizzazione è generalmente impiegato per interazioni "server-server", che devono essere eseguite in background senza un'interazione immediata con l'utente. Il flusso di concessione delle credenziali del client consente a un servizio web (client riservato) di utilizzare le proprie credenziali invece della rappresentazione dell'utente per l'autenticazione quando chiama un altro servizio web. Per un livello di sicurezza maggiore, è possibile che il servizio chiamante utilizzi un certificato (invece di un segreto condiviso) come credenziali.
La specifica OAuth2 è descritta in
Token JWT e i suoi vantaggi
JWT (JSON Web Token) è uno standard aperto (), che definisce un modo compatto e autonomo per la trasmissione sicura di informazioni tra le parti sotto forma di oggetto JSON.
Secondo lo standard, il token è composto da tre parti in formato base-64, separate da punti. La prima parte è chiamata intestazione (header), dove sono contenuti il tipo di token e il nome dell'algoritmo di hash per generare la firma digitale. La seconda parte contiene le informazioni principali (utente, attributi, ecc.). La terza parte è la firma digitale.
..
Non memorizzare mai il token nel tuo database. Perché un token valido è equivalente a una password, memorizzare un token è come memorizzare una password in chiaro.
Token di accesso — è un token che fornisce al suo proprietario l'accesso a risorse protette del server. Di solito ha una vita breve e può contenere informazioni aggiuntive, come l'indirizzo IP della parte che richiede questo token.
Refresh-token — è un token che permette ai client di richiedere nuovi access-token al termine della loro vita utile. Questi token vengono generalmente emessi per un lungo periodo.
I principali vantaggi dell'uso nell'architettura a microservizi:
- Possibilità di accesso a diverse applicazioni e servizi attraverso un'unica autenticazione.
- In assenza di alcuni attributi richiesti nel profilo utenti, è possibile arricchirlo con dati che possono essere aggiunti al payload, anche in modo automatizzato e 'al volo'.
- Non è necessario memorizzare informazioni sulle sessioni attive, l'applicazione server deve solo controllare la firma.
- Gestione dell'accesso più flessibile grazie ad attributi aggiuntivi nel payload.
- L'uso della firma del token per l'intestazione e il payload aumenta la sicurezza della soluzione nel suo complesso.
JWT token — composizione
Titolo — per impostazione predefinita, l'intestazione contiene solo il tipo di token e l'algoritmo utilizzato per la crittografia.
Il tipo di token è memorizzato nella chiave 'typ'. La chiave 'typ' è ignorata nel JWT. Se la chiave 'typ' è presente, il suo valore deve essere JWT, per indicare che questo oggetto è un JSON Web Token.
La seconda chiave 'alg' determina l'algoritmo utilizzato per crittografare il token. Per impostazione predefinita, deve essere impostato su HS256. L'intestazione è codificata in base64.
{ "alg": "HS256", "typ": "JWT"}
Payload (contenuto) — nel payload è memorizzata qualsiasi informazione che deve essere verificata. Ogni chiave nel payload è nota come 'dichiarazione'. Ad esempio, è possibile accedere all'applicazione solo tramite invito (promozione chiusa). Quando vogliamo invitare qualcuno a partecipare, inviamo un'email con l'invito. È importante verificare che l'indirizzo email appartenga alla persona che riceve l'invito, quindi includeremo questo indirizzo nel payload, conservandolo nella chiave 'e-mail'
{ "email": "example@x5.ru" }
Le chiavi nel payload possono essere arbitrarie. Tuttavia, ce ne sono alcune riservate:
- iss (Issuer) — definisce l'applicazione da cui viene inviato il token.
- sub (Soggetto) — definisce il tema del token.
- aud (Pubblico) – un array di stringhe sensibili al maiuscolo o URI, che costituisce un elenco dei destinatari di questo token. Quando il destinatario riceve il JWT con questa chiave, deve verificare di essere presente nell'elenco dei destinatari; in caso contrario, deve ignorare il token.
- exp (Tempo di scadenza) — indica quando scade la validità del token. Lo standard JWT richiede che in tutte le sue implementazioni i token scaduti vengano rifiutati. La chiave exp deve essere un timestamp in formato unix.
- nbf (Non prima di) — è un'ora in formato unix che definisce il momento in cui il token diventa valido.
- iat (Data di emissione) — questa chiave rappresenta il momento in cui il token è stato emesso e può essere utilizzata per determinare l'età del JWT. La chiave iat deve essere un timestamp in formato unix.
- Jti (ID JWT) — una stringa che definisce un identificatore unico per questo token, considerando il maiuscolo.
È importante comprendere che il payload non viene trasmesso in forma crittografata (anche se i token possono essere annidati e quindi è possibile trasmettere dati crittografati). Pertanto, non si possono memorizzare informazioni segrete al suo interno. Come l'intestazione, il payload è codificato in base64.
Firma — quando abbiamo l'intestazione e il payload, è possibile calcolare la firma.
Si prendono i codificati in base64: l'intestazione e il payload, si uniscono in una stringa tramite un punto. Quindi, questa stringa e la chiave segreta vengono inserite nell'algoritmo di crittografia specificato nell'intestazione (chiave “alg”). La chiave può essere qualsiasi stringa. Stringhe più lunghe saranno preferibili, poiché ci vorrà più tempo per il brute forcing.
{"alg":"RSA1_5", "payload":"A128CBC-HS256"}
Costruzione di un'architettura di cluster Keycloak ad alta disponibilità
Quando si utilizza un unico cluster per tutti i progetti, si verificano requisiti più elevati per la soluzione SSO. Quando il numero di progetti è limitato, questi requisiti non sono così evidenti per ogni progetto, tuttavia, con l'aumento del numero di utenti e integrazioni, aumentano le esigenze di disponibilità e prestazioni.
L'aumento dei rischi di fallimento del SSO unificato aumenta i requisiti per l'architettura della soluzione e i metodi di ridondanza dei componenti, portando a un SLA molto rigido. Di conseguenza, durante lo sviluppo o nelle fasi iniziali di implementazione delle soluzioni, i progetti presentano spesso un'infrastruttura non resiliente. Con l'evoluzione, è necessario prevedere opportunità di sviluppo e scalabilità. È più flessibile costruire un cluster resiliente utilizzando la virtualizzazione a container o un approccio ibrido.
Per operare in modalità Active/Active e Active/Passive di un cluster, è necessario garantire la coerenza dei dati nel database relazionale: entrambi i nodi del database devono essere replicati in modo sincrono tra i diversi data center distribuiti geograficamente.
Il più semplice esempio di un'installazione resiliente.

Quali vantaggi offre l'utilizzo di un cluster unificato:
- Alta disponibilità e prestazioni.
- Supporto per modalità operative: Active/Active, Active/Passive.
- Possibilità di scalabilità dinamica — in utilizzo con la virtualizzazione a container.
- Possibilità di gestione e monitoraggio centralizzati.
- Un approccio unificato per l'identificazione/autenticazione/autorizzazione degli utenti nei progetti.
- Interazione più trasparente tra diversi progetti senza il coinvolgimento degli utenti.
- Possibilità di riutilizzare il token JWT in diversi progetti.
- Unico punto di fiducia.
- Avvio più rapido dei progetti utilizzando microservizi/virtualizzazione a container (non è necessaria l'installazione e configurazione di componenti aggiuntivi).
- È possibile acquisire supporto commerciale dal fornitore.
Cosa considerare nella pianificazione del cluster
DBMS
Keycloak utilizza un sistema di gestione del DBMS per memorizzare: realms, clients, users, ecc.
È supportata una vasta gamma di DBMS: MS SQL, Oracle, MySQL, PostgreSQL. Keycloak viene fornito con un proprio database relazionale integrato. Si raccomanda l'uso per ambienti a bassa carico - come gli ambienti di sviluppo.
Per operare in modalità Active/Active e Active/Passive di un cluster, è necessario garantire la coerenza dei dati nel database relazionale e entrambi i nodi del cluster del database vengono replicati in sincrono tra i data center.
Cache distribuita (Infinispan)
Per il corretto funzionamento del cluster è necessaria una sincronizzazione aggiuntiva dei seguenti tipi di cache utilizzando JBoss Data Grid:
Sessioni di autenticazione — utilizzate per memorizzare i dati durante l'autenticazione di un utente specifico. Le richieste provenienti da questa cache di solito includono solo il browser e il server Keycloak, e non l'applicazione.
Action tokens — utilizzati per situazioni in cui l'utente deve confermare un'azione in modo asincrono (via email). Ad esempio, durante il flusso di recupero password, la cache actionTokens Infinispan viene utilizzata per monitorare i metadati sui token delle azioni correlate che sono già stati utilizzati e quindi non possono essere riutilizzati.
Caching e invalidazione di dati persistenti – utilizzato per memorizzare nella cache dati persistenti, al fine di evitare richieste eccessive al database. Quando un server Keycloak aggiorna i dati, tutti gli altri server Keycloak in tutti i data center devono esserne a conoscenza.
Work — utilizzato solo per inviare messaggi di invalidazione tra i nodi del cluster e i data center.
Sessioni utente — utilizzate per memorizzare i dati sulle sessioni utente, validi durante la sessione del browser dell'utente. La cache deve gestire le richieste HTTP dall'utente finale e dall'applicazione.
Protezione contro attacchi brute force — utilizzata per monitorare i dati sui tentativi di accesso non riusciti.
Il bilanciamento del carico
L'equilibratore di carico è un unico punto di accesso a Keycloak e deve supportare le sessioni sticky.
Server delle applicazioni
Utilizzati per controllare l'interazione tra i componenti e possono essere virtualizzati o containerizzati utilizzando strumenti di automazione e di scaling dinamico dell'infrastruttura esistenti. Gli scenari di distribuzione più comuni sono su OpenShift, Kubernates, Rancher.
Questo conclude la prima parte — teorica. Nei prossimi cicli di articoli verranno esaminati esempi di integrazioni con vari fornitori di identità e esempi di configurazioni.
Fonte: habr.com
