Migrar aplicações para MSAL para iOS e macOS

A Biblioteca de Autenticação Azure Active Directory (ADAL Objective-C) foi criada para trabalhar com contas Microsoft Entra através do endpoint v1.0.

A Biblioteca de Autenticação da Microsoft para iOS and macOS (MSAL) foi construída para funcionar com todas as identidades da Microsoft, como contas Microsoft Entra, contas pessoais da Microsoft e contas B2C do Azure AD através do plataforma de identidades da Microsoft (anteriormente o endpoint Azure AD v2.0).

A plataforma de identidades da Microsoft apresenta algumas diferenças importantes em relação ao Azure AD v1.0. Este artigo destaca estas diferenças e fornece orientações para migrar uma aplicação de ADAL para MSAL.

Diferenças de capacidades entre aplicações ADAL e MSAL

Quem pode iniciar sessão

  • A ADAL apenas suporta contas de trabalho e escola — também conhecidas como contas Microsoft Entra.
  • O MSAL suporta contas Microsoft pessoais (contas MSA) como Hotmail.com, Outlook.com e Live.com.
  • O MSAL suporta contas de trabalho e escola, e contas B2C do Azure AD.

Conformidade com as normas

  • A plataforma de identidades da Microsoft segue os padrões OAuth 2.0 e OpenId Connect.
  • A plataforma de identidades da Microsoft permite-lhe pedir permissões de forma dinâmica. As apps só podem pedir permissões quando necessário e pedir mais à medida que a app precisa. Para mais informações, consulte permissões e consentimento.

Diferenças entre bibliotecas ADAL e MSAL

A API pública MSAL reflete algumas diferenças-chave entre o Azure AD v1.0 e a plataforma de identidades da Microsoft.

MSALPublicClientApplication em vez de ADAuthenticationContext

ADAuthenticationContext é o primeiro objeto criado por uma aplicação ADAL. Representa uma instância da ADAL. As aplicações criam uma nova instância de ADAuthenticationContext para cada combinação de nuvem Microsoft Entra e inquilino (autoridade). O mesmo ADAuthenticationContext pode ser usado para obter tokens para múltiplas aplicações clientes públicas.

No MSAL, a principal interação é através de um MSALPublicClientApplication objeto, que é modelado a partir do Cliente Público OAuth 2.0. Uma instância de MSALPublicClientApplication pode ser usada para interagir com múltiplas nuvens e inquilinos do Microsoft Entra, sem ser necessário criar uma nova instância para cada autoridade. Para a maioria das aplicações, uma MSALPublicClientApplication instância é suficiente.

Escopos em vez de recursos

No ADAL, uma aplicação tinha de fornecer um identificador de recurso, como https://graph.microsoft.com para adquirir tokens do endpoint Azure AD v1.0. Um recurso pode definir, no manifesto da aplicação, vários escopos, ou oAuth2Permissions, que reconhece. Isto permitia que as aplicações clientes solicitassem tokens desse recurso para um determinado conjunto de escopos pré-definidos durante o registo da aplicação.

No MSAL, em vez de um único identificador de recurso, as aplicações fornecem um conjunto de escopos por pedido. Um escopo é um identificador de recurso seguido do nome da permissão na forma recurso/permissão. Por exemplo, https://graph.microsoft.com/user.read

Existem duas formas de especificar âmbitos no MSAL:

  • Forneça uma lista de todas as permissões que a sua aplicação necessita. Por exemplo:

    @[@"https://graph.microsoft.com/directory.read", @"https://graph.microsoft.com/directory.write"]

    Neste caso, a aplicação solicita as permissões directory.read e directory.write. O utilizador será solicitado a consentir nessas permissões caso não tenha consentido antes para esta aplicação. A aplicação pode também receber permissões adicionais às quais o utilizador já consentiu para a aplicação. O utilizador só será solicitado a consentir para novas permissões, ou permissões que não foram concedidas.

  • O âmbito /.default.

