Добавление проверки подлинности в приложение Xamarin.Android

Заметка

Этот продукт отставлен. Сведения о замене проектов с помощью .NET 8 или более поздней версии см. вбиблиотеке Community Toolkit Datasync.

В этом руководстве описано, как добавить проверку подлинности Майкрософт в проект TodoApp с помощью идентификатора Microsoft Entra. Перед выполнением этого руководства убедитесь, что вы создали проект и развернули серверную.

Кончик

Хотя мы используем идентификатор Microsoft Entra для проверки подлинности, вы можете использовать любую библиотеку проверки подлинности, которую вы хотите использовать с мобильными приложениями Azure.

Добавление проверки подлинности в серверную службу

Серверная служба — это стандартная служба ASP.NET 6. В любом руководстве показано, как включить проверку подлинности для службы ASP.NET 6, которая работает с мобильными приложениями Azure.

Чтобы включить проверку подлинности Microsoft Entra для серверной службы, необходимо:

  • Зарегистрируйте приложение с помощью идентификатора Microsoft Entra.
  • Добавьте проверку подлинности в проект серверной части ASP.NET 6.

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

Сначала зарегистрируйте веб-API в клиенте Microsoft Entra и добавьте область, выполнив следующие действия:

  1. Войдите на портал Azure .

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

  3. Найдите и выберите идентификатор Microsoft Entra ID.

  4. В разделе Управлениевыберите регистрации приложений>новой регистрации.

    • имя: введите имя приложения; например,краткого руководства todoApp . Пользователи приложения увидят это имя. Вы можете изменить его позже.
    • Поддерживаемые типы учетных записей: учетные записи в любом каталоге организации (любой каталог Microsoft Entra — Multitenant) и личных учетных записей Майкрософт (например, Skype, Xbox)
  5. Выберите Зарегистрировать.

  6. В разделе Управлениевыберите Предоставить API>Добавить область.

  7. Для URI идентификатора приложенияпримите значение по умолчанию, выбрав Сохранить и продолжить.

  8. Введите следующие сведения:

    • имени области :
    • Кто может согласиться?: администраторы и пользователи
    • отображаемое имя согласия администратора :
    • описания согласия администратора :
    • отображаемое имя согласия пользователя: Access TodoApp
    • описание согласия пользователя: Allow the app to access TodoApp on your behalf.
    • состояние: включено
  9. Выберите Добавить область, чтобы завершить добавление области.

  10. Обратите внимание на значение области, аналогичной api://<client-id>/access_as_user (называемой областью области веб-API). Вам нужна область при настройке клиента.

  11. Выберите Обзор.

  12. Обратите внимание на идентификатор приложения (клиента) в разделе Essentials (идентификатор приложения веб-API). Это значение необходимо для настройки серверной службы.

Откройте Visual Studio и выберите проект TodoAppService.NET6.

  1. Щелкните правой кнопкой мыши проект TodoAppService.NET6, а затем выберите Управление пакетами NuGet....

  2. На новой вкладке выберите Обзор, а затем введите Microsoft.Identity.Web в поле поиска.

    снимок экрана: добавление M S A L NuGet в Visual Studio.

  3. Выберите пакет Microsoft.Identity.Web, а затем нажмите Установить.

  4. Следуйте инструкциям, чтобы завершить установку пакета.

  5. Откройте Program.cs. Добавьте следующее в список операторов using:

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Identity.Web;
  1. Добавьте следующий код непосредственно над вызовом builder.Services.AddDbContext():
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
  .AddMicrosoftIdentityWebApi(builder.Configuration);
builder.Services.AddAuthorization();
  1. Добавьте следующий код непосредственно над вызовом app.MapControllers():
app.UseAuthentication();
app.UseAuthorization();

Теперь Program.cs должны выглядеть следующим образом:

using Microsoft.AspNetCore.Datasync;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Identity.Web;
using TodoAppService.NET6.Db;
  
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
  
if (connectionString == null)
{
  throw new ApplicationException("DefaultConnection is not set");
}
  
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
  .AddMicrosoftIdentityWebApi(builder.Configuration);
builder.Services.AddAuthorization();
builder.Services.AddDbContext<AppDbContext>(options => options.UseSqlServer(connectionString));
builder.Services.AddDatasyncControllers();
  
var app = builder.Build();
  
// Initialize the database
using (var scope = app.Services.CreateScope())
{
  var context = scope.ServiceProvider.GetRequiredService<AppDbContext>();
  await context.InitializeDatabaseAsync().ConfigureAwait(false);
}
  
// Configure and run the web service.
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
  1. Измените Controllers\TodoItemController.cs. Добавьте в класс атрибут [Authorize]. Класс должен выглядеть следующим образом:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Datasync;
using Microsoft.AspNetCore.Datasync.EFCore;
using Microsoft.AspNetCore.Mvc;
using TodoAppService.NET6.Db;

