Microsoft Identity Platform e flusso On-Behalf-Of di OAuth 2.0

Il flusso On-Behalf-Of (OBO) di OAuth 2.0 viene usato quando un'applicazione richiama un servizio o un'API Web, che a sua volta deve chiamare un altro servizio o un'altra API Web. Lo scopo è di propagare l'identità utente delegato e le autorizzazioni attraverso la catena di richieste. Per eseguire richieste autenticate al servizio downstream, il servizio di livello intermedio deve assicurarsi un token di accesso da Microsoft Identity Platform per conto dell'utente.

Questo articolo descrive come programmare direttamente in base al protocollo nell'applicazione. Quando possibile, è consigliabile usare le librerie di autenticazione Microsoft (MSAL) supportate anziché acquisire i token e chiamare le API Web protette. Vedere anche le app di esempio che usano MSAL.

A partire da maggio 2018, non è possibile usare un id_token derivato da flusso implicito per il flusso OBO. Le applicazioni a pagina singola dovrebbero invece passare un token di accesso a un client riservato di livello intermedio per eseguire i flussi OBO. Per altre informazioni su quali client possono eseguire chiamate OBO, vedere le limitazioni.

Suggerimento

Provare a eseguire la richiesta in Postman
Provare a eseguire questa richiesta e altro ancora in Postman. Non dimenticare di sostituire token e ID.

Diagramma di protocollo

Si supponga che l'utente sia stato autenticato in un'applicazione usando il flusso di concessione del codice di autorizzazione OAuth 2.0 o un altro flusso di accesso. A questo punto, l'applicazione contiene un token di accesso per l'API A (token A) con le attestazioni dell'utente e il consenso per accedere all'API Web di livello intermedio (API A). L'API A deve ora eseguire una richiesta autenticata all'API Web downstream (API B).

I passaggi che seguono costituiscono il flusso OBO e vengono descritti con l'aiuto del diagramma seguente.

Mostra il flusso On-Behalf-Of di OAuth2.0

  1. L'applicazione client esegue una richiesta all'API A con il token A, con un'attestazione aud dell'API A.
  2. L'API A esegue l'autenticazione all'endpoint di rilascio del token di Microsoft Identity Platform e richiede un token per accedere all'API B.
  3. L'endpoint di rilascio del token di Microsoft Identity Platform convalida le credenziali dell'API A con il token A ed emette il token di accesso per l'API B (token B) all'API A.
  4. Il token B viene impostato dall'API A nell'intestazione dell'autorizzazione della richiesta all'API B.
  5. I dati della risorsa protetta vengono restituiti dall'API B all'API A e quindi al client.

In questo scenario, il servizio di livello intermedio non ha alcuna interazione dell'utente per ottenere il consenso dell'utente per accedere all'API downstream. Pertanto, l'opzione per la concessione dell'accesso all'API downstream viene presentata in anticipo come parte della fase del consenso durante l'autenticazione. Per altre informazioni su questa impostazione per l'app, vedere Ottenere il consenso per l'applicazione di livello intermedio.

Richiesta di token di accesso di livello intermedio

Per richiedere un token di accesso, eseguire una richiesta HTTP POST all'endpoint del token di Microsoft Identity Platform specifico del tenant con i parametri seguenti.

https://login.microsoftonline.com/<tenant>/oauth2/v2.0/token

L'applicazione client può scegliere di essere protetta da un segreto condiviso oppure da un certificato.

Primo caso: richiesta del token di accesso con un segreto condiviso

Quando viene usato un segreto condiviso, una richiesta di token di accesso da servizio a servizio contiene i parametri seguenti:

Parametro Tipo Descrizione
grant_type Obbligatoria Il tipo di richiesta del token. Per una richiesta con un token JWT, il valore deve essere urn:ietf:params:oauth:grant-type:jwt-bearer.
client_id Obbligatoria ID dell'applicazione (client) che la pagina Registrazioni app del portale di Azure ha assegnato all'app.
client_secret Obbligatoria Segreto client generato per l'app nella pagina Registrazioni app del portale di Azure.
assertion Obbligatoria Token di accesso inviato all'API di livello intermedio. Questo token deve avere un'attestazione audience ( ) dell'app che effettua questa richiesta aud OBO (l'app è stata denotata dal client-id campo ). Le applicazioni non possono riscattare un token per un'app diversa( ad esempio, se un client invia un'API a un token destinato a MS Graph, l'API non può riscattarlo usando OBO. Deve invece rifiutare il token).
scope Obbligatoria Un elenco di ambiti separati da spazi per la richiesta di token. Per altre informazioni, vedere Scopes (Ambiti).
requested_token_use Obbligatoria Specifica la modalità di elaborazione della richiesta. Nel flusso OBO il valore deve essere impostato su on_behalf_of.

Esempio

La richiesta HTTP POST seguente richiede un token di accesso e un token di aggiornamento con ambito user.read per l'API Web https://graph.microsoft.com.

//line breaks for legibility only

POST /oauth2/v2.0/token HTTP/1.1
Host: login.microsoftonline.com/<tenant>
Content-Type: application/x-www-form-urlencoded

grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer
client_id=535fb089-9ff3-47b6-9bfb-4f1264799865
&client_secret=sampleCredentia1s
&assertion=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6InowMzl6ZHNGdWl6cEJmQlZLMVRuMjVRSFlPMCJ9.eyJhdWQiOiIyO{a lot of characters here}
&scope=https://graph.microsoft.com/user.read+offline_access
&requested_token_use=on_behalf_of

Secondo caso: richiesta del token di accesso con un certificato

Una richiesta di token di accesso da servizio a servizio con un certificato contiene i parametri seguenti:

Parametro Tipo Descrizione
grant_type Obbligatoria Il tipo di richiesta del token. Per una richiesta con un token JWT, il valore deve essere urn:ietf:params:oauth:grant-type:jwt-bearer.
client_id Obbligatoria ID dell'applicazione (client) che la pagina Registrazioni app del portale di Azure ha assegnato all'app.
client_assertion_type Obbligatoria Il valore deve essere urn:ietf:params:oauth:client-assertion-type:jwt-bearer.
client_assertion Obbligatoria Un'asserzione (un token JSON Web) che è necessario creare e firmare con il certificato registrato come credenziale per l'applicazione. Per informazioni sulla registrazione del certificato e il formato dell'asserzione, vedere le credenziali del certificato.
assertion Obbligatoria Token di accesso inviato all'API di livello intermedio. Questo token deve avere un'attestazione audience ( ) dell'app che effettua questa richiesta aud OBO (l'app è stata denotata dal client-id campo ). Le applicazioni non possono riscattare un token per un'app diversa( ad esempio, se un client invia un'API a un token destinato a MS Graph, l'API non può riscattarlo usando OBO. Deve invece rifiutare il token).
requested_token_use Obbligatoria Specifica la modalità di elaborazione della richiesta. Nel flusso OBO il valore deve essere impostato su on_behalf_of.
scope Obbligatoria Un elenco di ambiti separati da spazi per la richiesta di token. Per altre informazioni, vedere Scopes (Ambiti).

Si noti che i parametri sono quasi uguali a quelli usati nella richiesta tramite segreto condiviso, con l'eccezione del parametro client_secret che viene sostituito da due parametri: client_assertion_type e client_assertion.

Esempio

La richiesta HTTP POST seguente richiede un token di accesso con ambito user.read per l'API Web https://graph.microsoft.com con un certificato.

// line breaks for legibility only

POST /oauth2/v2.0/token HTTP/1.1
Host: login.microsoftonline.com/<tenant>
Content-Type: application/x-www-form-urlencoded

grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer
&client_id=625391af-c675-43e5-8e44-edd3e30ceb15
&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer
&client_assertion=eyJhbGciOiJSUzI1NiIsIng1dCI6Imd4OHRHeXN5amNScUtqRlBuZDdSRnd2d1pJMCJ9.eyJ{a lot of characters here}
&assertion=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6InowMzl6ZHNGdWl6cEJmQlZLMVRuMjVRSFlPMCIsImtpZCI6InowMzl6ZHNGdWl6cEJmQlZLMVRuMjVRSFlPMCJ9.eyJhdWQiO{a lot of characters here}
&requested_token_use=on_behalf_of
&scope=https://graph.microsoft.com/user.read+offline_access