Este é o âmbito incorporado para cada aplicação. Refere-se à lista estática de permissões configuradas quando a aplicação foi registada. O seu comportamento é semelhante ao de resource. Isto pode ser útil na migração para garantir que um conjunto semelhante de escopos e experiência do utilizador é mantido.

Para usar o /.default escopo, anexe /.default ao identificador de recurso. Por exemplo: https://graph.microsoft.com/.default. Se o seu recurso terminar com uma barra oblíqua (/), deve ainda acrescentar /.default, incluindo a barra oblíqua inicial, resultando num âmbito que contém uma barra oblíqua dupla (//).

Pode ler mais informações sobre o uso do âmbito "/.default" nas permissões e escopos.

Suporte a diferentes tipos de WebView e navegadores

O ADAL só suporta UIWebView/WKWebView para iOS e WebView para macOS. O MSAL para iOS suporta mais opções para exibir conteúdo web ao solicitar um código de autorização, e já não suporta UIWebView; o que pode melhorar a experiência do utilizador e a segurança.

Por defeito, o MSAL no iOS utiliza o ASWebAuthenticationSession, que é o componente web recomendado pela Apple para autenticação em dispositivos iOS 12+. Oferece benefícios de login único (SSO) através da partilha de cookies entre aplicações e o navegador Safari.

Pode optar por usar um componente web diferente dependendo dos requisitos da aplicação e da experiência do utilizador final que pretende. Consulte os tipos de web view suportados para mais opções.

Ao migrar de ADAL para MSAL, WKWebView proporciona a experiência de utilizador mais semelhante à do ADAL no iOS e macOS. Encorajamo-lo a migrar para ASWebAuthenticationSession no iOS, se possível. Para macOS, encorajamo-lo a usar WKWebView.

Diferenças na API de gestão de contas

Quando chama os métodos ADAL acquireToken() ou acquireTokenSilent(), recebe um objeto ADUserInformation que contém uma lista de afirmações do id_token que representa a conta que está a ser autenticada. Além disso, ADUserInformation devolve uma userId com base na declaração upn. Após a aquisição inicial do token interativo, a ADAL espera que o programador forneça userId em todas as chamadas silenciosas.

O ADAL não fornece uma API para recuperar identidades de utilizadores conhecidas. Depende da aplicação para guardar e gerir essas contas.

A MSAL fornece um conjunto de APIs para listar todas as contas conhecidas pela MSAL sem necessidade de adquirir um token.

Tal como o ADAL, o MSAL devolve informações sobre a conta que contêm uma lista de declarações provenientes de id_token. Faz parte do MSALAccount objeto dentro do MSALResult objeto.

A MSAL fornece um conjunto de APIs para remover contas, tornando as contas removidas inacessíveis à aplicação. Após a remoção da conta, chamadas posteriores de aquisição de tokens pedem ao utilizador que faça uma aquisição interativa de tokens. A remoção de conta aplica-se apenas à aplicação cliente que a iniciou, e não remove a conta das outras aplicações a correr no dispositivo ou do navegador do sistema. Isto garante que o utilizador continua a ter uma experiência SSO no dispositivo mesmo após sair de uma aplicação individual.

Além disso, o MSAL também devolve um identificador de conta que pode ser usado para solicitar um token silenciosamente mais tarde. No entanto, o identificador da conta (acessível através da identifier propriedade no MSALAccount objeto) não é exibível e não se pode assumir em que formato está, nem se deve tentar interpretá-lo ou analisá-lo.

Migração da cache da conta

Ao migrar do ADAL, as aplicações normalmente armazenam o userId do ADAL, que não tem o identifier exigido pelo MSAL. Como etapa de migração única, uma aplicação pode consultar uma conta MSAL usando o userId da ADAL com a seguinte API:

- (nullable MSALAccount *)accountForUsername:(nonnull NSString *)username error:(NSError * _Nullable __autoreleasing * _Nullable)error;

Esta API lê as caches do MSAL e do ADAL para encontrar a conta pelo userId do ADAL (UPN).

