Accesso dell'applicazione a pagina singola usando il flusso implicito OAuth 2.0 in Azure Active Directory B2C

Molte applicazioni moderne hanno un front-end di app a pagina singola (SPA) scritto principalmente in JavaScript. Spesso l'app viene scritta usando un framework come React, Angular o Vue.js. Gli spA e altre app JavaScript che vengono eseguite principalmente in un browser presentano alcune sfide aggiuntive per l'autenticazione:

  • Le caratteristiche di sicurezza di queste app sono diverse dalle applicazioni Web basate su server tradizionali.

  • Molti server di autorizzazione e provider di identità non supportano richieste CORS (Cross-Origin Resource Sharing).

  • Il browser a pagina intera reindirizza dall'app può essere invasivo per l'esperienza utente.

Il modo consigliato per supportare gli SPA è il flusso di codice di autorizzazione OAuth 2.0 (con PKCE).

Alcuni framework, come MSAL.js 1.x, supportano solo il flusso di concessione implicita. In questi casi, Azure Active Directory B2C (Azure AD B2C) supporta il flusso di concessione implicita dell'autorizzazione OAuth 2.0. Il flusso è descritto nella sezione 4.2 della specifica OAuth 2.0. Nel flusso implicito, l'app riceve i token direttamente dall'endpoint di autorizzazione B2C di Azure AD, senza alcun scambio da server a server. Tutte le operazioni di gestione delle sessioni e della logica di autenticazione vengono eseguite interamente nel client JavaScript con un reindirizzamento di pagina o una casella popup.

Azure AD B2C estende il flusso implicito OAuth 2.0 standard e va oltre le semplici operazioni di autorizzazione e autenticazione. Azure AD B2C introduce il parametro di criteri. Con il parametro di criteri è possibile usare OAuth 2.0 per aggiungere criteri all'app, ad esempio i flussi utente di iscrizione, accesso e gestione dei profili. Nell'esempio di richieste HTTP in questo articolo viene usato {tenant}.onmicrosoft.com per l'illustrazione. Sostituire {tenant} con il nome del tenant se ne hai uno. È inoltre necessario creare un flusso utente.

Viene usata la figura seguente per illustrare il flusso di accesso implicito. Ogni passaggio verrà descritto in dettaglio più avanti nell'articolo.

Diagramma in stile swimlane che mostra il flusso implicito openID Connect

Invio di richieste di autenticazione

Quando l'applicazione Web deve autenticare l'utente ed eseguire un flusso utente, indirizza l'utente all'endpoint di /authorize Azure AD B2C. L'utente esegue l'azione a seconda del flusso utente.

In questa richiesta, il client indica le autorizzazioni che deve acquisire dall'utente nel scope parametro e dal flusso utente da eseguire. Per ottenere un'idea del funzionamento della richiesta, provare a incollarla in un browser ed eseguirla. Sostituire:

  • {tenant} con il nome del tenant di Azure AD B2C.

  • 90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6 con l'ID app dell'applicazione registrata nel tenant.

  • {policy} con il nome di un criterio creato nel tenant, ad esempio b2c_1_sign_in.

GET https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/{policy}/oauth2/v2.0/authorize?
client_id=90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6
&response_type=id_token+token
&redirect_uri=https%3A%2F%2Faadb2cplayground.azurewebsites.net%2F
&response_mode=fragment
&scope=openid%20offline_access
&state=arbitrary_data_you_can_receive_in_the_response
&nonce=12345

I parametri nella richiesta HTTP GET sono illustrati nella tabella seguente.

