Руководство по миграции ADAL в MSAL для Android

В этой статье описываются изменения, которые необходимо внести, чтобы перенести приложение, которое использует библиотеку аутентификации Майкрософт Azure Active Directory (ADAL) в библиотеку проверки подлинности (MSAL).

Основные различия

ADAL работает с конечной точкой Azure AD версии 1.0. Библиотека проверки подлинности Майкрософт (MSAL) работает с платформа удостоверений Майкрософт, ранее известной как конечная точка Azure AD версии 2.0. Платформа Microsoft Identity отличается от Azure AD версии 1.0 тем, что:

Поддерживаемые возможности и компоненты:

  • Удостоверение организации (идентификатор Microsoft Entra)

  • Другие (неорганизационные) удостоверения, такие как Outlook.com, Xbox Live и т. д.

  • Только Azure AD B2C: федеративный вход с Google, Facebook, Twitter и Amazon

  • Совместима со стандартами:

    • OAuth v2.0
    • OpenID Connect (OIDC)

Общедоступный API-интерфейс MSAL содержит важные изменения, включая перечисленные ниже.

  • Новая модель для доступа к маркерам:
    • ADAL предоставляет доступ к маркерам через объект AuthenticationContext, представляющий сервер. MSAL предоставляет доступ к маркерам через объект PublicClientApplication, представляющий клиента. Разработчикам клиентов не нужно создавать новый экземпляр PublicClientApplication для каждого центра авторизации, с которым им требуется взаимодействовать. Требуется только одна конфигурация PublicClientApplication.
    • Поддержка запроса маркеров доступа с использованием областей в дополнение к идентификаторам ресурсов.
    • Поддержка добавочного согласия. Разработчики могут запрашивать области по мере того, как пользователю требуются всё новые функции приложения, включая те, которые не были добавлены во время его регистрации.
    • Центры авторизации больше не проверяются во время выполнения. Вместо этого разработчик объявляет список известных центров в ходе разработки.
  • Изменения API маркеров:
    • В ADAL AcquireToken() сначала выполняет автоматический запрос. В случае неудачи выполняется интерактивный запрос. Это вело к тому, что некоторые разработчики полагались только на метод AcquireToken, вследствие чего у пользователя запрашивались учетные данные в неожиданные моменты. При использовании MSAL разработчики должны выдавать все запросы на ввод данных осознанным образом.
      • Вариант AcquireTokenSilent всегда означает автоматический запрос, который завершается либо успешно, либо ошибкой.
      • Вариант AcquireToken всегда означает запрос для ввода данных через пользовательский интерфейс.
  • MSAL поддерживает вход из браузера по умолчанию или внедренного веб-представления:
    • По умолчанию используется текущий стандартный браузер на устройстве. Это позволяет MSAL использовать состояние проверки подлинности (файлы cookie), которые могут уже быть в одной или нескольких учетных записях, выполнивших вход. Если состояние проверки подлинности отсутствует, проверка подлинности при авторизации через MSAL приводит к созданию такого состояния (файлов cookie), и эти данные затем могут использовать другие веб-приложения в том же браузере.
  • Новая модель исключений:
    • В исключениях более четко определены тип возникшей ошибки и действия, которые разработчик должен выполнить для ее устранения.
  • MSAL поддерживает объекты параметров для вызовов AcquireToken и AcquireTokenSilent.
  • MSAL поддерживает декларативную конфигурацию для:
    • Идентификатор клиента, URI перенаправления.
    • Встроенный браузер или браузер по умолчанию.
    • Полномочия
    • Параметры HTTP, такие как время ожидания чтения и подключения.

Регистрация и перенос приложения в MSAL

Для перехода на MSAL изменять регистрацию существующего приложения не требуется. Если вы планируете использовать добавочное или прогрессивное согласие, вам может потребоваться внести в регистрацию изменения и указать конкретные области для добавочных запросов. Дополнительные сведения об областях и добавочном согласии приведены ниже.

В параметрах регистрации приложения на портале вы увидите вкладку Разрешения API. Здесь приведен список API-интерфейсов и разрешений (областей), к которым ваше приложение сейчас может запрашивать доступ. Здесь также отображается список имен областей, связанных с каждым разрешением API.

С помощью ADAL и конечной точки Azure AD версии 1.0 пользователю было предоставлено согласие на ресурсы, которыми они владеет, при первом использовании. При использовании MSAL и платформы удостоверений Майкрософт разрешения можно запрашивать постепенно. Добавочное согласие можно использовать для разрешений, которые пользователи предоставляют менее охотно или для которых требуется четко разъяснить цели. В ADAL пользователь в таких случаях мог просто отказаться от входа в приложение.

Совет

Добавочное согласие позволяет предоставить пользователям дополнительные сведения о том, зачем приложению требуется то или иное разрешение.

