La guida completa all'integrazione di un server OIDC nel tuo progetto
Impara le migliori pratiche per integrare un server OIDC (OpenID Connect) nel tuo progetto e comprendi come i componenti interagiscono tra loro sul palco.
Potresti incontrare una situazione in cui hai bisogno di un sistema centralizzato di autenticazione e autorizzazione, noto anche come gestione degli accessi identitari (IAM) o fornitore di identità (IdP). A volte le persone aggiungono una parola per designare il business, come IAM del Cliente e IAM della Forza Lavoro.
Mettiamo da parte per un attimo questi nomi altisonanti. La necessità di IAM potrebbe sorgere perché la tua applicazione sta crescendo o perché hai intenzione di delegare il lavoro difficile a un fornitore fin dall'inizio. Tuttavia, stai raggiungendo un punto in cui un sistema di identità dovrà essere introdotto nel tuo progetto.
Considerando la popolarità di OAuth 2.0, OpenID Connect (OIDC) è una scelta naturale per molti sviluppatori. Poiché OIDC è uno strato di autenticazione costruito sopra OAuth 2.0, potresti sentirti familiare quando inizi a lavorare con OIDC. Cominciamo!
Cos'è un server OIDC e perché dovrei integrarlo?
Un server OIDC, o fornitore di identità, è un sistema centralizzato che gestisce l'autenticazione e l'autorizzazione degli utenti. Come discusso in Perché hai bisogno di un sistema di identità centralizzato per un business multi-app, un sistema di identità centralizzato ha molti vantaggi.
Supponiamo che il tuo progetto inizi con una semplice applicazione web e che abbia l'autenticazione integrata:
Man mano che il tuo progetto cresce, hai bisogno di introdurre una versione mobile:
Sarà una pessima esperienza per gli utenti se devono creare un account per ogni applicazione. Poiché hai iniziato con un'applicazione web, lasci che l'applicazione mobile comunichi con l'applicazione web per l'autenticazione:
Ora, viene introdotto un nuovo servizio API. Poiché è un servizio per utenti paganti, devi assicurarti che l'utente sia autenticato e autorizzato ad accedere al servizio. Per ottenere ciò, puoi prosi attraverso il servizio tramite l'applicazione web:
Oppure, utilizza alcune tecniche token per autenticare l'utente e valida il token parlando con l'applicazione web nel servizio. Pertanto, l'applicazione mobile può utilizzare il servizio direttamente:
Le cose stanno diventando complicate. Decidi quindi di dividere la logica di autenticazione e autorizzazione in un servizio separato:
Il processo di refactoring può essere doloroso. Potresti notare che la complessità aumenterà esponenzialmente man mano che aggiungerai più applicazioni e servizi al progetto. Ancora peggio, potresti dover mantenere più metodi di autenticazione come accesso senza password, accesso social, SAML, ecc.
Questo è il motivo per cui è meglio introdurre un fornitore di identità all'inizio quando hai un piano per scalare il tuo progetto.
Migliori pratiche per integrare un server OIDC
Trova un fornitore OIDC
Ci sono molti fornitori OIDC disponibili sul mercato. Puoi sceglierne uno in base ai tuoi requisiti e preferenze. Finché il fornitore è conforme a OIDC, avrà lo stesso ruolo nel tuo progetto.
Cosa significano "soggetto", "cliente" e "audience" in OIDC?
Per semplificare il concetto, possiamo pensare che il soggetto sia l'entità che richiede l'accesso a una audience tramite un cliente.
Vediamo alcuni scenari tipici:
1. Un utente clicca sul pulsante di accesso in un'applicazione web
In un'applicazione web tradizionale e server-side rendering, la frontend e il backend sono accoppiati. Supponiamo che l'applicazione web serva entrambi:
- Soggetto: L'utente
- Audience: Il server OIDC
- Cliente: L'applicazione web
Potrebbe sembrare controintuitivo che l'audience sia il server OIDC. In realtà, è la chiave per realizzare l'esperienza SSO (Single Sign-On) per gli utenti finali. Vediamo un diagramma di sequenza semplificato per il flusso del codice di autorizzazione:
code
è un codice unico che può essere scambiato con vari token, come token di accesso, token ID e token di aggiornamento. Va bene se non comprendi tutti questi token in questo momento. Man mano che andiamo avanti, avrai una comprensione migliore di essi.
Nel caso precedente, l'utente non ha bisogno di accedere nuovamente quando passa a un'altra applicazione perché l'utente (soggetto) è già autenticato con il server OIDC (audience).
2. Un utente utilizza un'applicazione a pagina singola
In un'applicazione a pagina singola (o un'applicazione mobile), la frontend e il backend sono separati. Supponiamo che il backend sia un servizio API:
- Soggetto: L'utente
- Audience: Il servizio API
- Cliente: L'applicazione a pagina singola (SPA)
Un diagramma di sequenza semplificato con il flusso del codice di autorizzazione:
Poiché il servizio API è non interattivo, la SPA deve utilizzare il token di accesso con il servizio API come audience (l'aud
nel token).
Perché il server OIDC è ancora un'audience?
Tecnicamente, puoi rimuovere il server OIDC dalla lista delle audience. Poiché nella maggior parte dei casi avrai bisogno delle informazioni utente dal server OIDC (che richiede che il server OIDC sia l'audience), è meglio includere sempre il server OIDC nella lista delle audience quando coinvolge l'interazione con l'utente.
Aspetta, stai dicendo che possiamo avere più audience in una richiesta di autorizzazione?
Esattamente! Ricorda che OIDC è costruito sopra OAuth 2.0, è possibile sfruttare RFC 8707: Indicazioni di Risorsa per OAuth 2.0 nella richiesta di autorizzazione per specificare più audience. Richiede il supporto sia dalla concessione che dal server OIDC. Logto supporta nativamente questa funzionalità.
3. Una comunicazione macchina-a-macchina
Supponiamo che tu abbia un servizio A che deve chiamare il servizio B:
- Soggetto: Servizio A
- Audience: Servizio B
- Cliente: Servizio A
Un diagramma di sequenza semplificato con concessione delle credenziali del client:
Quando il servizio B deve chiamare il servizio A, i ruoli vengono semplicemente scambiati.
Ricapitolare
- Soggetto: Può essere un utente, un servizio o qualsiasi entità che ha bisogno di accedere all'audience.
- Cliente: Può essere un'applicazione web, un'applicazione mobile o qualsiasi entità che avvia la richiesta o agisce per conto del soggetto.
- Audience: Può essere un servizio, un'API o qualsiasi entità che fornisce accesso al soggetto.
Cosa sono i token di accesso, i token ID e i token di aggiornamento?
Ci sono tre tipi di token che potresti incontrare lavorando con OIDC:
- Token di accesso: Viene utilizzato per accedere all'audience. Può essere un JWT (JSON Web Token) o un token opaco (solitamente una stringa casuale).
- Token ID: Un token specifico di OIDC che contiene informazioni sull'utente. È sempre un JWT. Il cliente può decodificare il token per ottenere informazioni sull'utente.
- Token di aggiornamento: Viene utilizzato per ottenere un nuovo set di token quando il token di accesso o il token ID scade.
Per una spiegazione dettagliata di questi token, puoi fare riferimento a Comprendere i token di aggiornamento, i token di accesso e i token ID nel protocollo OIDC.
Negli scenari sopra 1 e 2, il termine richiesta di autorizzazione si riferisce a una richiesta per ottenere un set di token tramite una concessione specifica grant.
Quando tutto va bene, un set di token verrà restituito nel passaggio "Scambia token usando code
". I token disponibili nel set dipendono da molti fattori, soprattutto dal parametro scope
nella richiesta di autorizzazione. Per semplicità, supponiamo che tutti i token vengano restituiti nel set. Una volta che il token di accesso scade, il cliente può utilizzare il token di aggiornamento per ottenere un nuovo set di token senza interazione dell'utente.
Per lo scenario 3, è più semplice perché la concessione delle credenziali del cliente restituisce solo un token di accesso.
Come gestire più audience in OIDC?
Potresti notare che viene restituito solo un token di accesso alla volta. Come potremmo gestire il caso in cui il cliente deve accedere a più audience?
Ci sono due soluzioni comuni:
Specifica resource
nella richiesta di scambio del codice
Quando il cliente scambia il codice per i token, può specificare un parametro resource
nella richiesta. Il server OIDC restituirà un token di accesso per l'audience specificata se applicabile.
Ecco un esempio non normativo:
Quindi il server OIDC restituirà un token di accesso per l'audience API_SERVICE
, se applicabile.
Usa un token di aggiornamento per ottenere un nuovo token di accesso
Con RFC 8707, il cliente può anche specificare più audience utilizzando il parametro resource
più volte. Ora, se i token di aggiornamento sono disponibili nel cliente, il cliente può specificare l'audience nel parametro resource
durante l'aggiornamento del token.
Ecco un esempio non normativo:
Ha lo stesso effetto della soluzione precedente. Nel frattempo, altre audience concesse sono ancora disponibili nelle future richieste di token.
Concessione delle credenziali del client
Puoi anche usare il parametro resource
nella concessione delle credenziali del cliente per specificare l'audience. Non c'è problema con multiple audience in questa concessione perché puoi sempre richiedere un nuovo token di accesso per un'audience diversa semplicemente inviando un'altra richiesta di token.
Proteggi il tuo servizio API
Il "servizio API" nello scenario 2 e il "Servizio B" nello scenario 3 hanno una cosa in comune: devono convalidare il token di accesso per determinare se la richiesta è autorizzata. A seconda del formato del token di accesso, il processo di convalida pu ò variare.
- Token opaco: Il servizio API deve chiamare il server OIDC per convalidare il token. Un endpoint di introspezione è solitamente fornito dal server OIDC per questo scopo.
- JWT: Il servizio API può convalidare il token localmente controllando la firma e le affermazioni nel token. Il server OIDC solitamente fornisce un JSON Web Key Set (JWKS) endpoint (
jwks_uri
) per il servizio API per ottenere la chiave pubblica per verificare la firma.
Se sei nuovo a JWT, puoi fare riferimento a Cos'è il JSON Web Token (JWT)?. In effetti, di solito non c'è bisogno di convalidare manualmente la firma e affermare le affermazioni perché ci sono molte librerie che possono farlo per te, come jose per Node.js e browser web.
Affermare le affermazioni
Inoltre, per convalidare la firma JWT, il servizio API dovrebbe sempre controllare le affermazioni nel token:
iss
: L'emittente del token. Dovrebbe corrispondere all'URL dell'emittente del server OIDC.aud
: L'audience del token. Dovrebbe corrispondere al valore dell'audience del servizio API (solitamente un URI valido).exp
: Il tempo di scadenza del token. Il servizio API dovrebbe rifiutare il token se è scaduto.scope
: Gli ambiti (autorizzazioni) del token. Il servizio API dovrebbe controllare se l'ambito richiesto è presente nel token.
Altre affermazioni, come sub
(soggetto) e iat
(emesso a), sono anche importanti in alcuni casi. Se hai misure di sicurezza aggiuntive, controlla le affermazioni di conseguenza.
Autorizzazione
Rimane una domanda senza risposta: come determiniamo se un ambito (cioè un'autorizzazione) può essere concesso a un soggetto?
La singola domanda porta a un intero nuovo mondo di autorizzazione, che è al di fuori dello scopo di questo articolo. In breve, ci sono alcuni approcci comuni come RBAC (Controllo di Accesso Basato sui Ruoli) e ABAC (Controllo di Accesso Basato sugli Attributi). Ecco alcune risorse per iniziare:
- RBAC e ABAC: i modelli di controllo accessi che dovresti conoscere
- Padroneggiare RBAC in Logto: Un esempio comprensivo nel mondo reale
Note finali
Introdurre un server OIDC nel tuo progetto è un grande passo. Può migliorare significativamente la sicurezza e la scalabilità del tuo progetto. Nel frattempo, potrebbe richiedere del tempo per comprendere i concetti e le interazioni tra i componenti.
Scegliere un buon fornitore OIDC che si adatti ai tuoi requisiti e preferenze può ridurre notevolmente la complessità del processo di integrazione, poiché il fornitore di solito offre l'intero pacchetto, compreso il server OIDC, i meccanismi di autorizzazione, gli SDK e le funzionalità aziendali necessarie in futuro.
Spero che questa guida ti aiuti a comprendere le basi dell'integrazione di un server OIDC. Se stai cercando uno con cui iniziare, consiglierei egoisticamente Logto, la nostra infrastruttura identitaria per sviluppatori.