Parametro Obbligatoria Descrizione
{tenant} Nome del tenant di Azure AD B2C
{policy} Nome del flusso utente da eseguire. Specificare il nome di un flusso utente creato nel tenant di Azure AD B2C. Ad esempio: b2c_1_sign_in, b2c_1_sign_up o b2c_1_edit_profile.
client_id ID applicazione assegnato all'applicazione portale di Azure.
response_type Deve includere id_token per l'accesso a OpenID Connect. Può includere anche il tipo di tokenrisposta . Se si usa token, l'app può ricevere immediatamente un token di accesso dall'endpoint di autorizzazione senza dover inviare una seconda richiesta a tale endpoint. Se si usa il tipo di risposta token, il parametro scope deve contenere un ambito che indica la risorsa per cui emettere il token.
redirect_uri No URI di reindirizzamento dell'app dove le risposte di autenticazione possono essere inviate e ricevute dall'app. Deve corrispondere esattamente a uno degli URI di reindirizzamento aggiunti a un'applicazione registrata nel portale, ad eccezione del fatto che deve essere codificato con URL.
response_mode No Specifica il metodo da usare per restituire il token risultante all'app. Per i flussi impliciti, usare fragment.
ambito Elenco di ambiti separato da spazi. Un singolo valore di ambito indica Microsoft Entra ID entrambe le autorizzazioni richieste. L'ambito openid indica un'autorizzazione per l'accesso dell'utente e per ottenere i dati relativi all'utente sotto forma di token ID. L’ambito offline_access è facoltativo per le applicazioni Web. Indica che l'app necessita di un token di aggiornamento per avere un accesso duraturo alle risorse.
state No Valore incluso nella richiesta che viene anche restituito nella risposta del token. Può trattarsi di una stringa di qualsiasi contenuto si voglia usare. Per evitare attacchi di richiesta intersito falsa, viene in genere usato un valore univoco generato casualmente. Lo stato viene usato anche per codificare informazioni sullo stato dell'utente nell'app prima che si sia verificata la richiesta di autenticazione, ad esempio la pagina in cui l'utente è stato attivato o il flusso utente in esecuzione.
nonce Valore incluso nella richiesta, generata dall'app, che viene incorporato nel token ID risultante come attestazione. L'app può quindi verificare questo valore per l'attenuazione degli attacchi di riproduzione del token. Il valore è in genere una stringa casuale univoca che può essere usata per identificare l'origine della richiesta.
prompt No Tipo di interazione utente obbligatoria. Al momento l'unico valore valido è login. Questo parametro impone all'utente di immettere le proprie credenziali in tale richiesta. La singola Sign-On non ha effetto.

Questa è la parte interattiva del flusso. L'utente viene chiesto di completare il flusso di lavoro del criterio. L'utente potrebbe dover immettere il nome utente e la password, accedere con un'identità social, iscriversi a un account locale o qualsiasi altro numero di passaggi. Le azioni dell'utente dipendono dal modo in cui è definito il flusso utente.

Al termine del flusso utente, Azure AD B2C restituisce una risposta all'app tramite redirect_uri. Viene usato il metodo specificato nel parametro response_mode. La risposta è esattamente la stessa per ogni scenario di azione dell'utente, indipendentemente dal flusso utente eseguito.

Risposta di esito positivo

Una risposta con esito positivo che usa response_mode=fragment e response_type=id_token+token è simile a quanto riportato di seguito. Sono state aggiunte interruzioni di riga per migliorare la leggibilità:

GET https://aadb2cplayground.azurewebsites.net/#
access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1Q...
&token_type=Bearer
&expires_in=3599
&scope="90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6 offline_access",
&id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1Q...
&state=arbitrary_data_you_sent_earlier
Parametro Descrizione
access_token Token di accesso richiesto dall'app da Azure AD B2C.
token_type Valore del tipo di token. L'unico tipo supportato da Azure AD B2C è Bearer.
expires_in Periodo di validità del token di accesso (in secondi).
ambito Ambiti per i quali il token è valido. È possibile usare gli ambiti anche per memorizzare i token nella cache per un uso successivo.
id_token Token ID richiesto dall'app. È possibile usare il token ID per verificare l'identità dell'utente e avviare una sessione con l'utente. Per informazioni dettagliate sui token ID e sul relativo contenuto, vedere Azure AD B2C: informazioni di riferimento sui token.
state Se nella richiesta è incluso un parametro state, lo stesso valore deve essere visualizzato nella risposta. L'app deve verificare che i valori state nella richiesta e nella risposta siano identici.

Risposta di errore

Anche le risposte di errore possono essere inviate all'URI di reindirizzamento in modo che l'app possa gestirle adeguatamente:

GET https://aadb2cplayground.azurewebsites.net/#
error=access_denied
&error_description=the+user+canceled+the+authentication
&state=arbitrary_data_you_can_receive_in_the_response
Parametro Descrizione
error Codice utilizzato per classificare i tipi di errori che si verificano.
error_description Messaggio di errore specifico che consente di identificare la causa principale di un errore di autenticazione.
state Se nella richiesta è incluso un parametro state, lo stesso valore deve essere visualizzato nella risposta. L'app deve verificare che i valori state nella richiesta e nella risposta siano identici.

Convalidare il token ID

