Gestire errori ed eccezioni in MSAL per iOS/macOS

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 per iOS/macOS

L'elenco completo degli errori MSAL per iOS e macOS è elencato nell'enumerazione MSALError.

Tutti gli errori generati da MSAL vengono restituiti con MSALErrorDomain il dominio.

In caso di errori di sistema, MSAL restituisce l'originale NSError dell'API di sistema. Ad esempio, se l'acquisizione del token non riesce a causa della mancanza di connettività di rete, MSAL restituisce un errore con il dominio NSURLErrorDomain e il codice NSURLErrorNotConnectedToInternet.

È consigliabile gestire almeno i due errori MSAL seguenti sul lato client:

  • MSALErrorInteractionRequired: l'utente deve eseguire una richiesta interattiva. Esistono molte condizioni che possono causare questo errore, ad esempio una sessione di autenticazione scaduta o la necessità di requisiti di autenticazione aggiuntivi. Chiamare l'API di acquisizione di token interattivi MSAL per il ripristino.

  • MSALErrorServerDeclinedScopes: alcuni o tutti gli ambiti sono stati rifiutati. Scegliere se continuare solo con le autorizzazioni concesse o di interrompere il processo di accesso.

Note

L'enumerazione MSALInternalError deve essere usata solo per riferimento e debug. Non tentare di gestire automaticamente questi errori in fase di esecuzione. Se l'app rileva uno degli errori che rientrano in MSALInternalError, può essere utile visualizzare un messaggio generico rivolto all'utente che spiega cosa è successo.

Ad esempio, MSALInternalErrorBrokerResponseNotReceived significa che l'utente non ha completato l'autenticazione ed è tornato manualmente all'app. In questo caso, l'app dovrebbe visualizzare un messaggio di errore generico che spiega che l'autenticazione non è stata completata e suggerisce che provano a eseguire nuovamente l'autenticazione.

