Client Credentials: il servizio per l’autenticazione M2M con OAuth 2.0

Mia-Platform Team 12 maggio 2021

In un articolo precedente abbiamo parlato di come si gestisce l’autenticazione machine to machine attraverso il protocollo OAuth 2.0, specificando anche le differenze tra autorizzazione e autenticazione. 

In questo articolo vogliamo raccontare come lo gestiamo internamente attraverso un componente appositamente realizzato, Client Credentials, che utilizza la registrazione dei client e il flusso Client Credentials di OAuth 2.0, e i metodi di Client Authentication client_secret_basic e private_key_jwt descritti in OpenID Connect 1.0. 

 

Client Credentials

Client Credentials è un servizio di Mia-Platform che abbiamo implementato allo scopo di gestire la registrazione, la login, i permessi e i metadati dei client. 

Tra i requisiti fondamentali troviamo: 

  • Alte performance: il servizio deve essere contattato ad ogni chiamata API sulla piattaforma. Per questo, dovrebbe essere scritto con un linguaggio con alte performance

  • La verifica di validità dell’access-token deve essere fatta sia internamente alla piattaforma che da provider esterni, i quali devono avere anche accesso ai permessi dei client autenticati

Abbiamo deciso di implementare il servizio usando Go, linguaggio già usato in Mia-Platform per altri progetti e che sappiamo essere performante.

Di seguito descriveremo i metodi di autenticazione supportati dal servizio e la fase di autorizzazione, che è indipendente dal tipo di autenticazione che si è effettuata.

Prima di tutto però è importante definire come abbiamo deciso di costruire l’access token che, come abbiamo spiegato in questo articolo, è un attore centrale del protocollo OAuth 2.0.

 

Access Token

Abbiamo scelto di utilizzare come tipologia di access token lo standard JWT (JSON Web Token) che permette di firmare un payload contenente un JSON con un numero variabile di claim. I claim sono un modo comune per le applicazioni di acquisire informazioni sugli utenti, come per esempio i permessi del client che ha richiesto l’autenticazione.
Il Client Credentials crea la signature del token utilizzando una coppia di chiavi asimmetriche, quindi una chiave pubblica e una chiave privata.

Per una spiegazione più dettagliata su JWT consigliamo di leggere il rispettivo RFC o visitare il sito web jwt.io.

 

Autenticazione

Client Secret Basic

Il primo metodo di autenticazione che abbiamo sviluppato è il metodo base per il grant type client credentials, chiamato client secret basic.

Questo metodo di autenticazione si basa sulla condivisione tra il client e il servizio Client Credentials di un client id e di un client secret.

La creazione di questa coppia avviene durante la registrazione del client.

 

Registrazione

Mia-Platform_ClientSecretBasic_registration

 

Come si può vedere dall’immagine, per effettuare la registrazione l’utente deve inviare all’endpoint di registrazione un nome per identificare il client.
Il Client Credentials genera un client id e un secret, e li salva in un database riservato alle credenziali; in un altro database vengono salvate le informazioni non riservate del client, come il nome.
Il Client Credentials risponde quindi con la coppia di credenziali, più le informazioni sulla scadenza e la data di rilascio delle credenziali, come da specifica OAuth2.0 RFC7591.

Login

L’endpoint di login è esposto sotto la rotta /oauth/token, e segue le specifiche OAuth2.0 per il grant type Client Credentials. La richiesta avviene usando il formato x-www-form-urlencoded e le credenziali sono inviate nell’authorization header con tipo Basic. Come si può notare, il nome del metodo di autenticazione deriva dalla posizione delle credenziali nella chiamata di autenticazione.

 

Mia-Platform_Client-secret-basic-registration

 

Il servizio Client Credentials verifica che le credenziali siano corrette e risponde al client con un access token, le informazioni sul tipo di token (nel nostro caso, Bearer) e l’informazione sulla durata (in secondi) del token.

La durata dell’access token deve essere temporalmente limitata così da rendere sicura l’autorizzazione: chi dovesse riuscire a rubare il token non farebbe in tempo a utilizzarlo. 
Per andare incontro alle diverse necessità di sicurezza dei nostri clienti, si è deciso di lasciare configurabile la durata dell’access token.