La ricezione di un token ID non è sufficiente per autenticare l'utente. Convalidare la firma del token ID e verificare le attestazioni nel token in base ai requisiti dell'app. Azure AD B2C usa token JSON Web (JWT) e crittografia a chiave pubblica per firmare i token e verificare che siano validi.

Sono disponibili molte librerie open source per la convalida dei token JWT, a seconda del linguaggio preferito. È consigliabile prendere in esame le librerie open source disponibili anziché implementare una logica di convalida personalizzata. È possibile usare le informazioni contenute in questo articolo permettono di imparare a usare correttamente tali librerie.

Azure AD B2C include un endpoint dei metadati di OpenID Connect. Un'app può usare l'endpoint per recuperare informazioni su Azure AD B2C in fase di esecuzione. Queste informazioni includono endpoint, contenuti del token e chiavi per la firma dei token. Il tenant Azure AD B2C include un documento di metadati JSON per ogni flusso utente. Ad esempio, il documento di metadati per un flusso utente denominato b2c_1_sign_in in un fabrikamb2c.onmicrosoft.com tenant si trova in:

https://fabrikamb2c.b2clogin.com/fabrikamb2c.onmicrosoft.com/b2c_1_sign_in/v2.0/.well-known/openid-configuration

Una proprietà di questo documento di configurazione è jwks_uri. Il valore per lo stesso flusso utente sarà:

https://fabrikamb2c.b2clogin.com/fabrikamb2c.onmicrosoft.com/b2c_1_sign_in/discovery/v2.0/keys

Per determinare il flusso utente usato per firmare un token ID (e da dove recuperare i metadati), è possibile usare una delle opzioni seguenti:

  • Il nome del flusso utente è incluso nell'attestazione acr in id_token. Per informazioni su come analizzare le attestazioni da un token ID, vedere Azure AD B2C: informazioni di riferimento sui token.

  • Codificare il flusso utente nel valore del state parametro quando si esegue la richiesta. per poi decodificare il parametro state e determinare il flusso utente usato.

Dopo aver acquisito il documento dei metadati dall'endpoint di metadati OpenID Connect, è possibile usare le chiavi pubbliche RSA 256 che si trovano in questo endpoint per convalidare la firma del token ID. In un determinato punto nel tempo è possibile che siano presenti più chiavi elencate in questo endpoint, ognuna identificata da un'attestazione kid. Anche l'intestazione di id_token contiene un'attestazione kid, che indica le chiavi usate per firmare il token ID. Per altre informazioni, inclusa la convalida dei token, vedere Azure AD B2C: informazioni di riferimento sui token.

Dopo la convalida della firma del token ID sarà necessario verificare anche diverse altre attestazioni, Ad esempio:

  • Convalidare l'attestazione nonce per impedire attacchi di riproduzione dei token. Il valore deve corrispondere a quello specificato nella richiesta di accesso.

  • Convalidare l'attestazione aud per verificare che il token ID sia stato emesso per l'app. Il valore deve essere l'ID applicazione dell'app.

  • Convalidare le attestazioni iat e exp per verificare che il token ID non sia scaduto.

Altre convalide da eseguire sono descritte in dettaglio nella specifica OpenID Connect Core. È anche possibile convalidare attestazioni aggiuntive, a seconda dello scenario. Alcune convalide comuni includono:

  • Verificare che l'utente o l'organizzazione abbia eseguito l'iscrizione all'app.

  • Verificare che l'utente abbia le autorizzazioni e i privilegi adeguati.

  • Garantire che si sia verificata una certa forza di autenticazione, ad esempio usando Microsoft Entra'autenticazione a più fattori.

Per altri dettagli sulle attestazioni in un token ID, vedere Azure AD B2C: informazioni di riferimento sui token.

Dopo aver convalidato il token ID, è possibile iniziare una sessione con l'utente. Usare nell'app le attestazioni del token ID per ottenere informazioni sull'utente. Queste informazioni possono essere usate per la visualizzazione, i record, le autorizzazioni e così via.

Ottenere i token di accesso

Se l'app Web deve solo eseguire flussi utente, è possibile saltare le prossime sezioni. Le informazioni nelle sezioni seguenti sono applicabili solo alle app Web che devono effettuare chiamate autenticate a un'API Web protetta da Azure AD B2C stesso.

