Autenticazione e autorizzazione M2M con OAuth 2.0 e OpenID Connect 1.0

Mia-Platform Team 23 aprile 2021

In questo articolo parleremo di come gestire l’autenticazione machine to machine (M2M) attraverso il protocollo di autorizzazione OAuth 2.0.
Cercheremo di fare luce sulle differenze tra autorizzazione, autenticazione e meccanismo di delega dell’autorizzazione. Faremo riferimento alla specifica OpenID Connect 1.0 (OIDC) dalla quale abbiamo preso spunto per l’implementazione dei metodi di autenticazione. 

Nel prossimo articolo illustreremo e descriveremo la nostra implementazione del meccanismo di autenticazione e autorizzazione M2M attraverso il componente Client Credentials.

 

Introduzione 

Prima o poi capita a tutti di dover esporre dati via API verso l’esterno e di doverne consentire il consumo esclusivamente ai client designati. 

Entrano qui in gioco parecchi concetti come login, credenziali, token, permessi, autorizzazione, autenticazione, il flusso e l’ordine in cui determinate azioni devono essere effettuate, e così via. Ognuno di questi concetti ha un significato e un confine preciso. Cerchiamo quindi di fare un po’ di chiarezza.

 

Autenticazione e Autorizzazione: quali sono le differenze?

Per prima cosa spieghiamo la differenza fra autenticazione e autorizzazione, due termini spesso utilizzati in maniera intercambiabile, ma che hanno in realtà due significati e funzioni differenti.

L’autenticazione permette di verificare che il chiamante sia chi afferma di essere e quindi di verificarne l’identità. Questa operazione viene fatta tramite la validazione di credenziali che possono essere password, dati biometrici, firme digitali e altre modalità in base al livello di sicurezza richiesto dal sistema. L’autenticazione è solitamente eseguita prima dell’autorizzazione.
Una volta che l’utente è autenticato, l’autorizzazione stabilisce le risorse a cui esso può accedere tramite l’assegnazione di permessi agli utenti, regole e policy.

Riassumendo, si può dire che l'autenticazione permette di verificare l’identità del chiamante, mentre l’autorizzazione consente di determinare le risorse a cui il chiamante può o non può accedere.

Non è semplice gestire autorizzazione e autenticazione. Soprattutto nel caso in cui il server che vuole accedere a una risorsa di un terzo è un server diverso da quello che la possiede.
Fortunatamente esistono dei protocolli che aiutano a scegliere e implementare il corretto flusso per il proprio caso d’uso. Il più noto è il protocollo OAuth 2.0 di cui parleremo di seguito. Scopriremo che OAuth 2.0 non è una specifica esaustiva sui meccanismi di autenticazione e autorizzazione, ma si occupa di descrivere molteplici meccanismi per l’ottenimento di un token autorizzativo.

 

RFC 6749: The OAuth 2.0 Authorization Framework

OAuth 2.0 (OAuth) è descritto nella specifica RFC 6749 titolata “The OAuth 2.0 Authorization Framework”. Sul sito oauth.net è introdotto come “OAuth 2.0 is the industry-standard protocol for authorization”. Da questi contenuti si è portati a pensare che tale protocollo si occupi di autorizzazione in senso stretto. Eppure OAuth sottintende che il sistema che applica le policy autorizzative e che concede l’accesso alle risorse, sia già esistente. 

Ma allora di che cosa si occupa OAuth 2.0? 

Questo protocollo può essere meglio inquadrato se descritto come un protocollo di delega degli accessi. Il ruolo che OAuth si pone è quello di descrivere come un client possa accedere alle risorse protette (Resource) di un utente (Resource Owner), le quali risiedono su un server terzo (Resource Server), senza che il client venga a conoscenza delle credenziali del Resource Owner. 

Mia-Platform_Client-credentials_OAuth Figura 1: Flusso astratto del protocollo

 

Questo avviene, come descritto dal flusso teorico del protocollo visibile in figura 1, tramite i seguenti passaggi:

  • Il Resource Owner concede l'autorizzazione (Authorization Grant) al client [Passi A, B];
  • Il client ottiene un Access Token, con il quale può accedere alla risorsa protetta [Passi C, D];
  • Il client utilizza l’Access Token per accedere alla risorsa protetta [Passi E, F].

 

Prima di fornire ulteriori spiegazioni è necessario fare un paio di precisazioni. 