Risposta del token di accesso di livello intermedio

Una risposta di esito positivo è una risposta OAuth 2.0 JSON con i parametri seguenti.

Parametro Descrizione
token_type Indica il valore del tipo di token. L'unico tipo supportato Microsoft Identity Platform è Bearer . Per altre informazioni sui bearer token, vedere OAuth 2.0 Authorization Framework: Bearer Token Usage (RFC 6750) (Framework di autorizzazione di OAuth 2.0: uso dei bearer token - RFC 6750).
scope L'ambito di accesso concesso nel token.
expires_in Il periodo di validità, in secondi, del token di accesso.
access_token Token di accesso richiesto. Il servizio chiamante può usare questo token per l'autenticazione nel servizio ricevente.
refresh_token Il token di aggiornamento per il token di accesso richiesto. Il servizio chiamante può usare questo token per richiedere un altro token di accesso dopo la scadenza di quello corrente. Il token di aggiornamento viene fornito solo se è stato richiesto l'ambito offline_access.

Esempio di risposta di esito positivo

L'esempio seguente mostra una risposta corretta a una richiesta di token di accesso per l'API Web https://graph.microsoft.com.

{
  "token_type": "Bearer",
  "scope": "https://graph.microsoft.com/user.read",
  "expires_in": 3269,
  "ext_expires_in": 0,
  "access_token": "eyJ0eXAiOiJKV1QiLCJub25jZSI6IkFRQUJBQUFBQUFCbmZpRy1tQTZOVGFlN0NkV1c3UWZkQ0NDYy0tY0hGa18wZE50MVEtc2loVzRMd2RwQVZISGpnTVdQZ0tQeVJIaGlDbUN2NkdyMEpmYmRfY1RmMUFxU21TcFJkVXVydVJqX3Nqd0JoN211eHlBQSIsImFsZyI6IlJTMjU2IiwieDV0IjoiejAzOXpkc0Z1aXpwQmZCVksxVG4yNVFIWU8wIiwia2lkIjoiejAzOXpkc0Z1aXpwQmZCVksxVG4yNVFIWU8wIn0.eyJhdWQiOiJodHRwczovL2dyYXBoLm1pY3Jvc29mdC5jb20iLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC83MmY5ODhiZi04NmYxLTQxYWYtOTFhYi0yZDdjZDAxMWRiNDcvIiwiaWF0IjoxNDkzOTMwMzA1LCJuYmYiOjE0OTM5MzAzMDUsImV4cCI6MTQ5MzkzMzg3NSwiYWNyIjoiMCIsImFpbyI6IkFTUUEyLzhEQUFBQU9KYnFFWlRNTnEyZFcxYXpKN1RZMDlYeDdOT29EMkJEUlRWMXJ3b2ZRc1k9IiwiYW1yIjpbInB3ZCJdLCJhcHBfZGlzcGxheW5hbWUiOiJUb2RvRG90bmV0T2JvIiwiYXBwaWQiOiIyODQ2ZjcxYi1hN2E0LTQ5ODctYmFiMy03NjAwMzViMmYzODkiLCJhcHBpZGFjciI6IjEiLCJmYW1pbHlfbmFtZSI6IkNhbnVtYWxsYSIsImdpdmVuX25hbWUiOiJOYXZ5YSIsImlwYWRkciI6IjE2Ny4yMjAuMC4xOTkiLCJuYW1lIjoiTmF2eWEgQ2FudW1hbGxhIiwib2lkIjoiZDVlOTc5YzctM2QyZC00MmFmLThmMzAtNzI3ZGQ0YzJkMzgzIiwib25wcmVtX3NpZCI6IlMtMS01LTIxLTIxMjc1MjExODQtMTYwNDAxMjkyMC0xODg3OTI3NTI3LTI2MTE4NDg0IiwicGxhdGYiOiIxNCIsInB1aWQiOiIxMDAzM0ZGRkEwNkQxN0M5Iiwic2NwIjoiVXNlci5SZWFkIiwic3ViIjoibWtMMHBiLXlpMXQ1ckRGd2JTZ1JvTWxrZE52b3UzSjNWNm84UFE3alVCRSIsInRpZCI6IjcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0NyIsInVuaXF1ZV9uYW1lIjoibmFjYW51bWFAbWljcm9zb2Z0LmNvbSIsInVwbiI6Im5hY2FudW1hQG1pY3Jvc29mdC5jb20iLCJ1dGkiOiJWR1ItdmtEZlBFQ2M1dWFDaENRSkFBIiwidmVyIjoiMS4wIn0.cubh1L2VtruiiwF8ut1m9uNBmnUJeYx4x0G30F7CqSpzHj1Sv5DCgNZXyUz3pEiz77G8IfOF0_U5A_02k-xzwdYvtJUYGH3bFISzdqymiEGmdfCIRKl9KMeoo2llGv0ScCniIhr2U1yxTIkIpp092xcdaDt-2_2q_ql1Ha_HtjvTV1f9XR3t7_Id9bR5BqwVX5zPO7JMYDVhUZRx08eqZcC-F3wi0xd_5ND_mavMuxe2wrpF-EZviO3yg0QVRr59tE3AoWl8lSGpVc97vvRCnp4WVRk26jJhYXFPsdk4yWqOKZqzr3IFGyD08WizD_vPSrXcCPbZP3XWaoTUKZSNJg",
  "refresh_token": "OAQABAAAAAABnfiG-mA6NTae7CdWW7QfdAALzDWjw6qSn4GUDfxWzJDZ6lk9qRw4An{a lot of characters here}"
}

