OpenID Connect (OIDC) è un livello di identità che si appoggia al protocollo OAuth 2.0 e permette alle applicazioni di autenticare gli utenti senza doverne gestire e archiviare le credenziali. AWS Application Load Balancer (ALB) si integra con i principali identity provider (IdP) social, con le identità aziendali e con qualsiasi IdP conforme a OIDC. Questa integrazione semplifica l'autenticazione e ne rafforza la sicurezza, delegando la gestione delle sessioni utente e dei token a un provider terzo affidabile.
Per l'utente finale l'accesso è trasparente, ma quando l'autenticazione si interrompe individuare la causa può diventare complicato a causa degli hop aggiuntivi tra l'utente e l'applicazione che sta cercando di raggiungere.
Questo articolo si propone di dare visibilità su come si presentano le transazioni HTTP, da diverse prospettive, durante il flusso authorization code.
Per chi volesse approfondire la configurazione dell'autenticazione utente sul proprio ALB, consigliamo la documentazione ufficiale di AWS. AWS mette inoltre a disposizione un sito demo per testare la funzionalità di autenticazione.
**Analizziamo passo dopo passo il flusso di autenticazione —**

Il logging è fondamentale per preservare integrità, sicurezza ed efficienza delle applicazioni in cloud. Fornisce le informazioni necessarie per monitorare e risolvere eventuali problemi, garantendo che le applicazioni funzionino in modo regolare e sicuro.
Per analizzare a fondo il flusso di autenticazione ho raccolto i seguenti log:
- File HAR del browser dell'utente.
- Access log degli endpoint dell'IdP (Auth, Token, User-Info), dell'ALB e dell'applicazione di destinazione.
Prima di esaminare le transazioni HTTP, suggerisco di prendere familiarità con i diversi componenti OIDC e con il loro ruolo.
Prerequisiti —
- L'IdP è configurato per eseguire il flusso Authorization code grant con gli scope previsti. Sono stati inoltre generati Client ID e client secret.
- L'ALB è configurato con una regola di listener che attiva l'azione "authenticate" quando il path HTTP è
/auth*. Vanno definiti i parametri della richiesta di autenticazione: client ID, client secret, authorization endpoint, token endpoint e user info endpoint. Sono questi i parametri che l'ALB utilizza per dialogare con l'IdP.
Passaggio 1 — L'utente invia una richiesta HTTP all'applicazione protetta da un ALB con autenticazione abilitata.

Il browser viene reindirizzato all'Auth endpoint dell'IdP.
Access log dell'ALB per la stessa transazione —
h2 2024–07–11T18:47:52.382721Z app/demo/25be909a3f190764 109.78.96.82:54871 - -1 -1 -1 302–359 657 "GET https://demo.aws.doit.com:443/auth.html HTTP/2.0" arn:aws:elasticloadbalancing:eu-west-1:21112316:targetgroup/TG/1a24c5faad770fb2 "Root=1–669028d8–653487fd74af592f498329f8" "authenticate"
- L'azione di autenticazione si attiva quando l'utente invia una richiesta HTTP GET all'ALB.
- Se negli header della richiesta HTTP non è presente alcun cookie di sessione di autenticazione, l'ALB genera una risposta HTTP 302 e l'utente viene reindirizzato all'URL indicato nel location header (l'authorization endpoint dell'IdP).
- Il
redirect_uriè l'indirizzo a cui il browser viene reindirizzato dopo che l'IdP ha concesso l'authorization code.
Passaggio 2 — L'utente viene reindirizzato all'authorization endpoint dell'IdP.

Richiesta HTTP all'auth endpoint.
- L'utente invia una richiesta HTTP all'authorization endpoint dell'IdP.
- L'authorization endpoint reindirizza poi l'utente al login endpoint dell'IdP (
/login). - Il login endpoint si occupa dell'autenticazione dell'utente.
Passaggio 3 — L'utente raggiunge il login endpoint.

Richiesta HTTP al login endpoint.
- L'utente invia una richiesta HTTP al login endpoint.
- Viene caricata la pagina di login con i campi username e password.
Passaggio 4 — L'utente si autentica.

L'utente inserisce username e password.
- L'utente inserisce le proprie credenziali nella pagina di login dell'IdP.
- Una volta autenticato con successo, viene reindirizzato all'authorization endpoint dell'IdP.
Esempio di payload di una richiesta POST —
csrf=izvsVKMB-GxnSvAK6McnPw6uNcZVCqqWxjeU&challenge=cbcab3062ca041399178171a4078d30b&email=user%40name.com&password=complex&submit=Log+in
Passaggio 5 — L'utente riceve l'authorization code dall'IdP.