Come un occhio attento avrà già notato dalle prima righe di questo paragrafo, OAuth non si occupa di autenticazione, al più ne dà qualche suggerimento.
OAuth non è neppure una guida esaustiva su come implementare i meccanismi di autorizzazione all’interno del proprio sistema; bensì è una specifica che descrive la sequenza di azioni che devono (MUST) essere fatte, quelle che dovrebbero (SHOULD) essere fatte, quelle che possono essere fatte (MAY) e quelle che non devono essere fatte (MUST NOT). Il modo in cui queste azioni possono essere implementate va oltre le scopo di questo protocollo, nonostante questi spesso fornisca alcuni suggerimenti a riguardo.

Per esempio, al punto 3.1 Authorization Endpoint della specifica, viene detto:

"The authorization endpoint is used to interact with the resource owner and obtain an authorization grant. The authorization server MUST first verify the identity of the resource owner. The way in which the authorization server authenticates the resource owner (e.g., username and password login, session cookies) is beyond the scope of this specification."

La specifica quindi impone che per usare l’endpoint di autorizzazione, l’Authorization Server debba verificare l’identità - autenticare - del Resource Owner, ma non ne descrive le modalità.

Questo è solo un esempio dei molteplici punti in cui la specifica OAuth 2.0 lascia libertà di implementazione. Questa libertà non è spesso apprezzata dagli sviluppatori, i quali si trovano a non sapere come implementare gli aspetti che la specifica non definisce. Il rischio è inoltre quello di effettuare un’implementazione che non rispetta determinati requisiti di sicurezza.

Anche per questo motivo ci si affida spesso a servizi esterni (Okta, Auth0, Authlete) che implementano i protocolli sopra citati rispettando al contempo i necessari requisiti di sicurezza e offrendo molteplici alternative di implementazione, come ad esempio diverse modalità di autenticazione.

Quindi lo scopo principale della specifica OAuth 2.0 è definire:

  • Come avviene l’ottenimento dell’Access Token da parte del client;
  • Come il client può usare l’Access Token per ottenere accesso alla risorsa richiesta.

La parte più interessante di questo protocollo è proprio il flusso di ottenimento del token. Vediamo come può avvenire.

 

Flussi di concessione dell’autorizzazione (Grant Type)

Il protocollo OAuth 2.0 descrive quattro possibili flussi autorizzativi e ognuno di essi ha un particolare caso d’uso.

  • Authorization Code Grant: utilizzato da applicazioni server side.

  • Implicit Grant: utilizzato da applicazioni mobile o web (SPA), o comunque applicazioni che vengono eseguite sul dispositivo (User Agent) dell’utente. In questo flusso l’Access Token viene fatto transitare sullo User Agent dell’utente, rendendo potenzialmente l’Access Token accessibile a parti non autorizzate.
    Ne è sconsigliato l’uso e laddove possibile è consigliato l’uso del Authorization Code Grant with Proof Key for Code Exchange (PKCE), il quale risulta essere un’estensione del Authorization Code Grant e descritto in una specifica a parte (RFC 7636).

  • Resource Owner Password Credentials Grant: utilizzato da applicazioni considerate altamente sicure (trusted) poiché le credenziali dell’utente transitano attraverso l’applicazione stessa.
    È utilizzato solitamente in applicazioni legacy o in fase di migrazione. La specifica stessa, al paragrafo 10.7, dice essere un anti-pattern rispetto a ciò che il protocollo stesso cerca di evitare: l’utente, infatti, deve concedere le proprie credenziali al client il quale lo impersonificherà.

  • Client Credentials Grant: utilizzato per l’accesso API tramite interazione M2M. 

La spiegazione nel dettaglio di ciascuno di questi flussi va oltre gli scopi di questo articolo; in rete sono presenti molteplici risorse che spiegano nel dettaglio i flussi sopra citati (1, 2, 3).
Ci concentreremo esclusivamente sull’ultimo flusso autorizzativo, il Client Credentials Grant.

 

Client Credentials Grant

Client Credentials Grant è sicuramente il più semplice dei flussi autorizzativi di OAuth 2.0. Lo si può intuire dalla seguente rappresentazione grafica:

 

Mia-Platform_Client-credentials-grant

Figura 2: Flusso del Client Credential Grant

 

Come emerge dalla figura 2, questo flusso non prevede l’interazione con un utente, né con un dispositivo dell'utente: il client è un server - quindi una macchina - e deve accedere a una risorsa su un Resource Server, un’altra macchina. Si tratta esattamente dell’ipotesi che abbiamo illustrato all’inizio dell’articolo: il consumo di una API attraverso un’interazione M2M.

