Guia de migração de ADAL para MSAL para Android

Este artigo destaca as alterações que precisa de fazer para migrar uma aplicação que utiliza a Azure Active Directory Authentication Library (ADAL) para utilizar a Biblioteca de Autenticação da Microsoft (MSAL).

Destaques das diferenças

O ADAL funciona com o endpoint Azure AD v1.0. A Biblioteca de Autenticação da Microsoft (MSAL) funciona com a plataforma de identidades da Microsoft, anteriormente conhecida como endpoint Azure AD v2.0. A plataforma de identidades da Microsoft difere do Azure AD v1.0 porque:

Suporta:

  • Identidade Organizacional (Microsoft Entra ID)

  • Identidades não organizacionais como Outlook.com, Xbox Live, e assim por diante

  • (Apenas Azure AD B2C) Login federado com Google, Facebook, X e Amazon

  • Os padrões são compatíveis com:

    • OAuth v2.0
    • OpenID Connect (OIDC)

A API pública MSAL introduz mudanças importantes, incluindo:

  • Um novo modelo para aceder a tokens:
    • O ADAL fornece acesso a tokens através do AuthenticationContext, que representa o servidor. A MSAL fornece acesso a tokens através do PublicClientApplication, que representa o cliente. Os programadores clientes não precisam de criar uma nova PublicClientApplication instância para cada Autoridade com a qual precisam de interagir. Só é necessária uma PublicClientApplication configuração.
    • Suporte para solicitar tokens de acesso usando escopos além de identificadores de recursos.
    • Suporte para consentimento incremental. Os programadores podem solicitar escopos à medida que o utilizador acede a mais funcionalidades na aplicação, incluindo aquelas que não estão incluídas durante o registo da aplicação.
    • As autoridades já não são validadas em tempo de execução. Em vez disso, o promotor declara uma lista de 'autoridades conhecidas' durante o desenvolvimento.
  • Alterações na API de tokens:
    • Na ADAL, AcquireToken() primeiro faz um pedido silencioso. Caso contrário, faz um pedido interativo. Este comportamento levou alguns programadores a depender apenas de AcquireToken, o que resultou em que o utilizador fosse inesperadamente solicitado a obter credenciais por vezes. O MSAL exige que os programadores sejam intencionais quanto ao momento em que o utilizador recebe um prompt de interface.
      • AcquireTokenSilent resulta sempre num pedido silencioso que ou tem sucesso ou falha.
      • AcquireToken resulta sempre num pedido apresentado ao utilizador através da IU.
  • O MSAL suporta iniciar sessão a partir de um navegador predefinido ou de uma vista web embutida:
    • Por defeito, é utilizado o navegador predefinido do dispositivo. Isto permite que a MSAL utilize o estado de autenticação (cookies) que poderá já estar presente para uma ou mais contas com sessão iniciada. Se não houver estado de autenticação presente, autenticar durante a autorização via MSAL resulta na criação de estados de autenticação (cookies) para benefício de outras aplicações web que serão usadas no mesmo navegador.
  • Novo modelo de exceção:
    • As exceções definem de forma mais clara o tipo de erro que ocorreu e o que o programador precisa de fazer para o resolver.
  • O MSAL suporta objetos de parâmetros nas chamadas a AcquireToken e AcquireTokenSilent.
  • O MSAL suporta configuração declarativa para:
    • ID do cliente, URI de redirecionamento.
    • Navegador Embutido vs Navegador Padrão
    • Autoridades
    • Definições HTTP, como o tempo limite de leitura e de ligação

Registo e migração da sua aplicação para MSAL

Não precisas de alterar o registo da tua aplicação para usar MSAL. Se quiser tirar partido do consentimento incremental/progressivo, poderá ser necessário rever o registo para identificar os âmbitos específicos que pretende solicitar de forma progressiva. Seguem-se mais informações sobre os âmbitos e o consentimento incremental.

No registo da sua aplicação no portal, verá um separador Permissões de API. Aí encontrará uma lista das APIs e permissões (âmbitos) às quais a sua aplicação está atualmente configurada para solicitar acesso. Também mostra uma lista dos nomes de âmbito associados a cada permissão da API.

Com o ADAL e o endpoint Azure AD v1.0, o consentimento do utilizador para os recursos que possuía era concedido na primeira utilização. Com a MSAL e a plataforma de identidades da Microsoft, o consentimento pode ser solicitado de forma incremental. O consentimento incremental é útil para permissões que um utilizador pode considerar de alto privilégio, ou pode questionar se não for fornecida uma explicação clara do motivo pelo qual a permissão é necessária. No ADAL, essas permissões podem ter levado o utilizador a abandonar o processo de iniciar sessão na sua aplicação.