Ora che l'utente è stato connesso all'applicazione a pagina singola, è possibile ottenere i token di accesso per chiamare le API Web protette da Microsoft Entra ID. Anche se è già stato ricevuto un token usando il token tipo di risposta, è possibile usare questo metodo per acquisire token per risorse aggiuntive senza reindirizzare l'utente all'accesso.

In un flusso tipico dell'app Web è necessario effettuare una richiesta all'endpoint /token . Tuttavia, l'endpoint non supporta le richieste CORS, quindi l'esecuzione di chiamate AJAX per ottenere un token di aggiornamento non è un'opzione. È possibile usare invece il flusso implicito in un elemento iframe HTML nascosto per ottenere nuovi token per altre API Web. Di seguito è riportato un esempio, con le interruzioni di riga per migliorare la leggibilità:

https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/{policy}/oauth2/v2.0/authorize?
client_id=90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6
&response_type=token
&redirect_uri=https%3A%2F%2Faadb2cplayground.azurewebsites.net%2F
&scope=https%3A%2F%2Fapi.contoso.com%2Ftasks.read
&response_mode=fragment
&state=arbitrary_data_you_can_receive_in_the_response
&nonce=12345
&prompt=none
Parametro Necessaria? Descrizione
{tenant} Necessario Nome del tenant di Azure AD B2C
{policy} Necessario Flusso utente da eseguire. Specificare il nome di un flusso utente creato nel tenant di Azure AD B2C. Ad esempio: b2c_1_sign_in, b2c_1_sign_up o b2c_1_edit_profile.
client_id Necessario ID applicazione assegnato all'app nel portale di Azure.
response_type Obbligatoria Deve includere id_token per l'accesso a OpenID Connect. Può anche includere il tipo di risposta token. Se si usa token in questo momento, l'app può ricevere immediatamente un token di accesso dall'endpoint di autorizzazione senza dover inviare una seconda richiesta a tale endpoint. Se si usa il tipo di risposta token, il parametro scope deve contenere un ambito che indica la risorsa per cui emettere il token.
redirect_uri Consigliato URI di reindirizzamento dell'app dove le risposte di autenticazione possono essere inviate e ricevute dall'app. Deve corrispondere esattamente a uno degli URI di reindirizzamento registrati nel portale, ad eccezione del fatto che deve essere codificato come URL.
ambito Necessario Elenco di ambiti separati da spazi. Per ottenere i token, includere tutti gli ambiti necessari per la risorsa di interesse.
response_mode Consigliato Specifica il metodo usato per restituire il token risultante all'app. Per il flusso implicito, usare fragment. È possibile specificare query altre due modalità e form_post, ma non funzionano nel flusso implicito.
state Consigliato Valore incluso nella richiesta che viene restituito nella risposta del token. Può trattarsi di una stringa di qualsiasi contenuto si voglia usare. Per evitare attacchi di richiesta intersito falsa, viene in genere usato un valore univoco generato casualmente. Anche lo stato viene usato per codificare le informazioni sullo stato dell'utente nell'app prima del verificarsi della richiesta di autenticazione, ad esempio, la pagina o la vista in cui si trovava l'utente.
nonce Necessario Valore incluso nella richiesta, generato dall'app inclusa nel token ID risultante come attestazione. L'app può quindi verificare questo valore per l'attenuazione degli attacchi di riproduzione del token. Il valore è in genere una stringa casuale univoca che identifica l'origine della richiesta.
prompt Necessario Per aggiornare e ottenere i token in un iframe nascosto, usare prompt=none per assicurarsi che l'iframe non si blocchi nella pagina di accesso e restituisca immediatamente.
login_hint Necessario Per aggiornare e ottenere token in un iframe nascosto, includere il nome utente dell'utente in questo hint per distinguere tra più sessioni che l'utente potrebbe avere in un determinato momento. È possibile estrarre il nome utente da un accesso precedente usando l'attestazione preferred_username (l'ambito è necessario per ricevere l'attestazione profilepreferred_username ).
domain_hint Necessario Può essere consumers o organizations. Per aggiornare e ottenere token in un iframe nascosto, includere il domain_hint valore nella richiesta. Estrarre l'attestazione tid dal token ID di un accesso precedente per determinare quale valore usare (l'ambito è necessario per ricevere l'attestazione tidprofile). Se il valore dell'attestazione tid è 9188040d-6c67-4c5b-b112-36a304b66dad, usare domain_hint=consumers. In caso contrario, usare domain_hint=organizations.