Se a conta for encontrada, o programador deve usá-la para fazer aquisição silenciosa de tokens. A primeira aquisição silenciosa de tokens irá efetivamente atualizar a conta, e o programador obterá um identificador de conta compatível com MSAL no resultado MSAL (identifier). Depois disso, só identifier deve ser usado para consultas de contas, utilizando a seguinte API:

- (nullable MSALAccount *)accountForIdentifier:(nonnull NSString *)identifier error:(NSError * _Nullable __autoreleasing * _Nullable)error;

Embora seja possível continuar a usar ADAL userId para todas as operações em MSAL, como userId é baseado em UPN, está sujeito a múltiplas limitações que resultam numa má experiência de utilizador. Por exemplo, se o UPN mudar, o utilizador tem de iniciar sessão novamente. Recomendamos que todas as aplicações utilizem a conta identifier não visível para todas as operações.

Leia mais sobre a migração do estado da cache.

Alterações na aquisição de tokens

A MSAL introduz algumas alterações nas calls de aquisição de tokens:

  • Tal como o ADAL, acquireTokenSilent resulta sempre num pedido silencioso.
  • Ao contrário do ADAL, acquireToken resulta sempre numa interface acionável para o utilizador, seja através da web view ou da aplicação Microsoft Authenticator. Dependendo do estado do SSO dentro do webview/Microsoft Authenticator, o utilizador pode ser solicitado a introduzir as suas credenciais.
  • No ADAL, acquireToken com AD_PROMPT_AUTO tenta primeiro adquirir tokens em silêncio e só apresenta a interface de utilizador se o pedido em silêncio falhar. No MSAL, esta lógica pode ser conseguida começando por chamar acquireTokenSilent e chamando acquireToken apenas se a aquisição silenciosa falhar. Isto permite aos programadores personalizar a experiência do utilizador antes de iniciar a aquisição interativa de tokens.

Diferenças no tratamento de erros

O MSAL proporciona mais clareza entre erros que podem ser tratados pela sua aplicação e aqueles que requerem intervenção do utilizador. Existem um número limitado de erros que o programador deve gerir:

  • MSALErrorInteractionRequired: O utilizador deve fazer um pedido interativo. Isto pode ser causado por várias razões, como uma sessão de autenticação expirada, a política de Acesso Condicional alterada, um token de atualização expirou ou foi revogado, não existem tokens válidos na cache, e assim sucessivamente.
  • MSALErrorServerDeclinedScopes: O pedido não foi totalmente concluído e algumas áreas não tiveram acesso concedido. Isto pode ser causado por um utilizador recusar consentimento para um ou mais escopes.

Tratar de todos os outros erros na MSALError lista é opcional. Pode usar a informação desses erros para melhorar a experiência do utilizador.

Consulte Gestão de exceções e erros usando MSAL para mais informações sobre o tratamento de erros MSAL.

Apoio aos corretores

O MSAL, a partir da versão 0.3.0, oferece suporte para autenticação intermediada através da aplicação Microsoft Authenticator. O Microsoft Authenticator também permite suporte para cenários de Acesso Condicional. Exemplos de cenários de Acesso Condicional incluem políticas de conformidade com dispositivos que exigem que o utilizador inscreva o dispositivo através do Intune ou se registe com o Microsoft Entra ID para obter um token. E políticas de Acesso Condicional de Gestão de Aplicações Móveis (MAM), que exigem prova de conformidade antes de a sua aplicação poder obter um token.