Con il metodo client secret basic viene inviata la secret per effettuare la login; in questo modo è possibile essere esposti ad attacchi quali man in the middle volti ad ottenere la secret o a possibili errori umani (come per esempio la condivisione di una curl di autenticazione con inserite le credenziali). 

Private Key JWT

Questo metodo di autenticazione eleva notevolmente il livello di sicurezza del meccanismo. Risulta infatti essere tra i metodi consentiti per l’uso di API Financial-Grade (FAPI): questo significa che è adatto a proteggere interazioni di tipo finanziario, bancario e assicurativo.

Da un punto di vista implementativo, gli endpoint di registrazione e di login sono gli stessi usati per Client Secret Basic e cambiano solo i parametri che vengono passati.

 

Mia-Platform_Client-credentials

Registrazione

Questo metodo di autenticazione si basa sul possesso da parte del client di una coppia di chiavi asimmetriche.

Come primo passaggio, il client deve creare una coppia formata da una chiave privata e dalla relativa chiave pubblica e rendere accessibile la chiave pubblica al servizio Client Credentials, condividendola tramite JSON Web Key (JWK), un oggetto JSON che rappresenta una chiave crittografica, come spiegato nel RFC 7517

Con questo metodo di autenticazione il client non condivide con il servizio di autorizzazione nessun secret, ma solamente delle informazioni pubbliche.

Nel diagramma seguente, viene illustrato il flusso di registrazione.

 

Mia-Platform_PrivateKeyJWT_registration

 

Di seguito, un esempio della chiamata di registrazione di un client usando questo sistema di autenticazione e una chiave RSA256:

curl --location --request POST 'http://client-credential-host/register' \

  --header 'Content-Type: application/json' \

  --data-raw '{

    "client_name": "my client name",

    "token_endpoint_auth_method": "private_key_jwt",

    "public_key": {

      "kid": "key id",

      "use": "sig",

      "kty": "RSA",

      "alg": "RSA256",

      "n": "...",

      "e": "AQAB"

    }

  }



La public_key indicata nel body della chiamata è un esempio di JWK.
Il servizio Client Credentials ritorna il client id generato e l’informazione su quando è stato generato. 

 

Login

Una volta ottenuto il client id, il client può usare la chiave privata per ottenere un access token. 

A tal fine il client deve creare un JWT firmato con la propria chiave privata chiamata client assertion. La client assertion contiene le informazioni che consentono a Client Credentials di identificare il client. In questo modo, Client Credentials può validare sia il contenuto del JWT, sia chi è stato a crearlo:  l’unico a possedere la chiave privata è il client.

Per scongiurare un Replay Attack, il JWT non può essere usato più di una volta come metodo di asserzione; chi dovesse entrare in possesso dell’assertion JWT non potrebbe in ogni caso utilizzarlo. È stato quindi risolto in questo modo anche il possibile errore umano della condivisione accidentale di credenziali.

 

Mia-Platform_PrivateKeyJWT_login

 

La richiesta di autenticazione contiene nel body in formato urlencoded:

  • grant_type: costante client_credentials;
  • client_assertion_type: costante urn:ietf:params:oauth:client-assertion-type:jwt-bearer;
  • assertion_jwt: il JWT firmato con la chiave privata in possesso del client. Questo JWT deve contenere nell’header le informazioni sulla chiave pubblica da utilizzare per verificarne la validità. Inoltre, nel payload, deve contenere dei claim fissi:
    • iss: l’issuer, ovvero il clientId del client che genera il JWT
    • sub: il subject, ovvero il clientId del client che richiede la login
    • aud: l’identificativo del servizio Client Credentials
    • jti: un identificativo univoco del JWT
    • iat: quando è stato creato il token
    • exp: la data di scadenza del token
  • client id: il client id per il quale si sta facendo la richiesta di login;
  • token_endpoint_auth_method: costante a private_key_jwt.

 

Autorizzazione

Utilizzo e Validazione dell’access token

Una volta ottenuto l’access token con uno dei due metodi di autenticazione supportati da Client Credentials, il client può utilizzarlo per richiedere l’autorizzazione al resource owner. Questo viene fatto inserendo l’access token nella richiesta, all’interno dell’authorization header.

Se il servizio richiesto è erogato dalla piattaforma di Mia-Platform, la validazione è fatta dallo stesso Client Credentials.