Impostando il parametro prompt=none, la richiesta ha immediatamente esito positivo o negativo e torna all'applicazione. Una risposta riuscita viene inviata all'app tramite l'URI di reindirizzamento usando il metodo specificato nel response_mode parametro .

Risposta di esito positivo

Una risposta con esito positivo usando response_mode=fragment è simile all'esempio seguente:

GET https://aadb2cplayground.azurewebsites.net/#
access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1Q...
&state=arbitrary_data_you_sent_earlier
&token_type=Bearer
&expires_in=3599
&scope=https%3A%2F%2Fapi.contoso.com%2Ftasks.read
Parametro Descrizione
access_token Token richiesto dall'app.
token_type Il tipo di token sarà sempre una connessione.
state Se nella richiesta è incluso un parametro state, lo stesso valore deve essere visualizzato nella risposta. L'app deve verificare che i valori state nella richiesta e nella risposta siano identici.
expires_in Tempo di validità del token di accesso (in secondi).
ambito Ambiti per i quali il token di accesso è valido.

Risposta di errore

Anche le risposte di errore possono essere inviate all'URI di reindirizzamento in modo che l'app possa gestirle adeguatamente. Per prompt=none, un errore previsto è simile all'esempio seguente:

GET https://aadb2cplayground.azurewebsites.net/#
error=user_authentication_required
&error_description=the+request+could+not+be+completed+silently
Parametro Descrizione
error Stringa di codice di errore che può essere usata per classificare i tipi di errore che si verificano. È possibile usare la stringa anche per rispondere agli errori.
error_description Messaggio di errore specifico che consente di identificare la causa principale di un errore di autenticazione.

Se si riceve questo errore nella richiesta iframe, l'utente deve accedere di nuovo in modo interattivo per recuperare un nuovo token.

Token di aggiornamento

Token ID e token di accesso scadono entrambi dopo un breve periodo di tempo. L'app deve essere predisposta ad aggiornare periodicamente questi token. I flussi impliciti non consentono di ottenere un token di aggiornamento a causa di motivi di sicurezza. Per aggiornare uno dei tipi di token, usare il flusso implicito in un elemento iframe HTML nascosto. Nella richiesta di autorizzazione includere il prompt=none parametro . Per ricevere un nuovo valore id_token, assicurarsi di usare response_type=id_token e scope=openide un nonce parametro .

Inviare una richiesta di disconnessione

Quando si vuole disconnettere l'utente dall'app, reindirizzare l'utente all'endpoint di disconnessione di Azure AD B2C. È quindi possibile cancellare la sessione dell'utente nell'app. Se non si reindirizza l'utente, potrebbe essere possibile ripetere l'autenticazione all'app senza immettere di nuovo le credenziali perché ha una sessione single Sign-On valida con Azure AD B2C.

È sufficiente reindirizzare l'utente all'oggetto end_session_endpoint elencato nello stesso documento dei metadati di OpenID Connect descritto in Convalidare il token ID. Ad esempio:

GET https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/{policy}/oauth2/v2.0/logout?post_logout_redirect_uri=https%3A%2F%2Faadb2cplayground.azurewebsites.net%2F
Parametro Obbligatoria Descrizione
{tenant} Nome del tenant di Azure AD B2C.
{policy} Flusso utente da usare per disconnettere l'utente dall'applicazione. Deve essere lo stesso flusso utente usato dall'app per accedere all'utente.
post_logout_redirect_uri No URL a cui l'utente deve essere reindirizzato dopo la disconnessione. Se non è incluso, Azure AD B2C mostra all'utente un messaggio generico.
state No Se nella richiesta è incluso un parametro state, lo stesso valore deve essere visualizzato nella risposta. L'applicazione deve verificare che i state valori nella richiesta e nella risposta siano identici.

Nota

Indirizzando l'utente allo end_session_endpoint stato Single Sign-On dell'utente con Azure AD B2C. l'utente non viene disconnesso dalla sessione del provider di identità basato su social network. Se l'utente seleziona lo stesso provider di identità durante un accesso successivo, l'utente viene autenticato nuovamente, senza immettere le credenziali. Se un utente vuole disconnettersi dall'applicazione Azure AD B2C, non significa necessariamente che voglia disconnettersi completamente dal proprio account Facebook, ad esempio. Tuttavia, per gli account locali, la sessione dell'utente viene terminata in modo corretto.

Passaggi successivi

Vedere l'esempio di codice: Accedere con Azure AD B2C in un'applicazione a pagina singola JavaScript.