Manipular erros e exceções no MSAL para iOS/macOS

Este artigo fornece uma visão geral dos diferentes tipos de erros e recomendações para lidar com erros comuns de entrada.

Noções básicas sobre o tratamento de erros do MSAL

As exceções no Biblioteca do Microsoft Authenticator (MSAL) destinam-se aos desenvolvedores de aplicativos a solucionar problemas, não para exibição para usuários finais. As mensagens de exceção não são localizadas.

Ao processar exceções e erros, você pode usar o tipo de exceção em si e o código de erro para distinguir entre exceções. Para obter uma lista de códigos de erro, consulte Microsoft Entra códigos de erro de autenticação e autorização.

Durante a experiência de entrada, você pode encontrar erros sobre consentimentos, MFA (Acesso Condicional, Gerenciamento de Dispositivos, restrições baseadas em local), emissão e resgate de token e propriedades do usuário.

A seção a seguir fornece mais detalhes sobre o tratamento de erros para seu aplicativo.

Tratamento de erros no MSAL para iOS/macOS

A lista completa de erros do MSAL para iOS e macOS está em MSALError enum.

Todos os erros gerados pela MSAL são retornados com o domínio MSALErrorDomain.

Para erros do sistema, a MSAL retorna o NSError original da API do sistema. Por exemplo, se a aquisição do token falhar devido à falta de conectividade de rede, a MSAL retorna um erro com o domínio NSURLErrorDomain e o código NSURLErrorNotConnectedToInternet.

Recomendamos que você trate, no cliente, pelo menos os dois erros do MSAL a seguir:

  • MSALErrorInteractionRequired: o usuário deve fazer uma solicitação interativa. Há muitas condições que podem levar a esse erro, como uma sessão de autenticação expirada ou a necessidade de requisitos de autenticação adicionais. Use a API interativa de aquisição de token do MSAL para se recuperar.

  • MSALErrorServerDeclinedScopes: Alguns ou todos os escopos foram recusados. Decida se deseja continuar apenas com os escopos concedidos ou interromper o processo de login.

Note

A MSALInternalError enumeração deve ser usada apenas para referência e depuração. Não tente lidar automaticamente com esses erros em runtime. Se o aplicativo encontrar qualquer um dos erros abaixo MSALInternalError, talvez você queira mostrar uma mensagem genérica voltada para o usuário explicando o que aconteceu.

Por exemplo, MSALInternalErrorBrokerResponseNotReceived significa que o usuário não concluiu a autenticação e retornou manualmente ao aplicativo. Nesse caso, seu aplicativo deve mostrar uma mensagem de erro genérica explicando que a autenticação não foi concluída e sugerir que eles tentem se autenticar novamente.

O código de exemplo Objective-C a seguir demonstra as práticas recomendadas para lidar com algumas condições de erro comuns.

    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)

Acesso condicional e desafio de declarações

Ao obter tokens silenciosamente, seu aplicativo pode receber mensagens de erro quando um questionamento de declarações de Acesso Condicional, como uma política de MFA, for exigido por uma API que você está tentando acessar.

O padrão para lidar com esse erro é adquirir interativamente um token usando MSAL. Isso solicita a participação do usuário e oferece a oportunidade para atender à política de acesso condicional exigida.

Em alguns casos, ao chamar uma API que exige o acesso condicional, você poderá receber um desafio de declarações no erro da API. Por exemplo, se a política de Acesso Condicional for ter um dispositivo gerenciado (Intune), o erro será algo como AADSTS53000: seu dispositivo precisa ser gerenciado para acessar esse recurso ou algo semelhante. Nesse caso, é possível transmitir as declarações na chamada do token de aquisição, de modo que o usuário precise cumprir a política apropriada.

A MSAL para iOS e macOS permite que você solicite declarações específicas em cenários de aquisição de token interativo e silencioso.

Para solicitar declarações personalizadas, especifique claimsRequest dentro MSALSilentTokenParameters ou MSALInteractiveTokenParameters.

Consulte Solicitar declarações personalizadas usando MSAL para iOS e macOS para obter mais informações.

Tentar novamente após erros e exceções

Você deve implementar suas políticas de repetição ao chamar a MSAL. A MSAL faz chamadas HTTP para o serviço Microsoft Entra e, ocasionalmente, podem ocorrer falhas. Por exemplo, a rede pode ficar inoperante ou o servidor está sobrecarregado.

HTTP 429

Quando o Servidor de Token de Serviço (STS) é sobrecarregado por solicitações em excesso, ele retorna o erro HTTP 429 com uma indicação de quanto tempo falta para que você possa tentar novamente no campo de resposta Retry-After.

Próximas Etapas 

Considere habilitar o Acesso no MSAL para iOS/macOS para ajudar a diagnosticar e depurar problemas.