namespace TodoAppService.NET6.Controllers
{
  [Authorize]
  [Route("tables/todoitem")]
  public class TodoItemController : TableController<TodoItem>
  {
    public TodoItemController(AppDbContext context)
      : base(new EntityTableRepository<TodoItem>(context))
    {
    }
  }
}
  1. Измените appsettings.json. Добавьте следующий блок:
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com",
    "ClientId": "<client-id>",
    "TenantId": "common"
  },

Замените <client-id> идентификатором приложения веб-API , записанным ранее. После завершения он должен выглядеть следующим образом:

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com",
    "ClientId": "<client-id>",
    "TenantId": "common"
  },
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=TodoApp;Trusted_Connection=True"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*"
}

Опубликуйте службу в Azure еще раз:

  1. Щелкните правой кнопкой мыши проект TodoAppService.NET6, а затем выберите Опубликовать....
  2. Нажмите кнопку Опубликовать в правом верхнем углу вкладки.

Откройте браузер для https://yoursite.azurewebsites.net/tables/todoitem?ZUMO-API-VERSION=3.0.0. Обратите внимание, что служба теперь возвращает ответ 401, который указывает, что требуется проверка подлинности.

снимок экрана браузера с ошибкой.

Регистрация приложения в службе удостоверений

Платформа синхронизации данных Майкрософт имеет встроенную поддержку для любого поставщика проверки подлинности, использующего веб-токен Json (JWT) в заголовке транзакции HTTP. Это приложение использует библиотеку проверки подлинности Майкрософт (MSAL) для запроса такого маркера и авторизации пользователя, выполнившего вход в серверную службу.

Настройка собственного клиентского приложения

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

  1. На портале Azureвыберите Идентификатор Microsoft Entra ID>регистрации приложений>новой регистрации.

  2. На странице регистрация приложения:

    • Введите имени для регистрации приложения. Вы можете использовать имя native-quickstart, чтобы отличить его от имени, используемого серверной службой.
    • Выберите учетные записи в любом каталоге организации (любой каталог Microsoft Entra — Multitenant) и личных учетных записей Майкрософт (например, Skype, Xbox).
    • В URI перенаправления:
      • Выберите общедоступный клиент (мобильный & настольный компьютер)
      • Введите URL-адрес quickstart://auth
  3. Выберите Зарегистрировать.

  4. Выберите разрешения API>Добавить разрешение>мои API.

  5. Выберите регистрацию приложения, созданную ранее для серверной службы. Если вы не видите регистрацию приложения, убедитесь, что вы добавили область access_as_user.

    снимок экрана регистрации области на портале Azure.

  6. В разделе Выбор разрешенийвыберите access_as_user, а затем выберите Добавить разрешения.

  7. Выберите >мобильных и классических приложений проверки подлинности.

  8. Установите флажок рядом с https://login.microsoftonline.com/common/oauth2/nativeclient.

  9. Установите флажок рядом с msal{client-id}://auth (заменяя {client-id} идентификатором приложения).

  10. Выберите добавить URI, а затем добавьте http://localhost в поле для дополнительных URI.

  11. Выберите Сохранить в нижней части страницы.

  12. Выберите Обзор. Запишите идентификатор приложения (клиента), который называется идентификатором собственного клиентского приложения), так как это необходимо для настройки мобильного приложения.

Мы определили три URL-адреса перенаправления:

  • http://localhost используется приложениями WPF.
  • https://login.microsoftonline.com/common/oauth2/nativeclient используется приложениями UWP.
  • msal{client-id}://auth используется мобильными приложениями (Android и iOS).

Добавление клиента удостоверений Майкрософт в приложение

Откройте решение TodoApp.sln в Visual Studio и задайте проект TodoApp.Android в качестве запускаемого проекта. Добавьте библиотеки удостоверений Майкрософт (MSAL) в проект :

Добавьте библиотеки удостоверений Майкрософт (MSAL) в проект платформы:

  1. Щелкните проект правой кнопкой мыши, а затем выберите Управление пакетами NuGet....

  2. Перейдите на вкладку Обзор.

  3. Введите Microsoft.Identity.Client в поле поиска, а затем нажмите клавишу ВВОД.

  4. Выберите результат Microsoft.Identity.Client, а затем щелкните Установить.

    снимок экрана: выбор MSAL NuGet в Visual Studio.

  5. Примите лицензионное соглашение, чтобы продолжить установку.

Добавьте собственный идентификатор клиента и область серверной части в конфигурацию.

Откройте проект TodoApp.Data и измените файл Constants.cs. Добавьте константы для ApplicationId и Scopes:

  public static class Constants
  {
      /// <summary>
      /// The base URI for the Datasync service.
      /// </summary>
      public static string ServiceUri = "https://demo-datasync-quickstart.azurewebsites.net";

      /// <summary>
      /// The application (client) ID for the native app within Microsoft Entra ID
      /// </summary>
      public static string ApplicationId = "<client-id>";

      /// <summary>
      /// The list of scopes to request
      /// </summary>
      public static string[] Scopes = new[]
      {
          "<scope>"
      };
  }

