Guía de migración de ADAL a MSAL para Android

En este artículo se resaltan los cambios que debe realizar para migrar una aplicación que usa la biblioteca de autenticación de Azure Active Directory (ADAL) para usar el Biblioteca de autenticación de Microsoft (MSAL).

Resaltados de diferencia

ADAL funciona con el punto de conexión de Azure AD v1.0. La Biblioteca de autenticación de Microsoft (MSAL) funciona con la plataforma de identidad de Microsoft, anteriormente conocida como el punto de conexión de Azure AD v2.0. El Plataforma de identidad de Microsoft difiere de Azure AD v1.0 en que:

Compatible con:

  • Identidad organizativa (Microsoft Entra ID)

  • Identidades no organizativas, como Outlook.com, Xbox Live, etc.

  • (solo Azure AD B2C) Inicio de sesión federado con Google, Facebook, X y Amazon

  • Es compatible con los estándares:

    • OAuth v2.0
    • OpenID Connect (OIDC)

La API pública de MSAL presenta cambios importantes, entre los que se incluyen:

  • Un nuevo modelo para acceder a tokens:
    • ADAL proporciona acceso a tokens a través de AuthenticationContext, que representa el servidor. MSAL proporciona acceso a los tokens a través de PublicClientApplication, que representa el cliente. Los desarrolladores cliente no necesitan crear una nueva PublicClientApplication instancia para cada entidad con la que necesiten interactuar. Solo se requiere una PublicClientApplication configuración.
    • Compatibilidad para solicitar tokens de acceso mediante el uso de ámbitos además de identificadores de recursos.
    • Admite el consentimiento incremental. Los desarrolladores pueden solicitar ámbitos a medida que el usuario accede a más funcionalidades en la aplicación, incluidas las que no se incluyen durante el registro de la aplicación.
    • Las autoridades ya no se validan en tiempo de ejecución. En su lugar, el desarrollador declara una lista de "autoridades conocidas" durante el desarrollo.
  • Cambios en la API de token:
    • En ADAL, AcquireToken() primero realiza una solicitud silenciosa. Si eso falla, realiza una solicitud interactiva. Este comportamiento dio lugar a que algunos desarrolladores solo dependan de AcquireToken, lo que dio lugar a que el usuario se solicitara inesperadamente credenciales a veces. MSAL requiere que los desarrolladores decidan deliberadamente cuándo el usuario recibe un aviso de la interfaz de usuario.
      • AcquireTokenSilent siempre da lugar a una solicitud silenciosa que o bien se realiza correctamente o bien falla.
      • AcquireToken siempre genera una solicitud que muestra un aviso al usuario mediante la interfaz de usuario.
  • MSAL admite el inicio de sesión desde un explorador predeterminado o desde una vista web insertada:
    • De forma predeterminada, se usa el explorador predeterminado en el dispositivo. Esto permite a MSAL usar el estado de autenticación (cookies) que ya puedan estar presentes para una o varias cuentas que ya hayan iniciado sesión. Si no hay ningún estado de autenticación, autenticarse durante la autorización mediante MSAL hace que se cree un estado de autenticación (cookies) en beneficio de otras aplicaciones web que vayan a usarse en el mismo navegador.
  • Nuevo modelo de excepción:
    • Las excepciones definen con más claridad el tipo de error que se produjo y lo que el desarrollador debe hacer para resolverlo.
  • MSAL admite objetos de parámetros en las llamadas a AcquireToken y AcquireTokenSilent.
  • MSAL admite la configuración declarativa para:
    • Id. de cliente, URI de redirección.
    • Navegador integrado frente al navegador predeterminado
    • Autoridades
    • Ajustes HTTP, como los tiempos de espera de lectura y de conexión

Registro y migración de aplicaciones a MSAL

No es necesario cambiar el registro de la aplicación existente para usar MSAL. Si desea aprovechar el consentimiento incremental o progresivo, es posible que tenga que revisar el registro para identificar los ámbitos específicos que desea solicitar de forma incremental. A continuación encontrará más información sobre los ámbitos y el consentimiento incremental.

En el registro de la aplicación en el portal, verá una pestaña permisos de API . Esto proporciona una lista de las API y los permisos (ámbitos) a los que la aplicación está configurada actualmente para solicitar acceso. También muestra una lista de los nombres de ámbito asociados a cada permiso de API.

Con ADAL y el punto de conexión v1.0 de Azure AD, el usuario otorgaba su consentimiento para los recursos que poseía la primera vez que se usaban. Con MSAL y el Plataforma de identidad de Microsoft, se puede solicitar el consentimiento incrementalmente. El consentimiento incremental es útil para los permisos que un usuario puede considerar privilegios elevados o, de lo contrario, preguntar si no se proporciona una explicación clara de por qué se requiere el permiso. En ADAL, esos permisos pueden haber dado lugar a que el usuario abandone el inicio de sesión en la aplicación.

Tip

Use el consentimiento incremental para proporcionar contexto adicional a los usuarios sobre por qué la aplicación necesita un permiso.