Администраторы организаций могут давать согласие на разрешения, которые требуются вашему приложению, от имени всех сотрудников своей организации. В некоторых организациях согласие на приложения разрешено давать только администраторам. Чтобы получить согласие администратора, необходимо указать при регистрации приложения все используемые им разрешения и области API.

Совет

Хотя вы можете запросить с помощью MSAL область, не указанную при регистрации, рекомендуется обновить параметры регистрации приложения и добавить в них все ресурсы и области, на которые пользователь может предоставлять разрешения.

Переход с идентификаторов ресурсов на области

Проверка подлинности и запрос авторизации для всех разрешений при первом использовании

Если вы используете ADAL и не планируете применять добавочное согласие, самый простой способ перейти на MSAL — создать запрос acquireToken с помощью нового объекта AcquireTokenParameter и задать значение идентификатора ресурса.

Внимание

Задать сразу область и идентификатор ресурса нельзя: попытка указать и то, и другое приведет к исключению IllegalArgumentException.

В результате все будет работать так же, как в версии 1, которую вы уже используете. Все разрешения, запрошенные при регистрации приложения, запрашиваются у пользователя в момент первого взаимодействия с ним.

Проверка подлинности и запрос разрешений только по мере необходимости

Чтобы воспользоваться возможностями добавочного согласия, создайте список разрешений (областей), которые использует ваше приложение, при его регистрации, и сформируйте два отдельных списка:

  • Области, которые должны запрашиваться во время первого взаимодействия пользователя с приложением в момент входа.
  • Разрешения, связанные с важной функцией приложения, смысл которых необходимо разъяснить пользователю.

Составив два списка областей, систематизируйте каждый из них по ресурсам (API), для которых потребуется маркер. Также укажите все прочие области, для которых сразу потребуется авторизация пользователя.

Объект параметров, используемый для запроса к MSAL, поддерживает:

  • Scope: список областей, для которых потребуется запросить авторизацию и получить маркер доступа.
  • ExtraScopesToConsent: дополнительный список областей, для которых потребуется запросить авторизацию при запросе маркера доступа для другого ресурса. Этот список позволяет свести к минимуму число запросов авторизации у пользователя. Это, в свою очередь, сокращает число запросов согласия у пользователя.

Переход с AuthenticationContext на PublicClientApplications

Создание PublicClientApplication

При использовании MSAL создается экземпляр PublicClientApplication. Этот объект представляет удостоверение приложения и используется для выполнения запросов к одному или нескольким центрам авторизации. С помощью этого объекта настраиваются удостоверение клиента, URI перенаправления, центр авторизации по умолчанию, использование браузера устройства или встроенного веб-представление, уровень ведения журнала и многое другое.

Этот объект можно настроить декларативно с помощью кода JSON, предоставляемого в виде файла или хранимого в качестве ресурса в APK.

Хотя этот объект не является отдельным, он использует общий ресурс Executors как для интерактивных, так и для автоматических запросов.

Взаимодействие по схеме "бизнес-бизнес"

В ADAL каждой организации, для которой запрашиваются маркеры доступа, требуется отдельный экземпляр AuthenticationContext. В MSAL это больше не требуется. Можно указать центр авторизации, у которого требуется запросить маркер в рамках автоматического или интерактивного запроса.

Переход с проверки центра авторизации на известные центры

В MSAL нет флага для включения или отключения проверки центра авторизации. Проверка центра авторизации — это функция ADAL, а также ранних выпусков MSAL, которая не позволяет коду запрашивать маркеры у потенциально вредоносного центра. MSAL получает список центров авторизации, известных корпорации Майкрософт, и объединяет его со списком центров, указанным в вашей конфигурации.

Совет

Если вы являетесь пользователем Azure Business to Consumer (B2C), это означает, что вам больше не нужно отключать проверку центров авторизации. Вместо этого добавьте все поддерживаемые вами политики Azure AD B2C в качестве центров авторизации в конфигурацию MSAL.

Если вы попытаетесь использовать центр авторизации, который не известен корпорации Майкрософт и не входит в конфигурацию, вы получите исключение UnknownAuthorityException.

Ведение журнала

Теперь вы можете декларативным образом настроить ведение журнала в своей конфигурации. Например:

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

Переход с UserInfo на Account

В ADAL в AuthenticationResult есть объект UserInfo, используемый для получения сведений об учетной записи, прошедшей проверку подлинности. Термин "пользователь", обозначавший человека или программный агент, затруднял понимание того факта, что некоторые приложения поддерживают возможность для одного пользователя (или программного агента) иметь несколько учетных записей.

Представьте себе банковский счет. У вас может быть больше одного счета в нескольких финансовых учреждениях. При открытии счета вам (пользователю) выдаются реквизиты, такие как банковская карта и PIN-код, которые вы используете для доступа к своему балансу, оплаты счетов и т. д. по каждому счету. Эти реквизиты можно использовать только в финансовом учреждении, в котором они были выпущены.