Una delle esigenze dei clienti di Mia-Platform è permettere a sistemi esterni di usare Client Credentials come provider di autenticazione e sistema di assegnazione dei permessi. Tramite questo meccanismo, a un sistema esterno sarà sufficiente verificare la validità dell’access token e i permessi contenuti tra i claim.

Vediamo di seguito i due meccanismi.

 

Validazione del token attraverso Mia-Platform

Una volta che la richiesta è giunta alla piattaforma Mia-Platform, l’access token viene estratto dall’authorization header.

Client Credentials verifica la validità dell’access token attraverso la rispettiva chiave pubblica ed estrae i claim del JWT. Tra questi claim sono presenti i permessi che ha il client, e che possono quindi essere utilizzati per autorizzare il client in base alla richiesta.

La verifica dei permessi, quindi la fase di autorizzazione, può essere fatta dal servizio Authorization Service di Mia-Platform. Il metodo con cui le operazioni di autorizzazione vengono effettuate all’interno della piattaforma Mia-Platform vanno oltre gli scopi di questo articolo. 

Validazione del token attraverso un client esterno

Come detto in precedenza, l’access token è un JWT firmato tramite una chiave asimmetrica. Client Credentials espone un set di chiavi pubbliche (JWKS) tramite un apposito endpoint.

Un provider esterno per verificare l’access token:

  • ottiene il set di chiavi pubbliche;
  • cerca la rispettiva chiave pubblica tramite un identificativo della chiave contenuto nell’access token (nel claim kid contenuto nell’header del JWT);
  • valida l’access token tramite la chiave pubblica appena ottenuta.

Validato il JWT, il servizio esterno estrae e usa i permessi per autorizzare, o meno, l’accesso alla risorsa richiesta.

L’access token ha un ulteriore claim, detto audience, che contiene un identificativo del sistema che possiede la risorsa richiesta. In fase di login un client deve specificare l’audience richiesto.
Questo claim permette di evitare un uso improprio dell’access token da parte del ricevente, come mostrato di seguito.

Tre sistemi A, B e C utilizzano lo stesso provider di autenticazione e possiedono i seguenti permessi:

  • A ha i permessi per accedere a B e C
  • B non ha permessi per accedere a C

Se il sistema A chiamasse con un token il sistema B, nulla vieterebbe al sistema B di usare lo stesso token per accedere al sistema C, sistema al quale non dovrebbe poter accedere. Ma poiché in fase di login il client A specifica come audience B, l’access token può essere utilizzato solo per accedere a B.

Poiché l’audience viene salvato tra i claim del JWT, un sistema esterno può, e deve, verificare se quel token è stato creato per accedere a quel sistema specifico.

Conclusioni

Ci sono diversi modi per gestire l’autenticazione M2M; noi abbiamo scelto di realizzare un servizio apposito, Client Credentials, che utilizza il flusso Client Credentials di OAuth 2.0, e i metodi di Client Authentication client_secret_basic e private_key_jwt descritti in OpenID Connect 1.0.


Realizzando un componente apposito, oltre a svincolarci da terzi, abbiamo potuto calibrare le scelta sulle nostre necessità di performance - utilizzando il linguaggio Go - e di sicurezza - implementando la tecnologia jwt.
Il risultato è un nuovo componente di piattaforma, sicuro e performante, che può essere configurato in modo semplice e veloce, con un notevole risparmio di costi.

 

Articolo scritto da Davide Bianchi, Senior Technical Leader, e Davide Tantillo, Senior Technical Leader

 

White Paper - Digital Integration Hub: portare i dati al centro per accelerare lo sviluppo di nuovi servizi digitali

Post Correlati

Lavorare da remoto: la guida definitiva

Stiamo vivendo un momento storico delicato, in cui tante aziende hanno dovuto riorganizzarsi e tante persone si sono ritrovate a lavo...
Mia-Platform Team 05 marzo 2020

Da monolite a microservizi: come far evolvere un’applicazione legacy

La trasformazione digitale ha introdotto innovazioni tecnologiche, software e applicative, che si sono dimostrate estremamente vantag...
Mia-Platform Team 13 marzo 2020

Autenticazione e autorizzazione M2M con OAuth 2.0 e OpenID Connect 1.0

In questo articolo parleremo di come gestire l’autenticazione machine to machine (M2M) attraverso il protocollo di autorizzazione OAu...
Mia-Platform Team 23 aprile 2021