Los administradores de la organización pueden dar su consentimiento a los permisos que requiere la aplicación en nombre de todos los miembros de su organización. Algunas organizaciones solo permiten a los administradores dar su consentimiento a las aplicaciones. El consentimiento del administrador requiere que incluya todos los permisos y ámbitos de API usados por la aplicación en el registro de la aplicación.

Tip

Aunque puedes solicitar un ámbito mediante MSAL para algo que no esté incluido en el registro de la aplicación, te recomendamos que actualices el registro de la aplicación para incluir todos los recursos y ámbitos a los que un usuario podría conceder permiso.

Migrar de identificadores de recursos a ámbitos

Autenticación y solicitud de autorización para todos los permisos en el primer uso

Si actualmente usa ADAL y no necesita usar el consentimiento incremental, la manera más sencilla de empezar a usar MSAL es realizar una acquireToken solicitud con el nuevo AcquireTokenParameter objeto y establecer el valor del identificador de recurso.

Cuidado

No es posible establecer ambos ámbitos y un identificador de recurso. Al intentar establecer ambos, se producirá la excepción IllegalArgumentException.

Esto dará lugar al mismo comportamiento de v1 al que está acostumbrado. Todos los permisos solicitados en el registro de la aplicación se solicitan al usuario durante su primera interacción.

Autenticación y solicitud de permisos solo según sea necesario

Para aprovechar el consentimiento incremental, haga una lista de permisos (ámbitos) que usa la aplicación desde el registro de la aplicación y organícelos en dos listas en función de:

  • Qué ámbitos desea solicitar durante la primera interacción del usuario con la aplicación durante el inicio de sesión.
  • Los permisos asociados a una característica importante de la aplicación que también tendrás que explicar al usuario.

Una vez que hayas organizado los alcances, organiza cada lista según el recurso (API) para el que quieras solicitar un token. También cualquier otro ámbito que desee que el usuario autorice al mismo tiempo.

El objeto parameters usado para realizar la solicitud a MSAL admite:

  • Scope: la lista de ámbitos para los que desea solicitar autorización y recibir un token de acceso.
  • ExtraScopesToConsent: una lista adicional de ámbitos para los que desea solicitar autorización mientras solicita un token de acceso para otro recurso. Esta lista de ámbitos le permite minimizar el número de veces que necesita solicitar autorización de usuario. Esto significa menos solicitudes de autorización o consentimiento del usuario.

Migración de AuthenticationContext a PublicClientApplications

Creación de PublicClientApplication

Cuando se usa MSAL, se crea una instancia de PublicClientApplication. Este objeto modela la identidad de la aplicación y se usa para realizar solicitudes a una o varias autoridades. Con este objeto, configurará la identidad del cliente, el URI de redirección, la autoridad predeterminada, si se debe usar el navegador del dispositivo en lugar de la vista web integrada, el nivel de registro y mucho más.

Puede configurar mediante declaración este objeto con JSON, que se proporciona como un archivo o como un recurso dentro del APK.

Aunque este objeto no es un singleton, internamente utiliza un Executors compartido tanto para las solicitudes interactivas como para las silenciosas.

Empresa a empresa

En ADAL, cada organización a la que solicita tokens de acceso requiere una instancia independiente de AuthenticationContext. En MSAL, ya no es un requisito. Puede especificar la autoridad desde la que desea solicitar un token como parte de la solicitud silenciosa o interactiva.

Migrar de la validación de autoridades a autoridades conocidas

MSAL no tiene una marca para habilitar o deshabilitar la validación de la autoridad. La validación de autoridad es una característica de ADAL y, en las primeras versiones de MSAL, que impide que el código solicite tokens de una autoridad potencialmente malintencionada. MSAL ahora recupera una lista de autoridades conocidas para Microsoft y combina esa lista con las autoridades especificadas en la configuración.

Tip

Si es un usuario de Azure empresa a consumidor (B2C), esto significa que ya no tiene que deshabilitar la validación de la autoridad. En su lugar, incluya cada una de las directivas de Azure AD B2C compatibles como autoridades en la configuración de MSAL. Tenga en cuenta que a partir del 1 de mayo de 2025, Azure AD B2C ya no estará disponible para su compra por parte de nuevos clientes. Para más información, consulte ¿Azure AD B2C sigue estando disponible para la compra? en nuestras preguntas más frecuentes.

Si intenta usar una autoridad que Microsoft no reconoce y que no está incluida en su configuración, obtendrá un UnknownAuthorityException.

Logging

Ahora puede configurar el registro mediante declaración como parte de la configuración, de la siguiente manera:

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

Migración de UserInfo a cuenta

En ADAL, AuthenticationResult proporciona un UserInfo objeto que se usa para recuperar información sobre la cuenta autenticada. El término "usuario", que significaba un agente de software o humano, se aplicó de una manera que dificultaba la comunicación de que algunas aplicaciones admiten un solo usuario (ya sea un agente humano o de software) que tiene varias cuentas.

Considere una cuenta bancaria. Puede tener más de una cuenta en más de una institución financiera. Al abrir una cuenta, usted (el usuario) tiene credenciales emitidas, como una tarjeta ATM & PIN, que se usan para acceder a su saldo, pagos de facturación, etc., para cada cuenta. Esas credenciales solo se pueden usar en la institución financiera que las emitió.