La specifica OAuth 2.0 (4.4 Client Credentials Grant) afferma:

"The client can request an access token using only its client credentials (or other supported means of authentication) when the client is requesting access to the protected resources under its control, or those of another resource owner that have been previously arranged with the authorization server (the method of which is beyond the scope of this specification).
The client credentials grant type MUST only be used by confidential clients."

Come abbiamo già visto, OAuth non si occupa di autenticazione e la specifica semplicemente afferma che per l’ottenimento dell’Access Token sono sufficienti le credenziali del client o altri mezzi di autenticazione supportati.

Questo metodo è utilizzato quando il client richiede accesso a risorse protette:

  • di sua appartenenza (il client è il resource owner stesso);
  • di un altro resource owner che ha precedentemente concordato con l’Authorization Server l’accesso alle proprie risorse da parte del client. Il meccanismo di questa concessione non è definito nella specifica.

 

La RFC spiega infine il formato di input e output della richiesta dell’Access Token.
Può sembrare a questo punto che il flusso Client Credential sia così banale da risultare inutile implementarlo, cadendo nella tentazione di implementare un proprio meccanismo senza quindi dover aderire a queste specifiche. La sua forza risiede proprio nella sua semplicità. OAuth 2.0 standardizza il flusso autorizzativo con cui si può usufruire di una API in un’interazione M2M.

In un dialogo M2M Mia-Platform - grazie a un microservizio appositamente sviluppato - offre la possibilità di accedere alle proprie API attraverso il meccanismo standard Client Credentials di OAuth 2.0 rendendo l’integrazione il più semplice e veloce possibile. 

 

Client authentication in OpenID Connect 1.0

OpenID Connect 1.0 è un meccanismo costruito al di sopra di OAuth 2.0 che standardizza l’identificazione dell’utente. Nasce dall’esigenza di ridurre lo sforzo impiegato nell’integrarsi con Identity Provider per autenticare un utente e ottenere informazioni addizionali su di esso.

In passato ogni Identity Provider costruiva su OAuth 2.0 dei permessi e delle API custom dediti all’ottenimento di informazioni di identificazione su un utente. Di conseguenza, un client per mettere a disposizione degli utenti svariati provider di autenticazione/identificazione - i classici login con Google, Facebook, LinkedIn, etc - doveva implementare per ognuno di essi meccanismi differenti.

 

Mia-Platform_Client-credentials1

OIDC 1.0 standardizza questi meccanismi mettendo a disposizione strumenti come l’ID Token, l’API di /userinfo e nomi standard per varie proprietà di identificazione (nome è given_name, cognome è family_name, nome completo è name, …) riducendo drasticamente i tempi di integrazione con Identity Provider.

 

Mia-Platform_Client-credentials2

 

Tutto ciò ha enorme valore laddove sia presente un utente, ma l’interazione descritta in questo articolo è tra due macchine. Perché parlarne allora?

Come detto in precedenza, OAuth 2.0 rimane abbastanza vago sulle modalità tramite cui il client può autenticarsi con l’Authentication Server.
Nel paragrafo 2.3 Client Authentication del RFC 6749 viene infatti affermato “The authorization server MAY accept any form of client authentication meeting its security requirements”, lasciando libertà di implementazione per la Client Authentication.
OIDC non solo standardizza l’identificazione dell’utente, ma definisce alcune modalità semplici e sicure per effettuare la Client Authentication.

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 sono stati implementati in Mia-Platform all’interno del componente Client Credentials.

Nel prossimo articolo descriveremo come queste specifiche sono stato implementate, mostrando quindi come un client esterno può accedere a una API erogata da Mia-Platform oppure da un servizio terzo, usando Mia-Platform come provider di autenticazione e autorizzazione. 

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

 

Mia Platform - White Paper - Tutto quello che devi sapere per orientarti nel mondo del DevOps

Post Correlati

API Management: cosa non può mancare in una piattaforma moderna

L'API Management è un aspetto immancabile di un'azienda di successo. Le Application Programming Interface (API) sono infatti oggi cen...
Mia-Platform Team 20 maggio 2020

Flow Manager: l'orchestratore di Saga di Mia-Platform

Una delle ragioni che potrebbero inibire l’adozione dell’approccio Saga Pattern - che abbiamo approfondito in questo articolo - è lo ...
Mia-Platform Team 03 febbraio 2021

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

In un articolo precedente abbiamo parlato di come si gestisce l’autenticazione machine to machine attraverso il protocollo OAuth 2.0,...
Mia-Platform Team 12 maggio 2021