Замените идентификатором собственного клиентского приложения при регистрации клиентского приложения в идентификаторе Microsoft Entra ID, а области веб-API, скопированной при использовании предоставления API при регистрации приложения-службы.

Откройте файл MainActivity.cs в проекте TodoApp.Android. В верхней части файла добавьте следующие инструкции using:

using Android.Content;
using Microsoft.Identity.Client;
using Microsoft.Datasync.Client;
using System.Linq;
using System.Threading.Tasks;
using Debug = System.Diagnostics.Debug;

В верхней части класса MainActivity добавьте следующее поле:

public IPublicClientApplication identityClient;

В методе OnCreate() измените определение TodoService:

TodoService = new RemoteTodoService(GetAuthenticationToken);

Добавьте следующий код, чтобы определить метод GetAuthenticationToken():

public async Task<AuthenticationToken> GetAuthenticationToken()
{
    if (identityClient == null)
    {
        identityClient = PublicClientApplicationBuilder.Create(Constants.ApplicationId)
            .WithAuthority(AzureCloudInstance.AzurePublic, "common")
            .WithRedirectUri($"msal{Constants.ApplicationId}://auth")
            .WithParentActivityOrWindow(() => this)
            .Build();
    }

    var accounts = await identityClient.GetAccountsAsync();
    AuthenticationResult result = null;
    bool tryInteractiveLogin = false;

    try
    {
        result = await identityClient
            .AcquireTokenSilent(Constants.Scopes, accounts.FirstOrDefault())
            .ExecuteAsync();
    }
    catch (MsalUiRequiredException)
    {
        tryInteractiveLogin = true;
    }
    catch (Exception ex)
    {
        Debug.WriteLine($"MSAL Silent Error: {ex.Message}");
    }

    if (tryInteractiveLogin)
    {
        try
        {
            result = await identityClient
                .AcquireTokenInteractive(Constants.Scopes)
                .ExecuteAsync()
                .ConfigureAwait(false);
        }
        catch (Exception ex)
        {
            Debug.WriteLine($"MSAL Interactive Error: {ex.Message}");
        }
    }

    return new AuthenticationToken
    {
        DisplayName = result?.Account?.Username ?? "",
        ExpiresOn = result?.ExpiresOn ?? DateTimeOffset.MinValue,
        Token = result?.AccessToken ?? "",
        UserId = result?.Account?.Username ?? ""
    };
}

Метод GetAuthenticationToken() работает с библиотекой удостоверений Майкрософт (MSAL), чтобы получить маркер доступа, подходящий для авторизации вошедшего пользователя в серверную службу. Затем эта функция передается в RemoteTodoService для создания клиента. Если проверка подлинности выполнена успешно, AuthenticationToken создается с данными, необходимыми для авторизации каждого запроса. Если нет, вместо этого создается неправильный маркер с истекшим сроком действия.

Обработайте обратный вызов из клиента удостоверений, добавив следующий метод:

protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
{
    base.OnActivityResult(requestCode, resultCode, data);
    // Return control to MSAL
    AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(requestCode, resultCode, data);
}

Создайте новый класс MsalActivity со следующим кодом:

using Android.App;
using Android.Content;
using Microsoft.Identity.Client;

namespace TodoApp.Android
{
    [Activity(Exported = true)]
    [IntentFilter(new[] { Intent.ActionView },
        Categories = new[] { Intent.CategoryBrowsable, Intent.CategoryDefault },
        DataHost = "auth",
        DataScheme = "msal{client-id}")]
    public class MsalActivity : BrowserTabActivity
    {
    }
}

Замените {client-id} идентификатором приложения собственного клиента (который совпадает с Constants.ApplicationId).

Если проект предназначен для Android версии 11 (API версии 30) или более поздней версии, необходимо обновить AndroidManifest.xml в соответствии с требованиями видимости пакета Android. Откройте Properties/AndroidManifest.xml и добавьте следующие узлы queries/intent на узел manifest:

<manifest>
  ...
  <queries>
    <intent>
      <action android:name="android.support.customtabs.action.CustomTabsService" />
    </intent>
  </queries>
</manifest>

Тестирование приложения

Запустите или перезапустите приложение.

Когда приложение запускается, браузер открывается, чтобы запросить проверку подлинности. Если вы еще не прошли проверку подлинности в приложении, приложение просит вас предоставить согласие. После завершения проверки подлинности системный браузер закрывается и приложение запускается как раньше.

Дальнейшие действия

Затем настройте приложение для работы в автономном режиме, реализации автономного хранилища.

Дальнейшее чтение