Поделиться через


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

Заметка

Этот продукт отставлен. Сведения о замене проектов с помощью .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.MAUI в качестве запускаемого проекта. Добавьте библиотеки удостоверений Майкрософт (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 при регистрации приложения-службы.

Откройте класс MainPage.xaml.cs в проекте TodoApp.MAUI. Добавьте следующие операторы using:

using Microsoft.Datasync.Client;
using Microsoft.Identity.Client;
using System.Diagnostics;

В классе MainPage добавьте новое свойство:

public IPublicClientApplication IdentityClient { get; set; }

Настройте конструктор для чтения:

public MainPage()
{
    InitializeComponent();
    TodoService = new RemoteTodoService(GetAuthenticationToken);
    viewModel = new MainViewModel(this, TodoService);
    BindingContext = viewModel;
}

Добавьте метод GetAuthenticationToken в класс:

public async Task<AuthenticationToken> GetAuthenticationToken()
{
    if (IdentityClient == null)
    {
#if ANDROID
        IdentityClient = PublicClientApplicationBuilder
            .Create(Constants.ApplicationId)
            .WithAuthority(AzureCloudInstance.AzurePublic, "common")
            .WithRedirectUri($"msal{Constants.ApplicationId}://auth")
            .WithParentActivityOrWindow(() => Platform.CurrentActivity)
            .Build();
#elif IOS
        IdentityClient = PublicClientApplicationBuilder
            .Create(Constants.ApplicationId)
            .WithAuthority(AzureCloudInstance.AzurePublic, "common")
            .WithIosKeychainSecurityGroup("com.microsoft.adalcache")
            .WithRedirectUri($"msal{Constants.ApplicationId}://auth")
            .Build();
#else
        IdentityClient = PublicClientApplicationBuilder
            .Create(Constants.ApplicationId)
            .WithAuthority(AzureCloudInstance.AzurePublic, "common")
            .WithRedirectUri("https://login.microsoftonline.com/common/oauth2/nativeclient")
            .Build();
#endif
    }

    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();
        }
        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 создается с данными, необходимыми для авторизации каждого запроса. Если нет, вместо этого создается неправильный маркер с истекшим сроком действия.

Мы можем добавить любые параметры для конкретной платформы, используя области #if с описателями платформы. Например, Android требует указать родительское действие, которое передается на вызывающую страницу.

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

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

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

namespace TodoApp.MAUI
{
    [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. Откройте Platforms/Android/AndroidManifest.xml и добавьте следующие узлы queries/intent на узел manifest:

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

Откройте MauiProgram.cs. Включите следующие using инструкции в верхней части файла:

using Microsoft.Identity.Client;

Обновите построитель до следующего кода:

    builder
        .UseMauiApp<App>()
        .ConfigureLifecycleEvents(events =>
        {
#if ANDROID
            events.AddAndroid(platform =>
            {
                platform.OnActivityResult((activity, rc, result, data) =>
                {
                    AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(rc, result, data);
                });
            });
#endif
        })
        .ConfigureFonts(fonts =>
        {
            fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
            fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
        });

Если вы выполняете этот шаг после обновления приложения для iOS, добавьте код, указанный #if ANDROID (включая #if и #endif). Компилятор выбирает правильный фрагмент кода на основе скомпилированной платформы. Этот код можно поместить либо до, либо после существующего блока для iOS.

Когда Android требует проверки подлинности, он получает клиент удостоверений, а затем переключается на внутреннее действие, которое открывает системный браузер. После завершения проверки подлинности системный браузер перенаправляется на определенный URL-адрес перенаправления (msal{client-id}://auth). MsalActivity перехватывает URL-адрес перенаправления, который затем переключается обратно на основное действие путем вызова OnActivityResult(). Метод OnActivityResult() вызывает вспомогательное средство проверки подлинности MSAL для завершения транзакции.

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

Задайте TodoApp.MAUI в качестве запускаемого проекта, выберите эмулятор Android в качестве целевого объекта, а затем нажмите F5, чтобы создать и запустить приложение. При запуске приложения вам будет предложено войти в приложение. При первом запуске вам будет предложено предоставить согласие на приложение. После завершения проверки подлинности приложение запускается как обычное.

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

Задайте TodoApp.MAUI в качестве запускаемого проекта, выберите windows Machine в качестве целевого объекта, а затем нажмите клавишу F5, чтобы создать и запустить приложение. При запуске приложения вам будет предложено войти в приложение. При первом запуске вам будет предложено предоставить согласие на приложение. После завершения проверки подлинности приложение запускается как обычное.

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

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

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