Gestire errori ed eccezioni in MSAL.NET

Questo articolo offre una panoramica dei diversi tipi di errori e consigli per la gestione degli errori di accesso comuni.

Nozioni di base sulla gestione degli errori MSAL

Le eccezioni in Libreria di Autenticazione Microsoft (MSAL) sono destinate agli sviluppatori di app per la risoluzione dei problemi, non per la visualizzazione agli utenti finali. I messaggi di eccezione non vengono localizzati.

Quando si elaborano eccezioni ed errori, è possibile usare il tipo di eccezione stesso e il codice di errore per distinguere le eccezioni. Per un elenco dei codici di errore, vedere Microsoft Entra codici di errore di autenticazione e autorizzazione.

Durante l'esperienza di accesso, è possibile che si verifichino errori relativi al consenso, all'accesso condizionale (MFA, Gestione dispositivi, alle restrizioni basate sulla posizione), al rilascio e al riscatto dei token e alle proprietà utente.

La sezione seguente fornisce altri dettagli sulla gestione degli errori per l'app.

Gestione degli errori in MSAL.NET

Tipi di eccezione

MsalClientException viene generata quando la libreria stessa rileva uno stato di errore, ad esempio una configurazione non valida.

MsalServiceException viene generata quando il provider di identità (Microsoft Entra ID) restituisce un errore. Si tratta di una traduzione dell'errore del server.

MsalUIRequiredException è di tipo MsalServiceException e indica che è necessaria l'interazione dell'utente. Ad esempio, quando è necessaria l'autenticazione a più fattori (MFA) o quando l'utente modifica la password e un token non può essere acquisito automaticamente.

Gestione delle eccezioni

Quando si elaborano .NET eccezioni, è possibile usare il tipo di eccezione stesso e il ErrorCode membro per distinguere le eccezioni. ErrorCode i valori sono costanti di tipo MsalError.

È anche possibile esaminare i campi di MsalClientException, MsalServiceException e MsalUIRequiredException.

Se viene generata l'eccezione MsalServiceException , provare i codici di errore di autenticazione e autorizzazione per verificare se il codice è elencato.

Se viene sollevata l'eccezione MsalUIRequiredException, ciò indica che è necessario avviare un flusso interattivo affinché l'utente possa risolvere il problema. Nelle app client pubbliche, ad esempio desktop e app per dispositivi mobili, questa operazione viene risolta chiamando AcquireTokenInteractive, che visualizza un browser. Nelle app client riservate le app Web devono reindirizzare l'utente alla pagina di autorizzazione e le API Web devono restituire un codice di stato HTTP e un'intestazione indicativa dell'errore di autenticazione (401 Non autorizzato e un'intestazione WWW-Authenticate).

Eccezioni comuni .NET

Ecco le eccezioni comuni che potrebbero essere generate e alcune possibili mitigazioni:

Eccezione Codice di errore Mitigation
MsalUiRequiredException AADSTS65001: l'utente o l'amministratore non ha acconsentito a usare l'applicazione con ID '{appId}' denominato '{appName}'. Inviare una richiesta di autorizzazione interattiva per questo utente e questa risorsa. Ottenere prima il consenso dell'utente. Se non si usa .NET Core (che non ha alcuna interfaccia utente Web), chiamare (una sola volta) AcquireTokenInteractive. Se si usa .NET core o non si vuole eseguire un AcquireTokenInteractive' , l'utente può passare a un URL per fornire il consenso: https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id={clientId}&response_type=code&scope=user.read. per chiamare AcquireTokenInteractive: app.AcquireTokenInteractive(scopes).WithAccount(account).WithClaims(ex.Claims).ExecuteAsync();
MsalUiRequiredException AADSTS50079: l'utente deve usare l'autenticazione a più fattori (MFA). Non esiste alcuna mitigazione. Se l'autenticazione a più fattori è configurata per il tenant e Microsoft Entra ID decide di applicarla, ripiegare su un flusso interattivo come AcquireTokenInteractive.
MsalServiceException AADSTS90010: il tipo di concessione non è supportato negli endpoint /common o /consumer . Usare /organizations o l'endpoint specifico del tenant. È stato usato /common. Come illustrato nel messaggio di Microsoft Entra ID, l'autorità deve avere un tenant o in caso contrario /organizations.
MsalServiceException AADSTS70002: il corpo della richiesta deve contenere il parametro seguente: client_secret or client_assertion. Questa eccezione può essere generata se l'applicazione non è stata registrata come applicazione client pubblica in Microsoft Entra ID. Nel Interfaccia di amministrazione di Microsoft Entra, modifica il manifest dell'applicazione e imposta allowPublicClient su true.
MsalClientException unknown_user Message: non è stato possibile identificare l'utente connesso La libreria non è riuscita a interrogare l’utente Windows attualmente connesso oppure questo utente non è aggiunto a Active Directory o a Microsoft Entra (gli utenti aggiunti al luogo di lavoro non sono supportati). Mitigazione: implementare la propria logica per recuperare il nome utente (ad esempio, john@contoso.com) e usare il AcquireTokenByIntegratedWindowsAuth modulo che accetta il nome utente.
MsalClientException integrated_windows_auth_not_supported_managed_user Questo metodo si basa su un protocollo esposto da Active Directory (AD). Se un utente è stato creato in Microsoft Entra ID senza eseguire il backup di Active Directory ("utente gestito"), questo metodo ha esito negativo. Gli utenti creati in AD e supportati da Microsoft Entra ID ("federati") possono trarre vantaggio da questo metodo di autenticazione non interattivo. Mitigazione: usare l'autenticazione interattiva.

MsalUiRequiredException

Uno dei codici di stato comuni restituiti da MSAL.NET quando si chiama AcquireTokenSilent() è MsalError.InvalidGrantError. Questo codice di stato indica che l'applicazione deve richiamare la libreria di autenticazione, ma in modalità interattiva (AcquireTokenInteractive o AcquireTokenByDeviceCodeFlow per le applicazioni client pubbliche, oppure eseguire una challenge nelle app Web). Ciò è dovuto al fatto che è necessaria un'interazione utente aggiuntiva prima di poter emettere il token di autenticazione.

La maggior parte dei casi AcquireTokenSilent in cui si verifica un errore è dovuto al fatto che la cache dei token non dispone di token corrispondenti alla richiesta. I token di accesso scadono in 1 ora e AcquireTokenSilent tentano di recuperare un nuovo token in base a un token di aggiornamento (in termini OAuth2, si tratta del flusso del "Token di aggiornamento"). Questo flusso può anche non riuscire per diversi motivi, ad esempio se un amministratore tenant configura criteri di accesso più rigorosi.

L'interazione mira a indurre l'utente a compiere un'azione. Alcune di queste condizioni sono facili da risolvere (ad esempio, accettare condizioni per l'utilizzo con un solo clic) e alcune non possono essere risolte con la configurazione corrente (ad esempio, il computer in questione deve connettersi a una rete aziendale specifica). Alcuni consentono all'utente di configurare l'autenticazione a più fattori o di installare Microsoft Authenticator nel dispositivo.

MsalUiRequiredException enumerazione di classificazione

MSAL espone un Classification campo, che è possibile leggere per offrire un'esperienza utente migliore. Ad esempio, per indicare all'utente che la password è scaduta o che deve fornire il consenso per usare alcune risorse. I valori supportati fanno parte dell'enumerazione UiRequiredExceptionClassification :