Por analogía, como las cuentas de una institución financiera, se accede a las cuentas de la Plataforma de identidad de Microsoft mediante credenciales. Esas credenciales se registran con o se emiten mediante Microsoft. O por Microsoft en nombre de una organización.

Donde el Plataforma de identidad de Microsoft difiere de una institución financiera, en esta analogía, es que el Plataforma de identidad de Microsoft proporciona un marco que permite a un usuario usar una cuenta y sus credenciales asociadas, acceder a los recursos que pertenecen a varias personas y organizaciones. Esto es como poder usar una tarjeta emitida por un banco, en otra institución financiera. Esto funciona porque todas las organizaciones en cuestión usan el Plataforma de identidad de Microsoft, lo que permite usar una cuenta en varias organizaciones. Este es un ejemplo:

Sam funciona para Contoso.com, pero administra Azure máquinas virtuales que pertenecen a Fabrikam.com. Para que Sam administre las máquinas virtuales de Fabrikam, debe estar autorizado para acceder a ellas. Para conceder este acceso, agregue la cuenta de Sam a Fabrikam.com y conceda a su cuenta un rol que le permita trabajar con las máquinas virtuales. Esto se haría con el portal de Azure.

Agregar la cuenta de Contoso.com de Sam como miembro de Fabrikam.com daría lugar a la creación de un nuevo registro en la Microsoft Entra ID de Fabrikam.com para Sam. El registro de Sam en Microsoft Entra ID se conoce como un objeto de usuario. En este caso, ese objeto de usuario apuntaría al objeto de usuario de Sam en Contoso.com. El objeto de usuario fabrikam de Sam es la representación local de Sam y se usaría para almacenar información sobre la cuenta asociada a Sam en el contexto de Fabrikam.com. En Contoso.com, el título de Sam es consultor sénior de DevOps. En Fabrikam, el título de Sam es Contractor-Virtual Machines. En Contoso.com, Sam no es responsable ni autorizado para administrar máquinas virtuales. En Fabrikam.com, esa es su única función de trabajo. Pero Sam sigue teniendo un único conjunto de credenciales del que hacer seguimiento: las credenciales emitidas por Contoso.com.

Una vez que se haya realizado correctamente una llamada acquireToken, verá una referencia a un objeto IAccount que se puede usar en solicitudes acquireTokenSilent posteriores.

IMultiTenantAccount

Si tiene una aplicación que tiene acceso a las notificaciones de una cuenta de cada uno de los inquilinos en los que la cuenta está representada, puede convertir los objetos IAccount en IMultiTenantAccount. Esta interfaz proporciona un mapa de ITenantProfiles, con una clave por identificador de inquilino, que permite acceder a las notificaciones que pertenecen a la cuenta en cada uno de los inquilinos a los que ha solicitado un token, en relación con la cuenta actual.

Las notificaciones en la raíz de IAccount y IMultiTenantAccount siempre contienen las notificaciones del inquilino principal. Si aún no ha realizado una solicitud para un token dentro del inquilino principal, esta colección estará vacía.

Otros cambios

Usa la nueva 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);
}

Migración a las nuevas excepciones

En ADAL, hay un tipo de excepción, AuthenticationException, que incluye un método para recuperar el valor de la enumeración ADALError. En MSAL, hay una jerarquía de excepciones y cada una tiene su propio conjunto de códigos de error específicos asociados.

Exception Description
MsalArgumentException Se genera si uno o varios argumentos de entrada no son válidos.
MsalClientException Se lanza si el error es del cliente.
MsalDeclinedScopeException Se produce si el servidor rechazó uno o varios ámbitos solicitados.
MsalException Excepción comprobada predeterminada producida por MSAL.
MsalIntuneAppProtectionPolicyRequiredException Se produce si el recurso tiene habilitada la directiva de protección de MAMCA.
MsalServiceException Se lanza si el error es del lado del servidor.
MsalUiRequiredException Se produce si el token no se puede actualizar de forma silenciosa.
MsalUserCancelException Se produce si el usuario canceló el flujo de autenticación.

Traducción de ADALError a MsalException

Si detecta estos errores en ADAL... … detecte estas excepciones de MSAL:
No hay ningún 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
No hay ningún ADALError equivalente MsalDeclinedScopeException
  • ADALError.APP_PACKAGE_NAME_NOT_FOUND
  • ADALError.BROKER_APP_VERIFICATION_FAILED
  • ADALError.PACKAGE_NAME_NOT_FOUND
MsalException
No existe ningún ADALError equivalente MsalIntuneAppProtectionPolicyRequiredException
  • ADALError.SERVER_ERROR
  • ADALError.SERVER_INVALID_REQUEST
MsalServiceException
  • ADALError.AUTH_REFRESH_FAILED_PROMPT_NOT_ALLOWED
MsalUiRequiredException
No hay ningún ADALError equivalente MsalUserCancelException

Registro de ADAL a registro de 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
}