Che cos'e'#
OAuth 2.0 e OIDC risolvono due problemi distinti: come permettere a un'app di accedere a risorse di un altro servizio senza condividere la password dell'utente (OAuth), e come dire all'app chi e' quell'utente (OIDC). Sono due protocolli separati che lavorano in coppia nel 90% dei casi reali.
OAuth 2.0 delega l'autorizzazione tramite access token a scope limitato. OIDC aggiunge l'autenticazione con l'ID Token JWT. Insieme abilitano il "Accedi con Google/GitHub" e le integrazioni API sicure.
TL;DR#
- Un'app (Client) vuole accedere a risorse dell'utente su un altro servizio (Resource Server).
- L'utente approva su Authorization Server (Google, GitHub...).
- Authorization Server emette un Access Token con scope limitato.
- Il Client usa l'Access Token per chiamare le API del Resource Server.
- Se l'app ha anche bisogno di sapere chi e' l'utente: aggiunge
openidagli scope, riceve anche un ID Token (JWT con le claims di identita').
OAuth 2.0 - Il Framework di Autorizzazione#
OAuth 2.0 (Open Authorization) e' un framework standard per la delega degli accessi. Permette a un'app terza di accedere a risorse protette per conto dell'utente, senza che l'utente consegni mai le sue credenziali all'app. L'access token ricevuto ha scope limitato: l'app ottiene solo i permessi che l'utente ha esplicitamente approvato.

Grant Types#
I grant types sono i diversi flussi di scambio credenziali in OAuth 2.0. Ogni scenario ha il suo flusso ottimale: un'app web con redirect del browser usa Authorization Code, un servizio backend che parla con un altro servizio usa Client Credentials.
| Grant Type | Quando usarlo | Caratteristica chiave |
|---|---|---|
| Authorization Code + PKCE | App web, app mobile con redirect browser | Flusso piu' sicuro, con redirect e code verifier |
| Client Credentials | Server-to-server, background job, microservizi | Nessun utente coinvolto, solo client ID + secret |
| Device Flow | Smart TV, CLI, dispositivi senza browser | Codice breve mostrato su schermo, utente approva su altro device |
Authorization Code e' il piu' comune: il client non riceve mai direttamente le credenziali, riceve un code temporaneo e lo scambia con il token. PKCE (Proof Key for Code Exchange) aggiunge protezione per app mobile dove non si puo' tenere un secret sicuro.
Flusso Authorization Code#
Il flusso piu' comune in produzione. L'utente approva su Authorization Server, che emette un code usa-e-getta. Il client lo scambia con l'access token in una chiamata server-to-server (il token non passa dal browser).
sequenceDiagram
participant U as Utente (Browser)
participant C as Client App
participant AS as Authorization Server
participant RS as Resource Server (API)
C->>U: 1 - Redirect a AS con scope e state
U->>AS: 2 - Utente approva i permessi
AS->>U: 3 - Redirect al Client con code
U->>C: 4 - Code consegnato al Client
C->>AS: 5 - Scambia code con access token (server-to-server)
AS->>C: 6 - Access Token + Refresh Token
C->>RS: 7 - Chiama API con Access Token
RS->>C: 8 - Risposta con i dati
Lettura diagramma: Il code (passi 3-4) passa dal browser ma e' usa-e-getta e breve. Lo scambio token (passo 5) avviene server-to-server, non tocca il browser. Il Resource Server (passo 7-8) non sa chi e' l'utente, sa solo che il token ha gli scope necessari.*
OIDC - OpenID Connect#
OIDC (OpenID Connect) e' uno strato di identita' costruito sopra OAuth 2.0. Aggiunge l'autenticazione a un framework che di per se' gestisce solo l'autorizzazione. In pratica: quando usi OIDC, fai tutto quello che faresti con OAuth (access token, scope, redirect) e in piu' ricevi un ID Token - un JWT che certifica chi e' l'utente.

ID Token e Claims#
L'ID Token e' un JWT (JSON Web Token) firmato dall'Authorization Server. Il Client lo decodifica e verifica la firma: se la firma e' valida, le informazioni sull'utente (claims) sono affidabili. Le claims includono sub (l'ID univoco dell'utente), email, name e metadati sull'emissione del token (iss, aud, exp).
graph LR
HEADER["Header
alg: RS256
typ: JWT"]
PAYLOAD["Payload (Claims)
sub: 12345abc
email: mario@gmail.com
name: Mario Rossi
iss: accounts.google.com
aud: client-id-spotify
exp: 1753027200"]
SIG["Signature
HMAC/RSA della
concatenazione
header.payload"]
HEADER --> IDTOKEN["ID Token (JWT)"]
PAYLOAD --> IDTOKEN
SIG --> IDTOKEN
Lettura diagramma: Un JWT e' tre sezioni in Base64 separate da punti. L'header specifica l'algoritmo di firma. Il payload contiene le claims (informazioni sull'utente). La signature verifica che il token non sia stato alterato. Il Client verifica la firma usando la chiave pubblica dell'Authorization Server.*
OAuth vs OIDC - La distinzione critica#
Questa e' la trappola piu' frequente all'esame Security+ e nella pratica quotidiana. OAuth e OIDC non sono alternative: sono livelli sovrapposti.
| OAuth 2.0 | OIDC | |
|---|---|---|
| Domanda a cui risponde | Cosa puo' fare questa app? | Chi e' questo utente? |
| Token principale | Access Token | ID Token (JWT) |
| Scope minimo | Qualsiasi | openid obbligatorio |
| Contiene identita' | No | Si' (claims: sub, email, name) |
| Caso d'uso | Accesso API, delega permessi | Login, identita' utente |
| Esempio | Spotify legge Google Calendar | "Accedi con Google" su Spotify |
"Accedi con Google" usa entrambi: OAuth per i permessi e OIDC per l'identita'. Non e' l'uno o l'altro.
"Accedi con Google" - Come funziona davvero#
Quando clicchi "Accedi con Google" su un sito terzo, stai usando OAuth 2.0 + OIDC insieme. Il sito non vede mai la tua password Google, riceve un ID Token che certifica la tua identita' e (opzionalmente) un access token per accedere alle API Google che hai autorizzato.
sequenceDiagram
participant U as Utente
participant S as Sito Terzo (Client)
participant G as Google (AS + IdP)
U->>S: Clicca "Accedi con Google"
S->>G: Redirect con scope=openid profile email
G->>U: Schermata di consenso Google
U->>G: Approva
G->>S: Code (via redirect)
S->>G: Scambia code con token (server-to-server)
G->>S: Access Token + ID Token (JWT)
S->>S: Verifica firma ID Token
Note over S: ID Token dice: sub=abc123, email=mario@gmail.com
S->>U: Login completato come Mario
Lettura diagramma: Il sito terzo riceve due token. L'access token permette di chiamare le Google API con i permessi approvati. L'ID Token (JWT) contiene le claims di identita': il sito sa chi e' l'utente senza mai aver visto la sua password.*

Scenario Reale Blue Team#
Dal punto di vista difensivo, OAuth e OIDC introducono superfici d'attacco specifiche da monitorare: token leak nei log, consent phishing (app malevola chiede scope eccessivi), token replay.
# Verificare token OAuth in circolazione (log applicazione)
grep -i "access_token\|bearer" /var/log/nginx/access.log | grep -v "Authorization: Bearer"
# Token inspection (JWT decode senza verifica firma - solo analisi)
echo "eyJ..." | cut -d. -f2 | base64 -d 2>/dev/null | python3 -m json.tool
# Verificare scope di un token (se si usa un IdP con introspection endpoint)
curl -s -X POST https://idp.example.com/oauth/introspect \
-d "token=ACCESS_TOKEN&client_id=CLIENT_ID&client_secret=CLIENT_SECRET"
# Cercare refresh token esposti in variabili d'ambiente o config
grep -r "refresh_token\|client_secret" /etc/ /var/www/ 2>/dev/null | grep -v ".pyc"Collegato a#
- pki - ID Token JWT usa firme asimmetriche RSA/ECDSA, stessa infrastruttura PKI
- ssl-tls - il trasporto di tutti i flussi OAuth/OIDC avviene sempre su TLS
Dev parallel (Symfony/Node): In Symfony,
knpuniversity/oauth2-client-bundleimplementa il flusso Authorization Code. Il redirect verso Google, il callback concode, lo scambio con access token: e' esattamente il passo 1-6 del diagramma sopra. OIDC aggiunge l'id_tokennel response: il bundle lo decodifica e ti da' email e sub (user ID) pronti da usare.In Node.js con Passport,
passport-google-oauth20gestisce tutto il flusso OAuth. Ilprofileche ricevi nella callback e' l'equivalente delle OIDC claims: gia' decodificato e verificato dalla libreria.La trappola comune per chi viene dal web development: usare l'access token per autenticare l'utente. L'access token non dice chi sei - e' opaco. Serve l'ID Token OIDC per fare autenticazione. Alcune librerie (come passport-google-oauth20) gestiscono OIDC internamente e nascondono la distinzione, ma il principio rimane.