Il token di accesso precedente è un token in formato v1.0 per Microsoft Graph. Questo avviene perché il formato del token è basato sulla risorsa a cui si accede e non è correlata agli endpoint usati per richiederla. Microsoft Graph è impostata per accettare token v1.0, quindi il Microsoft Identity Platform produce token di accesso v1.0 quando un client richiede token per Microsoft Graph. Altre app possono indicare che vogliono token in formato v2.0, token in formato v1.0 o anche formati di token proprietari o crittografati. Entrambi gli endpoint v1.0 e v2.0 possono generare entrambi i formati di token, in questo modo la risorsa può sempre ottenere il formato corretto del token indipendentemente da come o dove il token è stato richiesto dal client.

Avviso

Non tentare di convalidare o leggere i token per qualsiasi API di cui non si è proprietari, inclusi i token in questo esempio, nel codice. I token per servizi Microsoft possono usare un formato speciale che non verrà convalidato come token JWT e può anche essere crittografato per gli utenti consumer (account Microsoft). Anche se la lettura dei token è uno strumento utile per il debug e l'apprendimento, non creare dipendenze nel codice o presupporre specifiche sui token che non sono per un'API che si controlla.

Esempio di risposta con errore

Quando si tenta di acquisire un token di accesso per l'API downstream, viene restituita una risposta di errore dall'endpoint del token, se per l'API downstream sono impostati criteri di accesso condizionale, ad esempio l'autenticazione a più fattori. Il servizio di livello intermedio segnala l'errore all'applicazione client in modo che questa possa fornire l'interazione dell'utente per soddisfare i criteri di accesso condizionale.

{
    "error":"interaction_required",
    "error_description":"AADSTS50079: Due to a configuration change made by your administrator, or because you moved to a new location, you must enroll in multifactor authentication to access 'bf8d80f9-9098-4972-b203-500f535113b1'.\r\nTrace ID: b72a68c3-0926-4b8e-bc35-3150069c2800\r\nCorrelation ID: 73d656cf-54b1-4eb2-b429-26d8165a52d7\r\nTimestamp: 2017-05-01 22:43:20Z",
    "error_codes":[50079],
    "timestamp":"2017-05-01 22:43:20Z",
    "trace_id":"b72a68c3-0926-4b8e-bc35-3150069c2800",
    "correlation_id":"73d656cf-54b1-4eb2-b429-26d8165a52d7",
    "claims":"{\"access_token\":{\"polids\":{\"essential\":true,\"values\":[\"9ab03e19-ed42-4168-b6b7-7001fb3e933a\"]}}}"
}

Usare il token di accesso per accedere alla risorsa protetta

