Lab · 07 / 16
Quando non c’è nessun utente.
Un job notturno ha bisogno di dati da un altro servizio. Nessuno digita una password: il servizio dimostra la propria identità e ottiene un token con permessi limitati.
- Service
- un job di backend, senza utente
- IdP
- emette token ai client
- API
- la risorsa protetta
- POST /token
Passo 1 di 5
Richiesta token con un secretRichiesta token con un’asserzione firmata
In parole semplici Il servizio mostra una sua password, come un codice del personale all’ingresso.Il servizio firma un breve biglietto con la sua chiave privata: in rete non viaggia nulla di riutilizzabile.
Il servizio si autentica con client_id e client_secret su TLS. Semplice, ma il secret va custodito, ruotato e mai scritto nei log.Il servizio firma un JWT di breve durata con la sua chiave privata. L’IdP lo verifica con la chiave pubblica registrata. Nessun segreto condiviso da perdere.
POST https://idp.example.com/token Content-Type: application/x-www-form-urlencoded grant_type=client_credentials &scope=invoices:read &client_id=billing-job &client_secret=••••••••••••&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer &client_assertion=eyJhbGciOiJQUzI1NiJ9.eyJpc3MiOiJiaWxsaW5nLWpvYiIsImF1ZCI6Imh0dHBzOi8vaWRwLmV4YW1wbGUuY29tL3Rva2VuIn0.… - access_token
Passo 2 di 5
Un token per il servizio
In parole semplici Il servizio riceve un pass temporaneo che apre una sola porta.
Torna solo un access token: niente ID token, perché non c’è un utente, e di solito niente refresh token, perché il servizio può semplicemente richiederlo.
eyJhbGciOiJSUzI1NiIsInR5cCI6ImF0K2p3dCIsImtpZCI6IjIwMjYtMTAifQ.eyJpc3MiOiJodHRwczovL2lkcC5leGFtcGxlLmNvbSIsInN1YiI6ImJpbGxpbmctam9iIiwiY2xpZW50X2lkIjoiYmlsbGluZy1qb2IiLCJhdWQiOiJodHRwczovL2FwaS5leGFtcGxlLmNvbSIsInNjb3BlIjoiaW52b2ljZXM6cmVhZCIsImV4cCI6MTc2MDAwMDkwMCwiaWF0IjoxNzYwMDAwMDAwfQ.c2lnbmF0dXJlLW9mLWV4YW1wbGUClaim dell’access token
iss"https://idp.example.com"L’IdP che l’ha emesso.
sub"billing-job"Con client credentials il soggetto è il servizio stesso, non una persona.
client_id"billing-job"Quale client registrato ha chiesto il token.
aud"https://api.example.com"L’API per cui il token è valido. Le altre API devono rifiutarlo.
scope"invoices:read"Solo ciò che serve al job: leggere le fatture, niente altro.
exp1760000900Durata breve: 15 minuti. Il job ne chiede semplicemente un altro.
iat1760000000Quando è stato emesso.
- GET /invoices · Bearer
Passo 3 di 5
Chiamata all’API
In parole semplici Il servizio mostra il pass alla porta dell’API.
Il token viaggia nell’header Authorization. È un bearer token: chi lo possiede può usarlo, quindi non deve mai finire nei log o negli URL.
GET https://api.example.com/invoices?since=2026-10-01 Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6ImF0K2p3dCJ9.… - GET /jwks (cache)
Passo 4 di 5
L’API scarica le chiavi pubbliche
In parole semplici La porta tiene una copia del timbro ufficiale per confrontare i pass.
Per verificare la firma, l’API scarica una volta le chiavi pubbliche dell’IdP e le tiene in cache, scegliendo la chiave tramite kid. Da lì la validazione avviene in locale, senza chiamare l’IdP a ogni richiesta.
{ "keys": [ { "kty": "RSA", "kid": "2026-10", "use": "sig", "alg": "RS256", "n": "0vx7agoebGcQSuu…", "e": "AQAB" } ] } - 200 OK
Passo 5 di 5
Accesso concesso, nei limiti dello scope
In parole semplici Il pass è autentico e valido per questa porta, quindi si apre.
Firma, iss, aud, exp e scope sono corretti. Una richiesta di scrittura con lo stesso token riceverebbe 403: lo scope consente solo la lettura.
Flusso completato.
Domini e valori d’esempio. Nulla esce dal tuo browser.