Ottenere il token (dettaglio tecnico)

Questa pagina descrive nel dettaglio la procedura con cui il client richiede l’access_token a Keycloak. Il meccanismo utilizzato è OAuth 2.0 Client Credentials Grant con autenticazione private_key_jwt (RFC 7521 / RFC 7523): il client non trasmette mai un segreto condiviso ma firma una asserzione con la propria chiave privata, che Keycloak verifica con la chiave pubblica registrata al momento del censimento.

Prerequisiti

Il client deve avere a disposizione:

  • il proprio client_id, comunicato in fase di censimento;

  • la chiave privata RSA in formato PEM (la corrispondente pubblica è registrata su Keycloak);

  • l’URL del realm Keycloak dell’ambiente su cui si opera.

Il token endpoint del realm ha la forma:

https://<keycloak-host>/keycloak/realms/<realm>/protocol/openid-connect/token

Passo 1 — Costruzione della client_assertion

Il client costruisce un JWT firmato RS256 composto da header e payload.

Header:

{
  "alg": "RS256",
  "typ": "JWT"
}

Payload (claim obbligatori):

Claim

Valore

iss

client_id del client

sub

client_id del client

client_id

client_id del client

aud

URL completo del token endpoint (destinatario dell’asserzione)

jti

identificatore univoco della singola asserzione (es. UUID)

iat

istante di emissione (epoch, secondi)

exp

istante di scadenza (epoch, secondi) — tipicamente pochi minuti dopo iat

acr

livello di assurance dichiarato dal client (es. ExternalClient)

La firma è calcolata su base64url(header) + "." + base64url(payload) con la chiave privata del client, algoritmo RSA PKCS#1 v1.5 + SHA-256. Il risultato è concatenato come terza parte del JWT.

Passo 2 — Richiesta dell’access_token

Il client invia una POST al token endpoint con body application/x-www-form-urlencoded e i seguenti parametri:

Parametro

Valore

grant_type

client_credentials

client_id

client_id del client

client_assertion_type

urn:ietf:params:oauth:client-assertion-type:jwt-bearer

client_assertion

il JWT firmato costruito al passo 1

Esempio:

POST /keycloak/realms/<realm>/protocol/openid-connect/token HTTP/1.1
Host: <keycloak-host>
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials
&client_id=<client_id>
&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer
&client_assertion=<JWT_firmato>

Passo 3 — Risposta di Keycloak

Keycloak verifica la firma della client_assertion usando la chiave pubblica registrata per il client. Se la verifica ha successo, restituisce un JSON contenente l’access_token e i relativi metadati:

{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIi...",
  "expires_in": 300,
  "refresh_expires_in": 0,
  "token_type": "Bearer",
  "not-before-policy": 0,
  "scope": "..."
}

Il valore di expires_in indica la durata in secondi dell’access_token; il client deve richiederne uno nuovo prima della scadenza. Non viene rilasciato refresh_token: nel flusso client_credentials il rinnovo avviene ripetendo la richiesta.

Passo 4 — Uso del token verso le API M2M

L’access_token va allegato a ogni chiamata alle API M2M di GovDesk nell’header Authorization:

GET /api/<banca-dati>/<versione>/<microservizio>/<endpoint> HTTP/1.1
Host: <govdesk-host>
Authorization: Bearer <access_token>

Ogni richiesta deve inoltre trasportare l’oggetto operator con i dati dell’operatore per conto del quale il client sta agendo (codice fiscale, livello di assurance, ufficio): questi campi sono obbligatori ai fini dell’audit e sono descritti in Parametri operator (obbligatori per l’audit).

Errori comuni

Codice

Causa più frequente

400 invalid_client

client_id non esiste nel realm oppure client_assertion_type mancante o errato

401 invalid_client / unauthorized_client

firma della client_assertion non valida (chiave privata non corrispondente alla pubblica registrata) o claim aud diverso dal token endpoint

400 invalid_grant

exp scaduto o iat nel futuro rispetto al server; verificare la sincronizzazione dell’orologio

403

client autenticato correttamente ma non autorizzato al servizio richiesto (verificare abilitazioni sul catalogo)