Il servizio di livello intermedio può ora usare il token acquisito in precedenza per eseguire richieste autenticate all'API Web downstream, impostando il token nell'intestazione Authorization.

Esempio

GET /v1.0/me HTTP/1.1
Host: graph.microsoft.com
Authorization: Bearer eyJ0eXAiO ... 0X2tnSQLEANnSPHY0gKcgw

Asserzioni SAML ottenute con un flusso di OAuth2.0 OBO

Alcuni servizi Web di OAuth devono accedere ad altre API di servizi Web che accettano le asserzioni SAML in flussi non interattivi. Azure AD può fornire un'asserzione SAML in risposta a un flusso on-behalf-of che usa un servizio Web SAML come risorsa di destinazione.

Si tratta di un'estensione non standard del flusso on-behalf-of di OAuth 2.0 che consente a un'applicazione OAuth2 di accedere agli endpoint API del servizio Web che usano token SAML.

Suggerimento

Se un servizio Web protetto con SAML viene chiamato da un'applicazione Web front-end, è sufficiente chiamare l'API e avviare un flusso di autenticazione interattiva normale con la sessione esistente degli utenti. È necessario usare un flusso OBO quando una chiamata da servizio a servizio richiede un token SAML per fornire il contesto utente.

Ottenere un token SAML usando una richiesta OBO con un segreto condiviso

Una richiesta da servizio a servizio per un'asserzione SAML contiene i parametri seguenti:

Parametro Tipo Descrizione
grant_type obbligatorio Il tipo di richiesta del token. Per una richiesta che usa un JWT, il valore deve essere urn:ietf:params:oauth:grant-type:jwt-bearer.
assertion obbligatorio Il valore del token di accesso usato nella richiesta.
client_id obbligatorio L'ID app assegnato al servizio chiamante durante la registrazione con Azure AD. Per trovare l'ID app nel portale di Azure, selezionare Active Directory, scegliere la directory e quindi selezionare il nome dell'applicazione.
client_secret obbligatorio La chiave registrata per il servizio chiamante in Azure AD. È necessario prendere nota di questo valore al momento della registrazione.
scope obbligatorio Un elenco di ambiti separati da spazi per la richiesta di token. Per altre informazioni, vedere Scopes (Ambiti). Ad esempio, https://testapp.contoso.com/user_impersonation 'openid'
requested_token_use necessarie Specifica la modalità di elaborazione della richiesta. Nel flusso on-behalf-of il valore deve essere on_behalf_of.
requested_token_type obbligatorio Specifica il tipo di token richiesto. Il valore può essere urn:ietf:params:oauth:token-type:saml2 o urn:ietf:params:oauth:token-type:saml1, a seconda dei requisiti della risorsa a cui si accede.

La risposta contiene un token SAML con codifica UTF8 e Base64url.

  • SubjectConfirmationData per un'asserzione SAML che ha origine da una chiamata OBO: se l'applicazione di destinazione richiede un valore del destinatario in SubjectConfirmationData, nella configurazione dell'applicazione della risorsa deve essere impostato come URL di risposta senza caratteri jolly.

  • Nodo SubjectConfirmationData: Il nodo non può contenere un attributo InResponseTo perché non fa parte di una risposta SAML. L'applicazione che riceve il token SAML deve essere in grado di accettare l'asserzione SAML senza un attributo InResponseTo.

  • Consenso: per ricevere un token SAML che contiene i dati utente in un flusso OAuth, è necessario aver autorizzato il consenso. Per informazioni sulle autorizzazioni e su come ottenere il consenso dell'amministratore, vedere Autorizzazioni e consenso nell'endpoint v1.0 di Azure Active Directory.

Risposta con asserzione SAML