Classification Meaning Gestione consigliata
BasicAction La condizione può essere risolta dall'interazione dell'utente durante il flusso di autenticazione interattiva. Chiamare AcquireTokenInteractively().
Azione aggiuntiva La condizione può essere risolta tramite un'interazione correttiva aggiuntiva con il sistema, all'esterno del flusso di autenticazione interattiva. Chiamare AcquireTokenInteractively() per visualizzare un messaggio che spiega l'azione correttiva. L'applicazione chiamante può scegliere di nascondere i flussi che richiedono additional_action se è improbabile che l'utente completi l'azione correttiva.
MessageOnly La condizione non può essere risolta in questo momento. L'avvio del flusso di autenticazione interattiva mostrerà un messaggio che spiega la condizione. Chiamare AcquireTokenInteractively() per visualizzare un messaggio che spiega la condizione. AcquireTokenInteractively() restituirà l'errore UserCanceled dopo che l'utente legge il messaggio e chiude la finestra. L'applicazione chiamante può scegliere di nascondere i flussi che generano message_only se è improbabile che l'utente tragga vantaggio dal messaggio.
Consenso richiesto Il consenso dell'utente è mancante o è stato revocato. Chiama AcquireTokenInteractively() per consentire all'utente di fornire il consenso.
Password utente scaduta La password dell'utente è scaduta. Chiamare AcquireTokenInteractively() in modo che l'utente possa reimpostare la password.
PromptNeverFailed L'autenticazione interattiva è stata chiamata con il parametro prompt=never, forzando MSAL a basarsi sui cookie del browser e non visualizzare il browser. L'operazione non è riuscita. Chiamare AcquireTokenInteractively() senza Prompt.None
Acquisizione automatica del token non riuscita MSAL SDK non dispone di informazioni sufficienti per recuperare un token dalla cache. Ciò può essere dovuto al fatto che nella cache non sono presenti token o non è stato trovato un account. Il messaggio di errore contiene altri dettagli. Chiamare AcquireTokenInteractively().
Nessuno Non vengono forniti altri dettagli. La condizione può essere risolta dall'interazione dell'utente durante il flusso di autenticazione interattiva. Chiamare AcquireTokenInteractively().

esempio di codice .NET

AuthenticationResult res;
try
{
 res = await application.AcquireTokenSilent(scopes, account)
        .ExecuteAsync();
}
catch (MsalUiRequiredException ex) when (ex.ErrorCode == MsalError.InvalidGrantError)
{
 switch (ex.Classification)
 {
  case UiRequiredExceptionClassification.None:
   break;
  case UiRequiredExceptionClassification.MessageOnly:
  // You might want to call AcquireTokenInteractive(). Azure AD will show a message
  // that explains the condition. AcquireTokenInteractively() will return UserCanceled error
  // after the user reads the message and closes the window. The calling application may choose
  // to hide features or data that result in message_only if the user is unlikely to benefit 
  // from the message
  try
  {
      res = await application.AcquireTokenInteractive(scopes).ExecuteAsync();
  }
  catch (MsalClientException ex2) when (ex2.ErrorCode == MsalError.AuthenticationCanceledError)
  {
   // Do nothing. The user has seen the message
  }
  break;

  case UiRequiredExceptionClassification.BasicAction:
  // Call AcquireTokenInteractive() so that the user can, for instance accept terms
  // and conditions

  case UiRequiredExceptionClassification.AdditionalAction:
  // You might want to call AcquireTokenInteractive() to show a message that explains the remedial action. 
  // The calling application may choose to hide flows that require additional_action if the user 
  // is unlikely to complete the remedial action (even if this means a degraded experience)

  case UiRequiredExceptionClassification.ConsentRequired:
  // Call AcquireTokenInteractive() for user to give consent.
  
  case UiRequiredExceptionClassification.UserPasswordExpired:
  // Call AcquireTokenInteractive() so that user can reset their password
  
  case UiRequiredExceptionClassification.PromptNeverFailed:
  // You used WithPrompt(Prompt.Never) and this failed
  
  case UiRequiredExceptionClassification.AcquireTokenSilentFailed:
  default:
  // May be resolved by user interaction during the interactive authentication flow.
  res = await application.AcquireTokenInteractive(scopes)
                         .ExecuteAsync(); break;
 }
}