Auth code concesso.
- L'authorization endpoint dell'IdP reindirizza l'utente all'applicazione client con un authorization code.
- I valori originali del parametro
statevengono preservati per mantenere una corrispondenza 1:1 tra richiesta e callback.
Passaggio 6 — L'utente torna all'ALB con l'authorization code.

L'utente viene reindirizzato a /auth con il cookie di autenticazione.
Access log dell'ALB per la stessa transazione —
h2 2024-07-11T18:48:27.805659Z app/demo/25be909a3f190764 109.78.96.82:54871 - -1 -1 -1 302 - 423 847 "GET https://demo.aws.doit.com:443/oauth2/idpresponse?code=ory_ac_9j6SCghDyFOexN03pTRP_GSJ5RHduhCLE-L74D2IlSs.zMsOhvXLbIrs0WQLtb43tkUnRZm0lWoI5T0IlNjnoO0&scope=openid&state=Y06EN0RLaODTpBbHGEpfK29AZJcLIpftyWwbyQN8EeiFyOtbN07H2nTXTGUa3DDYX5UgeMDsqP9psViZhPy41Y%2FVkNoJc5%2B6jb8po%2BLXQtcgxRgk9s5T0LgWt53mOEOjxL4nBVQ9Z9X1Sm%2BcZNO%2BFAIlh%2B6t99WKKj3vz1bekHiwdLWp18GUo9cp3eUkPWXbSBXprXOUHk2QlPK9xd7sG3AHyj4urRv3lc97AR4DRrVIECUMOsNP5BlYW6%2FGAg%3D%3D HTTP/2.0" "Root=1-669028fb-6e750f6c5c7fdde45853b7f6" "authenticate"
- L'utente presenta l'authorization code all'ALB.
- L'ALB risponde con un codice HTTP 302 e reindirizza l'utente all'URI originale:
https://demo.aws.doit.com/auth.html. - Prima di generare la risposta, l'ALB effettua richieste backchannel verso i seguenti endpoint:
Token endpoint dell'IdP, per scambiare il code con un IdToken.

Richiesta POST al Token endpoint.
UserInfo endpoint, per scambiare l'access token con le user claims.

Richiesta all'UserInfo endpoint.
Le user claims, l'access token e il refresh token vengono codificati in base64 e cifrati nel cookie AWSELBAuthSessionCookie.
Passaggio 7 — L'utente richiede l'URI originale con AWSELBAuthSessionCookie impostato.

L'utente viene autenticato dall'ALB e la richiesta arriva al backend.
Access log dell'ALB per la stessa transazione —
h2 2024-07-11T18:48:27.824183Z app/demo/25be909a3f190764 109.78.96.82:54871 172.31.11.119:80 0.007 0.001 0.000 200 200 596 3307 "GET https://demo.aws.doit.com:443/auth.html HTTP/2.0" "arn:aws:elasticloadbalancing:eu-west-1:211125377316:targetgroup/healthyTG/1a24c5faad770fb2 "Root=1-669028fb-156c503c2fe1fcdb60e4a5ad" 2024-07-11T18:48:27.815000Z "authenticate,forward" "172.31.11.119:80" "200"
- Le condizioni della regola dell'ALB per l'azione "authenticate" sono soddisfatte ed è presente anche il cookie di autenticazione.
- L'ALB convalida il cookie e inoltra le informazioni dell'utente ai target tramite gli header HTTP
X-AMZN-OIDC-*.
Header X-AMZN_OIDC* osservati sul target —

Header X-AMZN_OIDC*.
x-amzn-oidc-accesstoken- L'access token proveniente dal token endpoint.
x-amzn-oidc-identity- Il campo subject (sub) restituito dall'user info endpoint.
x-amzn-oidc-data- Le user claims, in formato JSON web token (JWT).
Le user claims in formato JWT comprendono header, payload e signature, codificati in base64 URL. Per generare la firma del JWT l'ALB utilizza ES256 (ECDSA con P-256 e SHA256).
JWT decodificato —

L'header del JWT è un oggetto JSON che contiene issuer, dettagli del signer e key ID. Il payload del JWT è un oggetto JSON con le user claims ricevute dall'UserInfo endpoint dell'IdP.
Il target (Apache) autorizza correttamente l'utente sulla base delle claims e restituisce all'utente, tramite l'ALB, una risposta HTTP 200 OK.
Conclusione —
Questo articolo offre uno sguardo approfondito su come si svolgono le transazioni HTTP durante il flusso authorization code OIDC con AWS Application Load Balancer (ALB). Vengono analizzati uno per uno tutti i passaggi, dalla richiesta HTTP iniziale dell'utente fino all'autenticazione e all'autorizzazione finali, mettendo in evidenza le interazioni HTTP chiave e i dettagli di logging indispensabili per il troubleshooting e per comprendere il processo.
Se desidera saperne di più o è interessato ai nostri servizi, non esiti a contattarci. Può farlo da qui.