Parametro Descrizione
token_type Indica il valore del tipo di token. L'unico tipo supportato da Azure AD è Bearer. Per altre informazioni sui bearer token, vedere OAuth 2.0 Authorization Framework: Bearer Token Usage (RFC 6750) (Framework di autorizzazione di OAuth 2.0: uso dei bearer token - RFC 6750).
scope Ambito di accesso concesso nel token.
expires_in Il periodo di validità del token di accesso (in secondi).
expires_on Scadenza del token di accesso. La data è rappresentata come numero di secondi da 1970-01-01T0:0:0Z UTC fino alla scadenza. Questo valore viene usato per determinare la durata dei token memorizzati nella cache.
resource L'URI dell'ID app del servizio ricevente (risorsa protetta).
access_token Il parametro che restituisce l'asserzione SAML.
refresh_token Token di aggiornamento. Il servizio chiamante può usare questo token per richiedere un altro token di accesso dopo la scadenza dell'asserzione SAML corrente.
  • token_type: Bearer
  • expires_in: 3296
  • ext_expires_in: 0
  • expires_on: 1529627844
  • risorsa: https://api.contoso.com
  • access_token: <SAML assertion>
  • issued_token_type: urn:ietf:params:oauth:token-type:saml2
  • refresh_token: <Refresh token>

A seconda dell'architettura o dell'utilizzo dell'applicazione, è possibile prendere in considerazione diverse strategie per garantire che il flusso OBO abbia esito positivo. In tutti i casi, l'obiettivo finale è quello di garantire il consenso appropriato, in modo che l'app client possa chiamare l'app di livello intermedio e l'app di livello intermedio disponga dell'autorizzazione per chiamare la risorsa back-end.

Nota

In precedenza il sistema di account Microsoft (account personali) non supportava il campo "applicazione client nota", né poteva visualizzare il consenso combinato. Questa funzionalità è stata aggiunta e tutte le app di Microsoft Identity Platform possono usare l'approccio basato sull'applicazione client nota per ottenere il consenso per le chiamate a OBO.

L'applicazione di livello intermedio aggiunge il client all'elenco delle applicazioni client note nel relativo manifesto e quindi il client può attivare un flusso di consenso combinato per se stesso e l'applicazione di livello intermedio. Nel Microsoft Identity Platform questa operazione viene eseguita usando /.default l'ambito. Quando si attiva una schermata di consenso con le applicazioni client note e /.default, la schermata di consenso visualizzerà le autorizzazioni sia del client per l'API di livello intermedio e richiederà anche le eventuali autorizzazioni necessarie per l'API di livello intermedio. L'utente fornisce il consenso per entrambe le applicazioni e quindi il flusso OBO funziona.

Applicazioni preautorizzate

Le risorse possono indicare che una determinata applicazione disponga sempre dell'autorizzazione per ricevere determinati ambiti. Ciò risulta particolarmente utile per semplificare le connessioni tra un client front-end e una risorsa back-end. Una risorsa può dichiarare più applicazioni preautorizzate: qualsiasi applicazione di questo tipo può richiedere tali autorizzazioni in un flusso OBO e riceverle senza che l'utente fornisca il consenso.

Un amministratore del tenant può garantire che le applicazioni siano autorizzate a chiamare le API necessarie fornendo il consenso dell'amministratore per l'applicazione di livello intermedio. A tale scopo, l'amministratore può trovare l'applicazione di livello intermedio nel proprio tenant, aprire la pagina delle autorizzazioni necessarie e scegliere di concedere l'autorizzazione per l'app. Per altre informazioni sul consenso dell'amministratore, vedere la documentazione su autorizzazioni e consenso.

Uso di un'applicazione singola

In alcuni scenari può esserci solo una singola associazione del client di livello intermedio e front-end. In questo scenario può risultare più semplice impostare l'applicazione come singola, senza la necessità di un'applicazione di livello intermedio. Per eseguire l'autenticazione tra il front-end e l'API Web, è possibile usare i cookie, un id_token o un token di accesso richiesto per l'applicazione stessa. Quindi, richiedere il consenso da questa applicazione singola alla risorsa back-end.

Limitazioni client

Se un client usa il flusso implicito per ottenere un id_token e quel client dispone anche di caratteri jolly in un URL di risposta, non è possibile usare l'id_token per un flusso OBO. Tuttavia, i token di accesso acquisiti tramite il flusso di concessione implicita possono ancora essere riscattati da un client riservato anche se il client di origine dispone di un URL di risposta con caratteri jolly registrato.

Passaggi successivi

Altre informazioni sul protocollo OAuth 2.0 e su un altro modo per eseguire l'autenticazione da servizio a servizio usando le credenziali del client.