Problemi di Accesso Condizionale e delle attestazioni

Quando si ricevono i token in modo invisibile all'utente, l'applicazione potrebbe ricevere errori quando una richiesta di attestazioni di accesso condizionale , ad esempio i criteri di autenticazione a più fattori, è richiesta da un'API a cui si sta provando ad accedere.

Il modello per la gestione di questo errore consiste nell'acquisire in modo interattivo un token tramite MSAL. Questo sollecita l'utente e gli offre l'opportunità di soddisfare i requisiti necessari dei criteri di Accesso condizionale.

In alcuni casi, quando si effettua una chiamata a un'API che richiede l'accesso condizionale, è possibile ricevere una richiesta di attestazioni nel messaggio di errore restituito dall'API. Ad esempio, se i criteri di accesso condizionale devono avere un dispositivo gestito (Intune), l'errore sarà simile a AADSTS53000: il dispositivo deve essere gestito per accedere a questa risorsa o qualcosa di simile. In questo caso, è possibile passare i claim nella chiamata di acquisizione del token affinché all'utente venga richiesto di soddisfare il criterio appropriato.

Quando si effettua una chiamata a un'API che richiede l'Accesso Condizionale con MSAL.NET, l'applicazione deve gestire le eccezioni di challenge dei claim. Viene visualizzato come MsalServiceException in cui la proprietà Claims non sarà vuota.

Per gestire la richiesta di attestazione, usare WithClaims(String).

Ripetizione di tentativi dopo errori ed eccezioni

È previsto che implementi criteri di ripetizione personalizzati quando effettui chiamate a MSAL. MSAL effettua chiamate HTTP al servizio Microsoft Entra e occasionalmente possono verificarsi errori. Ad esempio, la rete può scendere o il server è sovraccarico.

HTTP 429

Quando il server dei token di servizio (STS) è sovraccarico a causa di un numero eccessivo di richieste, restituisce l'errore HTTP 429 con un'indicazione del tempo da attendere prima di poter riprovare nel campo di risposta Retry-After.

Codici di errore HTTP 500-600

MSAL.NET implementa un semplice meccanismo che prevede un solo tentativo di ripetizione per gli errori con codici HTTP compresi tra 500 e 600.

MsalServiceException espone System.Net.Http.Headers.HttpResponseHeaders come proprietà namedHeaders. È possibile usare informazioni aggiuntive dal codice di errore per migliorare l'affidabilità delle applicazioni. Nel caso descritto, è possibile usare la RetryAfter proprietà (di tipo RetryConditionHeaderValue) e calcolare quando riprovare.

Ecco un esempio per un'applicazione daemon che usa il flusso delle credenziali client. È possibile adattarlo a uno qualsiasi dei metodi per l'acquisizione di un token.


bool retry = false;
do
{
    TimeSpan? delay;
    try
    {
         result = await publicClientApplication.AcquireTokenForClient(scopes, account).ExecuteAsync();
    }
    catch (MsalServiceException serviceException)
    {
         if (serviceException.ErrorCode == "temporarily_unavailable")
         {
             RetryConditionHeaderValue retryAfter = serviceException.Headers.RetryAfter;
             if (retryAfter.Delta.HasValue)
             {
                 delay = retryAfter.Delta;
             }
             else if (retryAfter.Date.HasValue)
             {
                 delay = (retryAfter.Date.Value – DateTimeOffset.Now).TotalMilliseconds;
             }
         }
    }
    // . . .
    if (delay.HasValue)
    {
        Thread.Sleep((int)delay.Value.TotalMilliseconds); // sleep or other
        retry = true;
    }
} while (retry);

Passaggi successivi

Valuta di abilitare la registrazione in MSAL.NET per aiutarti a diagnosticare ed eseguire il debug di eventuali problemi.