Il codice di esempio seguente Objective-C illustra le procedure consigliate per la gestione di alcune condizioni di errore comuni.

    MSALInteractiveTokenParameters *interactiveParameters = ...;
    MSALSilentTokenParameters *silentParameters = ...;
    
    MSALCompletionBlock completionBlock;
    __block __weak MSALCompletionBlock weakCompletionBlock;
    
    weakCompletionBlock = completionBlock = ^(MSALResult *result, NSError *error)
    {
        if (!error)
        {
            // Use result.accessToken
            NSString *accessToken = result.accessToken;
            return;
        }
        
        if ([error.domain isEqualToString:MSALErrorDomain])
        {
            switch (error.code)
            {
                case MSALErrorInteractionRequired:
                {
                    // Interactive auth will be required
                    [application acquireTokenWithParameters:interactiveParameters
                                            completionBlock:weakCompletionBlock];
                    
                    break;
                }
                    
                case MSALErrorServerDeclinedScopes:
                {
                    // These are list of granted and declined scopes.
                    NSArray *grantedScopes = error.userInfo[MSALGrantedScopesKey];
                    NSArray *declinedScopes = error.userInfo[MSALDeclinedScopesKey];
                    
                    // To continue acquiring token for granted scopes only, do the following
                    silentParameters.scopes = grantedScopes;
                    [application acquireTokenSilentWithParameters:silentParameters
                                                  completionBlock:weakCompletionBlock];
                    
                    // Otherwise, instead, handle error fittingly to the application context
                    break;
                }
                    
                case MSALErrorServerProtectionPoliciesRequired:
                {
                    // Integrate the Intune SDK and call the
                    // remediateComplianceForIdentity:silent: API.
                    // Handle this error only if you integrated Intune SDK.
                    // See more info here: https://aka.ms/intuneMAMSDK
                    
                    break;
                }
                    
                case MSALErrorUserCanceled:
                {
                    // The user cancelled the web auth session.
                    // You may want to ask the user to try again.
                    // Handling of this error is optional.
                    
                    break;
                }
                    
                case MSALErrorInternal:
                {
                    // Log the error, then inspect the MSALInternalErrorCodeKey
                    // in the userInfo dictionary.
                    // Display generic error message to the end user
                    // More detailed information about the specific error
                    // under MSALInternalErrorCodeKey can be found in MSALInternalError enum.
                    NSLog(@"Failed with error %@", error);
                    
                    break;
                }
                    
                default:
                    NSLog(@"Failed with unknown MSAL error %@", error);
                    
                    break;
            }
            
            return;
        }
        
        // Handle no internet connection.
        if ([error.domain isEqualToString:NSURLErrorDomain] && error.code == NSURLErrorNotConnectedToInternet)
        {
            NSLog(@"No internet connection.");
            return;
        }
        
        // Other errors may require trying again later,
        // or reporting authentication problems to the user.
        NSLog(@"Failed with error %@", error);
    };
    
    // Acquire token silently
    [application acquireTokenSilentWithParameters:silentParameters
                                  completionBlock:completionBlock];

     // or acquire it interactively.
     [application acquireTokenWithParameters:interactiveParameters
                             completionBlock:completionBlock];
    let interactiveParameters: MSALInteractiveTokenParameters = ...
    let silentParameters: MSALSilentTokenParameters = ...
            
    var completionBlock: MSALCompletionBlock!
    completionBlock = { (result: MSALResult?, error: Error?) in
                
        if let result = result
        {
            // Use result.accessToken
            let accessToken = result.accessToken
            return
        }

        guard let error = error as NSError? else { return }

        if error.domain == MSALErrorDomain, let errorCode = MSALError(rawValue: error.code)
        {
            switch errorCode
            {
                case .interactionRequired:
                    // Interactive auth will be required
                    application.acquireToken(with: interactiveParameters, completionBlock: completionBlock)

                case .serverDeclinedScopes:
                    let grantedScopes = error.userInfo[MSALGrantedScopesKey]
                    let declinedScopes = error.userInfo[MSALDeclinedScopesKey]

                    if let scopes = grantedScopes as? [String] {
                        silentParameters.scopes = scopes
                        application.acquireTokenSilent(with: silentParameters, completionBlock: completionBlock)
                    }
                        
                    case .serverProtectionPoliciesRequired:
                        // Integrate the Intune SDK and call the
                        // remediateComplianceForIdentity:silent: API.
                        // Handle this error only if you integrated Intune SDK.
                        // See more info here: https://aka.ms/intuneMAMSDK
                        break
                        
                    case .userCanceled:
                       // The user cancelled the web auth session.
                       // You may want to ask the user to try again.
                       // Handling of this error is optional.
                       break
                        
                    case .internal:
                        // Log the error, then inspect the MSALInternalErrorCodeKey
                        // in the userInfo dictionary.
                        // Display generic error message to the end user
                        // More detailed information about the specific error
                        // under MSALInternalErrorCodeKey can be found in MSALInternalError enum.
                        print("Failed with error \(error)");
                        
                    default:
                        print("Failed with unknown MSAL error \(error)")
            }
        }
                
        // Handle no internet connection.
        if error.domain == NSURLErrorDomain && error.code == NSURLErrorNotConnectedToInternet
        {
            print("No internet connection.")
            return
        }
                
        // Other errors may require trying again later,
        // or reporting authentication problems to the user.
        print("Failed with error \(error)");    
    }
   
    // Acquire token silently
    application.acquireToken(with: interactiveParameters, completionBlock: completionBlock)
 
    // or acquire it interactively.
    application.acquireTokenSilent(with: silentParameters, completionBlock: completionBlock)

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.

MSAL per iOS e macOS consente di richiedere attestazioni specifiche in scenari di acquisizione di token interattivi e invisibile all'utente.

Per richiedere attestazioni personalizzate, specificare claimsRequest in MSALSilentTokenParameters o MSALInteractiveTokenParameters.

Per altre informazioni, vedere Richiedere attestazioni personalizzate con MSAL per iOS e macOS .

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.

Passaggi successivi

Valutare la possibilità di abilitare la registrazione in MSAL per iOS/macOS per facilitare la diagnosi e il debug dei problemi.