Para ativar o broker na sua aplicação:

  1. Registe um formato URI de redirecionamento compatível com o corretor para a aplicação. O formato URI de redirecionamento compatível com o broker é msauth.<app.bundle.id>://auth. Substitua <app.bundle.id> pelo ID do pacote da sua aplicação. Se estás a migrar do ADAL e a tua aplicação já era compatível com broker, não há mais nada que precises de fazer. O teu URI de redirecionamento anterior é totalmente compatível com MSAL, por isso podes saltar para o passo 3.

  2. Adicione o esquema de URI de redirecionamento da sua aplicação ao seu ficheiro info.plist. Para o URI de redirecionamento MSAL padrão, o formato é msauth.<app.bundle.id>. Por exemplo:

    <key>CFBundleURLSchemes</key>
    <array>
        <string>msauth.<app.bundle.id></string>
    </array>
    
  3. Adicione os seguintes esquemas ao ficheiro Info.plist da sua aplicação, sob a chave LSApplicationQueriesSchemes:

    <key>LSApplicationQueriesSchemes</key>
    <array>
         <string>msauthv2</string>
         <string>msauthv3</string>
    </array>
    
  4. Adicione o seguinte ao seu ficheiro AppDelegate.m para gerir callbacks: Objective-C:

    - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options`
    {
        return [MSALPublicClientApplication handleMSALResponse:url sourceApplication:options[UIApplicationOpenURLOptionsSourceApplicationKey]];
    }
    

    Swift

    func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
        return MSALPublicClientApplication.handleMSALResponse(url, sourceApplication: options[UIApplication.OpenURLOptionsKey.sourceApplication] as? String)
    }
    

Empresa-empresa (B2B)

No ADAL, criam-se instâncias separadas de ADAuthenticationContext para cada locatário para o qual a aplicação pede tokens. Isto já não é um requisito no MSAL. No MSAL, pode criar uma única instância de MSALPublicClientApplication e utilizá-la para qualquer nuvem e organização do Microsoft Entra, ao especificar uma autoridade diferente para as chamadas a acquireToken e acquireTokenSilent.

SSO em parceria com outros SDKs

O MSAL para iOS permite SSO por meio de cache unificada com o ADAL Objective-C 2.7.x+.

O SSO é conseguido através da partilha de chaves no iOS e só está disponível entre aplicações publicadas a partir da mesma conta Apple Developer.

A partilha de SSO através do keychain do iOS é o único tipo de SSO silencioso.

No macOS, o MSAL consegue alcançar SSO com outros MSAL para aplicações baseadas em iOS e macOS e aplicações ADAL baseadas em Objective-C.

O MSAL no iOS também suporta outros dois tipos de SSO:

  • SSO pelo navegador. O MSAL para iOS suporta ASWebAuthenticationSession, que fornece SSO através de cookies partilhados entre outras aplicações no dispositivo e, especificamente, o navegador Safari.
  • SSO através de um broker de autenticação. Num dispositivo iOS, o Microsoft Authenticator atua como intermediário de autenticação. Pode seguir políticas de Acesso Condicional, como exigir um dispositivo compatível, e fornece SSO para dispositivos registados. Os SDKs da MSAL, a partir da versão 0.3.0, suportam um broker por defeito.

Intune MAM SDK

O SDK MAM do Intune suporta MSAL para iOS a partir da versão 11.1.2

MSAL e ADAL na mesma aplicação

A versão 2.7.0 do ADAL e superiores não pode coexistir com o MSAL na mesma aplicação. A principal razão é o código comum dos submódulos partilhados. Como Objective-C não suporta namespaces, se adicionares tanto frameworks ADAL como MSAL à tua aplicação, haverá duas instâncias da mesma classe. Não há garantia de qual será escolhido em tempo de execução. Se ambos os SDKs estiverem a usar a mesma versão da classe em conflito, a sua aplicação pode continuar a funcionar. No entanto, se for uma versão diferente, a sua aplicação pode ter crashes inesperados difíceis de diagnosticar.

A execução do ADAL e do MSAL na mesma aplicação em produção não é suportada. No entanto, se estiveres apenas a testar e a migrar os teus utilizadores do ADAL Objective-C para MSAL para iOS e macOS, podes continuar a usar o ADAL Objective-C 2.6.10. É a única versão que funciona com MSAL na mesma aplicação. Não haverá novas atualizações de funcionalidades para esta versão ADAL, pelo que deve ser usada apenas para fins de migração e testes. A tua aplicação não deve depender da coexistência entre ADAL e MSAL a longo prazo.

A coexistência entre ADAL e MSAL na mesma aplicação não é suportada. A coexistência entre ADAL e MSAL entre múltiplas aplicações é totalmente suportada.

Passos práticos de migração

Migração de registo de aplicações

Não precisa de alterar a sua aplicação Microsoft Entra existente para mudar para MSAL e ativar contas Microsoft Entra. No entanto, se a sua aplicação baseada em ADAL não suportar autenticação intermediária, terá de registar um novo URI de redirecionamento para a aplicação antes de poder mudar para MSAL.

O URI de redirecionamento deve estar neste formato: msauth.<app.bundle.id>://auth. Substitua <app.bundle.id> pelo ID do pacote da sua aplicação. Especifique o URI de redirecionamento no centro de administração Microsoft Entra.

Para iOS apenas, para suportar autenticação baseada em certificados, é necessário registar um URI de redirecionamento adicional na sua aplicação e no centro de administração Microsoft Entra no seguinte formato: msauth://code/<broker-redirect-uri-in-url-encoded-form>. Por exemplo, msauth://code/msauth.com.microsoft.mybundleId%3A%2F%2Fauth

Recomendamos que todas as aplicações registem ambos os URI de redirecionamento.

Se desejar adicionar suporte para consentimento incremental, selecione as APIs e permissões que a sua aplicação está configurada para solicitar acesso no registo da sua aplicação, no separador de permissões da API .

Se estás a migrar do ADAL e queres suportar tanto o Microsoft Entra ID como as contas MSA, o registo da tua aplicação atual precisa de ser atualizado para suportar ambos. Não recomendamos que atualize imediatamente a sua aplicação de produção existente para suportar tanto o Microsoft Entra ID como o MSA. Em vez disso, crie outro ID de cliente que suporte tanto o Microsoft Entra ID como o MSA para testes e, depois de verificares que todos os cenários funcionam, atualiza a aplicação existente.

Adicione MSAL à sua aplicação

Pode adicionar o MSAL SDK à sua aplicação usando a sua ferramenta preferida de gestão de pacotes. Consulte as instruções detalhadas aqui.

Atualize o ficheiro Info.plist da sua aplicação

Apenas para iOS, adicione o esquema de URI de redirecionamento da sua aplicação ao ficheiro info.plist. Para aplicações compatíveis com o broker ADAL, já deverá estar presente. O esquema predefinido de URI de redirecionamento MSAL estará no formato: msauth.<app.bundle.id>.

<key>CFBundleURLSchemes</key>
<array>
    <string>msauth.<app.bundle.id></string>
</array>

Adicione os seguintes esquemas ao Info.plist da sua aplicação em LSApplicationQueriesSchemes.

<key>LSApplicationQueriesSchemes</key>
<array>
     <string>msauthv2</string>
     <string>msauthv3</string>
</array>

Atualize o seu código AppDelegate

Apenas para iOS, adicione o seguinte ao seu ficheiro AppDelegate.m:

Objectivo-C:

- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options`
{
    return [MSALPublicClientApplication handleMSALResponse:url sourceApplication:options[UIApplicationOpenURLOptionsSourceApplicationKey]];
}