По аналогии, доступ к учетным записям на платформе удостоверений Майкрософт, как и к счетам в финансовом учреждении, осуществляется с помощью учетных данных. Эти учетные данные регистрируются в корпорации Майкрософт или выдаются ею. Майкрософт также может делать это от имени организации.

Отличие платформы удостоверений Майкрософт от финансового учреждения заключается в том, чтоб платформа удостоверений Майкрософт позволяет пользователю с помощью одной учетной записи и связанных с нею учетных данных обращаться к ресурсам, относящимся к нескольким физическим лицам и организациям. Это похоже на возможность использования кредитной карты, выданной одним банком, в другом финансовом учреждении. Это возможно потому, что все рассматриваемые организации работают на платформе удостоверений Майкрософт, что позволяет использовать одну учетную запись в нескольких организациях. Приведем пример:

Семен работает в компании Contoso.com, но управляет виртуальными машинами Azure, принадлежащими компании Fabrikam.com. Чтобы Семен мог управлять виртуальными машинами Fabrikam, ему необходимы права на доступ к ним. Чтобы обеспечить ему такой доступ, нужно добавить учетную запись Семена в систему Fabrikam.com и предоставить ей роль, которая позволяет работать с виртуальными машинами. Эту задачу можно выполнить на портале Azure.

Добавление учетной записи Contoso.com Sam в качестве члена Fabrikam.com приведет к созданию новой записи в Fabrikam.com Идентификатор Microsoft Entra для Sam. Запись Sam в идентификаторе Microsoft Entra называется объектом пользователя. В этом случае данный объект пользователя будет указывать на объект пользователя Семена в системе Contoso.com. Объект пользователя Семена в системе Fabrikam является его локальным представлением, и в нем хранится информация о связанной с Семеном учетной записи в контексте Fabrikam.com. В Contoso.com у Семена должность старшего консультанта по DevOps. В системе Fabrikam его роль — подрядчик по управлению виртуальными машинами. В Contoso.com Семен не несет ответственности за управление виртуальными машинами и не имеет на это необходимых разрешений. В Fabrikam.com это его единственная обязанность. При этом у Семена всего один набор учетных данных, выданных в системе Contoso.com.

После успешного вызова к acquireToken вы получите ссылку на объект IAccount, которую можно использовать в последующих запросах acquireTokenSilent.

IMultiTenantAccount

Если у вас есть приложение, обращающееся к утверждениям учетной записи из каждого арендатора, в котором она представлена, вы можете приводить объекты IAccount к типу IMultiTenantAccount. Этот интерфейс представляет карту профилей ITenantProfiles с ключами в виде идентификаторов арендаторов, которая обеспечивает доступ к утверждениям, связанным с учетной записью в каждом арендаторе, у которого вы запросили маркер, относительно текущей учетной записи.

Утверждения в корне IAccount и IMultiTenantAccount всегда содержат утверждения из домашнего арендатора. Если вы еще не отправляли запрос для получения маркера в домашнем арендаторе, эта коллекция будет пустой.

Другие изменения

Использование нового метода 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);
}

Переход на новые исключения

В ADAL существует один тип исключения — AuthenticationException, в котором есть метод для получения значения перечисления ADALError. В MSAL есть целая иерархия исключений, у каждого из которых собственный набор связанных кодов ошибки.

Исключение Description
MsalArgumentException Возникает, если один или несколько входных аргументов являются недопустимыми.
MsalClientException Возникает при наличии ошибки на стороне клиента.
MsalDeclinedScopeException Возникает, если одна или несколько запрошенных областей были отклонены сервером.
MsalException Исключение по умолчанию, инициируемое MSAL.
MsalIntuneAppProtectionPolicyRequiredException Возникает, если для ресурса включена политика защиты MAMCA.
MsalServiceException Возникает при наличии ошибки на стороне сервера.
MsalUiRequiredException Возникает, если не удается обновить маркер автоматически.
MsalUserCancelException Возникает, если пользователь отменил поток проверки подлинности.

Перевод ADALError в MsalException

Ошибки, перехватываемые в ADAL Эквивалентные исключения MSAL
Эквивалентной ошибки ADALError нет 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
Эквивалентной ошибки ADALError нет MsalDeclinedScopeException
  • ADALError.APP_PACKAGE_NAME_NOT_FOUND
  • ADALError.BROKER_APP_VERIFICATION_FAILED
  • ADALError.PACKAGE_NAME_NOT_FOUND
MsalException
Эквивалентной ошибки ADALError нет MsalIntuneAppProtectionPolicyRequiredException
  • ADALError.SERVER_ERROR
  • ADALError.SERVER_INVALID_REQUEST
MsalServiceException
  • ADALError.AUTH_REFRESH_FAILED_PROMPT_NOT_ALLOWED
MsalUiRequiredException
Эквивалентной ошибки ADALError нет MsalUserCancelException

Переход с журналов ADAL на журналы 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
}