Dica

Use consentimento incremental para fornecer contexto adicional aos seus utilizadores sobre porque é que a sua aplicação precisa de uma permissão.

Os administradores da organização podem consentir as permissões necessárias para a sua candidatura em nome de todos os membros da organização. Algumas organizações só permitem que administradores consintam com candidaturas. O consentimento do administrador exige que inclua todas as permissões e escopos da API usados pela sua aplicação no registo da aplicação.

Dica

Embora possa solicitar um âmbito usando MSAL para algo que não esteja incluído no registo da sua aplicação, recomendamos que atualize o registo da sua aplicação para incluir todos os recursos e scopes a que um utilizador possa conceder permissão.

Migrar de IDs de recursos para âmbitos

Autenticar e pedir autorização para todas as permissões na primeira utilização

Se estiveres a usar ADAL e não precisares de usar consentimento incremental, a forma mais simples de começar a usar MSAL é fazer um acquireToken pedido usando o novo AcquireTokenParameter objeto e definir o valor do ID do recurso.

Atenção

Não é possível definir ambos os escopos e um ID de recurso. Tentar definir ambos resultará num IllegalArgumentException.

Isto vai resultar no mesmo comportamento v1 a que estás habituado. Todas as permissões solicitadas no registo da sua aplicação são solicitadas ao utilizador durante a sua primeira interação.

Autentique e solicite permissões apenas quando necessário

Para tirar partido do consentimento incremental, faça uma lista de permissões (escopos) que a sua aplicação utiliza a partir do registo da aplicação e organize-as em duas listas baseadas em:

  • Que âmbitos pretende solicitar durante a primeira interação do utilizador com a sua aplicação ao iniciar sessão.
  • As permissões associadas a uma funcionalidade importante da sua aplicação que também terá de explicar ao utilizador.

Depois de organizares os escopos, organiza cada lista pelo recurso (API) para o qual queres pedir um token. Assim como quaisquer outros escopos que queiras que o utilizador autorize ao mesmo tempo.

O objeto de parâmetros usado para fazer o seu pedido ao MSAL suporta:

  • Scope: A lista de escopos para os quais pretende pedir autorização e receber um token de acesso.
  • ExtraScopesToConsent: Uma lista adicional de escopos para os quais pretende pedir autorização enquanto solicita um token de acesso para outro recurso. Esta lista de escopos permite-lhe minimizar o número de vezes que precisa de solicitar autorização de utilizador. O que significa menos pedidos de autorização ou consentimento dos utilizadores.

Migrar de AuthenticationContext para PublicClientApplications

Construção da PublicClientApplication

Quando usas MSAL, instancias um PublicClientApplication. Este objeto modela a identidade da sua aplicação e é usado para fazer pedidos a uma ou mais autoridades. Com este objeto, irá configurar a identidade do cliente, o URI de redirecionamento, a autoridade predefinida, se deve utilizar o navegador do dispositivo ou a vista Web incorporada, o nível de registo e muito mais.

Pode configurar declarativamente este objeto com JSON, que fornece como ficheiro ou armazena como recurso dentro do seu APK.

Embora este objeto não seja um singleton, internamente utiliza shared Executors tanto para pedidos interativos como silenciosos.

Empresa para Empresa

No ADAL, cada organização à qual solicita tokens de acesso requer uma instância separada do AuthenticationContext. No MSAL, isto já não é um requisito. Pode especificar a autoridade à qual pretende pedir um token como parte do seu pedido silencioso ou interativo.

Migrar da validação de autoridade para autoridades conhecidas

MSAL não tem uma opção para ativar ou desativar a validação da autoridade. A validação de autoridade é uma funcionalidade no ADAL, e nas primeiras versões do MSAL, que impede que o seu código solicite tokens a uma autoridade potencialmente maliciosa. A MSAL recupera agora uma lista de autoridades conhecidas pela Microsoft e funde essa lista com as autoridades que especificou na sua configuração.

Dica

Se for utilizador do Azure Business to Consumer (B2C), isso significa que já não precisa de desativar a validação de autoridade. Em vez disso, inclua cada uma das suas políticas B2C do Azure AD suportadas como autoridades na sua configuração MSAL. Por favor, note que, a partir de 1 de maio de 2025, o Azure AD B2C deixará de estar disponível para compra por novos clientes. Para saber mais, consulte O Azure AD B2C ainda está disponível para compra? na nossa FAQ.

Se tentar usar uma autoridade que não é conhecida pela Microsoft e que não está incluída na sua configuração, receberá um UnknownAuthorityException.

Logging

Agora pode configurar declarativamente o registo como parte da sua configuração, assim:

"logging": {
  "pii_enabled": false,
  "log_level": "WARNING",
  "logcat_enabled": true
}

Migrar do UserInfo para a Conta

No ADAL, o AuthenticationResult fornece um objeto UserInfo utilizado para obter informações sobre a conta autenticada. O termo "utilizador", que significava um humano ou agente de software, foi aplicado de forma a dificultar a comunicação de que algumas aplicações suportam um único utilizador (seja humano ou agente de software) que tem múltiplas contas.

Considere uma conta bancária. Pode ter mais do que uma conta em mais do que uma instituição financeira. Quando abre uma conta, você (o utilizador) recebe credenciais, como um Cartão ATM e um PIN, que são usadas para aceder ao seu saldo, pagamentos de contas, etc., para cada conta. Essas credenciais só podem ser usadas na instituição financeira que as emitiu.

Por analogia, tal como as contas numa instituição financeira, as contas na plataforma de identidades da Microsoft são acedidas usando credenciais. Essas credenciais são registadas ou emitidas pela Microsoft. Ou pela Microsoft em nome de uma organização.

Onde a plataforma de identidades da Microsoft difere de uma instituição financeira, nesta analogia, é que a plataforma de identidades da Microsoft fornece um quadro que permite a um utilizador usar uma conta, e as suas credenciais associadas, para aceder a recursos que pertencem a múltiplos indivíduos e organizações. Isto é como poder usar um cartão emitido por um banco, noutra instituição financeira. Isto funciona porque todas as organizações em questão utilizam a plataforma de identidades da Microsoft, que permite que uma conta seja usada entre várias organizações. Eis um exemplo:

O Sam trabalha para Contoso.com mas gere Azure máquinas virtuais que pertencem a Fabrikam.com. Para o Sam gerir as máquinas virtuais da Fabrikam, precisa de estar autorizado a aceder a elas. Este acesso pode ser concedido adicionando a conta do Sam à Fabrikam.com e concedendo à sua conta um papel que lhe permite trabalhar com as máquinas virtuais. Isto seria feito através do portal Azure.

Adicionar a conta Contoso.com de Sam como membro em Fabrikam.com resultaria na criação de um novo registo no Microsoft Entra ID de Fabrikam.com para Sam. O registo do Sam no Microsoft Entra ID é conhecido como objeto utilizador. Neste caso, esse objeto de utilizador remeteria para o objeto de utilizador do Sam em Contoso.com. O objeto de utilizador Fabrikam do Sam é a representação local do Sam e seria usado para armazenar informação sobre a conta associada ao Sam no contexto do Fabrikam.com. Em Contoso.com, o título do Sam é Consultor Sénior DevOps. Na Fabrikam, o cargo do Sam é Prestador de Serviços - Máquinas Virtuais. Em Contoso.com, Sam não é responsável nem autorizado a gerir máquinas virtuais. Em Fabrikam.com, essa é a sua única função profissional. No entanto, Sam ainda só tem um conjunto de credenciais para controlar, que são as credenciais emitidas por Contoso.com.

Assim que for efetuada uma chamada acquireToken bem-sucedida, verá uma referência a um objeto IAccount que pode ser utilizado em pedidos acquireTokenSilent subsequentes.

IMultiTenantAccount

Se tiver uma aplicação que acede a declarações relativas a uma conta em cada um dos locatários em que essa conta está representada, pode converter os objetos IAccount em IMultiTenantAccount. Esta interface disponibiliza um mapa de ITenantProfiles, indexado pelo ID do tenant, que lhe permite aceder às declarações associadas à conta em cada um dos tenants dos quais pediu um token, relativamente à conta atual.

As reivindicações na raiz do IAccount e IMultiTenantAccount contêm sempre as reivindicações do inquilino da casa. Se ainda não tiver feito um pedido de um token no tenant de origem, esta coleção estará vazia.

Outras alterações

Utilize o novo AuthenticationCallback

// Existing ADAL Interface
public interface AuthenticationCallback<T> {

    /**
     * This will have the token info.
     *
     * @param result returns <T>
     */
    void onSuccess(T result);

    /**
     * Sends error information. This can be user related error or server error.
     * Cancellation error is AuthenticationCancelError.
     *
     * @param exc return {@link Exception}
     */
    void onError(Exception exc);
}
// New Interface for Interactive AcquireToken
public interface AuthenticationCallback {

    /**
     * Authentication finishes successfully.
     *
     * @param authenticationResult {@link IAuthenticationResult} that contains the success response.
     */
    void onSuccess(final IAuthenticationResult authenticationResult);