Swift

func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
    return MSALPublicClientApplication.handleMSALResponse(url, sourceApplication: options[UIApplication.OpenURLOptionsKey.sourceApplication] as? String)
}

Se estiveres a usar Xcode 11, deves colocar o callback MSAL no SceneDelegate ficheiro em vez disso. Se suportar tanto UISceneDelegate como UIApplicationDelegate para compatibilidade com versões mais antigas do iOS, o callback do MSAL precisará ser colocado em ambos os arquivos.

Objectivo-C:

 - (void)scene:(UIScene *)scene openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts
 {
     UIOpenURLContext *context = URLContexts.anyObject;
     NSURL *url = context.URL;
     NSString *sourceApplication = context.options.sourceApplication;
     
     [MSALPublicClientApplication handleMSALResponse:url sourceApplication:sourceApplication];
 }

Swift

func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
        
        guard let urlContext = URLContexts.first else {
            return
        }
        
        let url = urlContext.url
        let sourceApp = urlContext.options.sourceApplication
        
        MSALPublicClientApplication.handleMSALResponse(url, sourceApplication: sourceApp)
    }

Isto permite que a MSAL trate das respostas do corretor e do componente web. Isto não era necessário no ADAL, pois "swizza" automaticamente os métodos de delegação da aplicação. Adicioná-lo manualmente é menos propenso a erros e dá mais controlo à aplicação.

