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


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

Заметка

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

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

Заметка

Так как приложению iOS требуется доступ к цепочке ключей, необходимо настроить профиль подготовки iOS. Для профиля подготовки требуется либо реальное устройство iOS, либо платная учетная запись разработчика Apple (при использовании симулятора). Вы можете пропустить это руководство и перейти к добавлению автономного доступа к приложению если вы не можете использовать проверку подлинности из-за этого ограничения.

Кончик

Хотя мы используем идентификатор 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.Forms в качестве запускаемого проекта.

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

Откройте проект TodoApp.Forms. Добавьте новый файл с именем IPlatform.cs со следующим содержимым:

using Microsoft.Identity.Client;

namespace TodoApp.Forms
{
    public interface IPlatform
    {
        IPublicClientApplication GetIdentityClient(string applicationId);
    }
}

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

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

using Microsoft.Datasync.Client;
using Microsoft.Identity.Client;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;

В классе App добавьте два новых свойства:

public IPublicClientApplication IdentityClient { get; set; }
public IPlatform PlatformService { get; }

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

public App(IPlatform platformService)
{
    InitializeComponent();

    PlatformService = platformService;
    TodoService = new RemoteTodoService(GetAuthenticationToken);
    MainPage = new NavigationPage(new MainPage(this, TodoService));
}

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

public async Task<AuthenticationToken> GetAuthenticationToken()
{
    if (IdentityClient == null)
    {
        IdentityClient = PlatformService.GetIdentityClient(Constants.ApplicationId);
    }

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

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

Откройте проект TodoApp.Forms.Android. Создайте новый класс MsalActivity со следующим кодом:

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

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

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

Откройте MainActivity.cs. Добавьте IPlatform в определение класса MainActivity:

public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity, IPlatform

Измените вызов LoadApplication() в методе OnCreate():

protected override void OnCreate(Bundle savedInstanceState)
{
    base.OnCreate(savedInstanceState);

    Xamarin.Essentials.Platform.Init(this, savedInstanceState);
    global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
    LoadApplication(new App(this));
}

Добавьте следующий код в нижней части класса:

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);
}

public IPublicClientApplication GetIdentityClient(string applicationId)
{
    var identityClient = PublicClientApplicationBuilder.Create(applicationId)
        .WithAuthority(AzureCloudInstance.AzurePublic, "common")
        .WithRedirectUri($"msal{applicationId}://auth")
        .WithParentActivityOrWindow(() => this)
        .Build();
    return identityClient;
}

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

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

Откройте файл AppDelegate.cs в проекте TodoApp.Forms.iOS. Добавьте IPlatform в определение класса AppDelegate:

public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate, IPlatform

Измените метод FinishedLaunching() на чтение:

public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
    global::Xamarin.Forms.Forms.Init();
    LoadApplication(new App(this));
    return base.FinishedLaunching(app, options);
}

Добавьте следующий код в конец класса:

public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options)
{
    bool result = AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(url);
    return result || base.OpenUrl(app, url, options);
}

public IPublicClientApplication GetIdentityClient(string applicationId)
{
    var identityClient = PublicClientApplicationBuilder.Create(applicationId)
        .WithIosKeychainSecurityGroup("com.microsoft.adalcache")
        .WithRedirectUri($"msal{applicationId}://auth")
        .Build();
    return identityClient;
}

Добавьте доступ к цепочке ключей к Entitlements.plist:

  1. Откройте файл Entitlements.plist.

  2. Выберитецепочку ключей .

  3. Выберите Добавить новые в группах цепочки ключей.

  4. Введите com.microsoft.adalcache в качестве значения:

    снимок экрана с правами I O S.

Добавьте пользовательские права в проект:

  1. Щелкните правой кнопкой мыши проект TodoApp.Forms.iOS, а затем выберите Свойства.

  2. Выберите подписывание пакета iOS.

  3. Нажмите кнопку ... рядом с полем настраиваемых прав.

  4. Выберите Entitlements, а затем выберите Открыть.

  5. Нажмите клавиши CTRL+S , чтобы сохранить проект.

    снимок экрана со свойствами подписывания пакета I O S.

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

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

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

Заметка

Так как приложению iOS требуется доступ к цепочке ключей, необходимо настроить профиль подготовки. Для профиля подготовки требуется либо реальное устройство, либо платная учетная запись разработчика Apple (при использовании симулятора). Дополнительные сведения см. в статье Подготовка устройств для iOS.

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

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

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

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