    /**
     * Error occurs during the authentication.
     *
     * @param exception The {@link MsalException} contains the error code, error message and cause if applicable. The exception
     *                  returned in the callback could be {@link MsalClientException}, {@link MsalServiceException}
     */
    void onError(final MsalException exception);

    /**
     * Will be called if user cancels the flow.
     */
    void onCancel();
}

// New Interface for Silent AcquireToken
public interface SilentAuthenticationCallback {

    /**
     * Authentication finishes successfully.
     *
     * @param authenticationResult {@link IAuthenticationResult} that contains the success response.
     */
    void onSuccess(final IAuthenticationResult authenticationResult);

    /**
     * Error occurs during the authentication.
     *
     * @param exception The {@link MsalException} contains the error code, error message and cause if applicable. The exception
     *                  returned in the callback could be {@link MsalClientException}, {@link MsalServiceException} or
     *                  {@link MsalUiRequiredException}.
     */
    void onError(final MsalException exception);
}

Migrar para as novas exceções

No ADAL, existe um tipo de exceção, AuthenticationException, que inclui um método para recuperar o ADALError valor de enum. No MSAL, existe uma hierarquia de exceções, e cada uma tem o seu próprio conjunto de códigos de erro específicos associados.

Exception Description
MsalArgumentException Lançado se um ou mais argumentos de entrada forem inválidos.
MsalClientException Lançado se o erro for do lado do cliente.
MsalDeclinedScopeException Lançado se um ou mais âmbitos solicitados tiverem sido recusados pelo servidor.
MsalException Exceção verificada por defeito lançada pelo MSAL.
MsalIntuneAppProtectionPolicyRequiredException Descartado se o recurso tiver a política de proteção MAMCA ativada.
MsalServiceException É lançado se o erro for do lado do servidor.
MsalUiRequiredException Lançado se o token não puder ser atualizado silenciosamente.
MsalUserCancelException É lançado se o utilizador cancelou o fluxo de autenticação.

Tradução de ADALError para MsalException

Se estás a detetar estes erros no ADAL... ... Veja estas exceções do MSAL:
Não há ADALError equivalente MsalArgumentException
  • ADALError.ANDROIDKEYSTORE_FAILED
  • ADALError.AUTH_FAILED_USER_MISMATCH
  • ADALError.DECRYPTION_FAILED
  • ADALError.DEVELOPER_AUTHORITY_CAN_NOT_BE_VALIDED
  • ADALError.DEVELOPER_AUTHORITY_IS_NOT_VALID_INSTANCE
  • ADALError.DEVELOPER_AUTHORITY_IS_NOT_VALID_URL
  • ADALError.DEVICE_CONNECTION_IS_NOT_AVAILABLE
  • ADALError.DEVICE_NO_SUCH_ALGORITHM
  • ADALError.ENCODING_IS_NOT_SUPPORTED
  • ADALError.ENCRYPTION_ERROR
  • ADALError.IO_EXCEPTION
  • ADALError.JSON_PARSE_ERROR
  • ADALError.NO_NETWORK_CONNECTION_POWER_OPTIMIZATION
  • ADALError.SOCKET_TIMEOUT_EXCEPTION
MsalClientException
Não há ADALError equivalente MsalDeclinedScopeException
  • ADALError.APP_PACKAGE_NAME_NOT_FOUND
  • ADALError.BROKER_APP_VERIFICATION_FAILED
  • ADALError.PACKAGE_NAME_NOT_FOUND
MsalException
Não há ADALError equivalente MsalIntuneAppProtectionPolicyRequiredException
  • ADALError.SERVER_ERROR
  • ADALError.SERVER_INVALID_REQUEST
MsalServiceException
  • ADALError.AUTH_REFRESH_FAILED_PROMPT_NOT_ALLOWED
MsalUiRequiredException
Não há ADALError equivalente MsalUserCancelException

Registo ADAL para Registo MSAL

// Legacy Interface
    StringBuilder logs = new StringBuilder();
    Logger.getInstance().setExternalLogger(new ILogger() {
            @Override
            public void Log(String tag, String message, String additionalMessage, LogLevel logLevel, ADALError errorCode) {
                logs.append(message).append('\n');
            }
        });
// New interface
  StringBuilder logs = new StringBuilder();
  Logger.getInstance().setExternalLogger(new ILoggerCallback() {
      @Override
      public void log(String tag, Logger.LogLevel logLevel, String message, boolean containsPII) {
          logs.append(message).append('\n');
      }
  });

// New Log Levels:
public enum LogLevel
{
    /**
     * Error level logging.
     */
    ERROR,
    /**
     * Warning level logging.
     */
    WARNING,
    /**
     * Info level logging.
     */
    INFO,
    /**
     * Verbose level logging.
     */
    VERBOSE
}