Habilitar cache de token

Por predefinição, o MSAL guarda os tokens da sua aplicação na cache do porta-chaves do iOS ou do macOS.

Para ativar a cache de tokens:

  1. Certifique-se de que a sua candidatura está devidamente assinada
  2. Vá às definições do projeto Xcode >separador Capacidades>Ative a Partilha de porta-chaves
  3. Clique + e introduza a seguinte entrada em Grupos do Porta-chaves: 3.a Para iOS, introduza com.microsoft.adalcache 3.b Para macOS, introduza com.microsoft.identity.universalstorage

Crie a MSALPublicClientApplication e passe a utilizar as chamadas acquireToken e acquireTokenSilent

Pode criar MSALPublicClientApplication usando o seguinte código:

Objectivo-C:

NSError *error = nil;
MSALPublicClientApplicationConfig *configuration = [[MSALPublicClientApplicationConfig alloc] initWithClientId:@"<your-client-id-here>"];
    
MSALPublicClientApplication *application =
[[MSALPublicClientApplication alloc] initWithConfiguration:configuration
                                                     error:&error];

Swift

let config = MSALPublicClientApplicationConfig(clientId: "<your-client-id-here>")
do {
  let application = try MSALPublicClientApplication(configuration: config)
  // continue on with application
            
} catch let error as NSError {
  // handle error here
}

Depois liga para a API de gestão de contas para ver se há contas na cache:

Objectivo-C:

NSString *accountIdentifier = nil /*previously saved MSAL account identifier */;
NSError *error = nil;
MSALAccount *account = [application accountForIdentifier:accountIdentifier error:&error];

Swift

// definitions that need to be initialized
let application: MSALPublicClientApplication!
let accountIdentifier: String! /*previously saved MSAL account identifier */

do {
  let account = try application.account(forIdentifier: accountIdentifier)
  // continue with account usage
} catch let error as NSError {
  // handle error here
}

Ou leia todos os relatos:

Objectivo-C:

NSError *error = nil;
NSArray<MSALAccount *> *accounts = [application allAccounts:&error];

Swift

let application: MSALPublicClientApplication!
do {
  let accounts = try application.allAccounts()
  // continue with account usage
} catch let error as NSError {
  // handle error here
}

Se for encontrada uma conta, ligue para a API MSAL acquireTokenSilent :

Objectivo-C:

MSALSilentTokenParameters *silentParameters = [[MSALSilentTokenParameters alloc] initWithScopes:@[@"<your-resource-here>/.default"] account:account];
    
[application acquireTokenSilentWithParameters:silentParameters
                              completionBlock:^(MSALResult *result, NSError *error)
{
    if (result)
    {
        NSString *accessToken = result.accessToken;
        // Use your token
    }
    else
    {
        // Check the error
        if ([error.domain isEqual:MSALErrorDomain] && error.code == MSALErrorInteractionRequired)
        {
            // Interactive auth will be required
        }
            
        // Other errors may require trying again later, or reporting authentication problems to the user
    }
}];

Swift

let application: MSALPublicClientApplication!
let account: MSALAccount!
        
let silentParameters = MSALSilentTokenParameters(scopes: ["<your-resource-here>/.default"], 
                                                 account: account)
application.acquireTokenSilent(with: silentParameters) {
  (result: MSALResult?, error: Error?) in
  if let accessToken = result?.accessToken {
     // use accessToken
  }
  else {
    // Check the error
    guard let error = error else {
      assert(true, "callback should contain a valid result or error")
      return
    }
    
    let nsError = error as NSError
    if (nsError.domain == MSALErrorDomain
        && nsError.code == MSALError.interactionRequired.rawValue) {
      // Interactive auth will be required
    }
                
    // Other errors may require trying again later, or reporting authentication problems to the user
  }
}

Passos seguintes

Saiba mais sobre fluxos de autenticação e cenários de aplicação