Xamarin.Essentials: Web Authenticator

Класс WebAuthenticator позволяет запускать потоки на основе браузера, которые ожидают обратного вызова по определенному URL-адресу, зарегистрированному за приложением.

Обзор

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

Библиотека проверки подлинности Майкрософт (MSAL) содержит удобное готовое решение для добавления функции проверки подлинности в приложение. Реализована даже поддержка приложений Xamarin в клиентском пакете NuGet.

Если вы хотите использовать собственную веб-службу для проверки подлинности, вы можете использовать WebAuthenticator для реализации такой возможности на стороне клиента.

Зачем использовать серверный компонент?

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

Рекомендуется использовать серверный веб-компонент в качестве промежуточного уровня между мобильным приложением и поставщиком проверки подлинности.

Внимание

Из-за недостаточной защиты хранимых секретов клиента настоятельно не рекомендуется использовать старые библиотеки и шаблоны проверки подлинности, предназначенные только для мобильных устройств и не использующие серверные веб-компоненты в потоке проверки подлинности.

Начать

Чтобы начать использовать этот API, ознакомьтесь с руководством по началу работы с Xamarin.Essentials, чтобы правильно настроить и установить библиотеку в проектах.

Для получения доступа к функции WebAuthenticator нужно создать описанную ниже конфигурацию для конкретной платформы.

Для обработки URI обратного вызова на устройствах Android требуется настроить фильтр намерения. Это легко сделать, создав подкласс класса WebAuthenticatorCallbackActivity.

const string CALLBACK_SCHEME = "myapp";

[Activity(NoHistory = true, LaunchMode = LaunchMode.SingleTop, Exported = true)]
[IntentFilter(new[] { Android.Content.Intent.ActionView },
    Categories = new[] { Android.Content.Intent.CategoryDefault, Android.Content.Intent.CategoryBrowsable },
    DataScheme = CALLBACK_SCHEME)]
public class WebAuthenticationCallbackActivity : Xamarin.Essentials.WebAuthenticatorCallbackActivity
{
}

Если целевой версией Android для проекта является Android 11 (API R 30), необходимо обновить манифест Android с помощью запросов, которые используются с новыми требованиями к видимости пакета.

Откройте файл AndroidManifest.xml в папке "Свойства" и добавьте следующее в узел манифеста:

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

Использование WebAuthenticator

Добавьте ссылку на Xamarin.Essentials в своем классе:

using Xamarin.Essentials;

API состоит главным образом из одного метода AuthenticateAsync , который принимает два параметра: URL-адрес, который следует использовать для запуска потока веб-браузера, и URI, к которому вы ожидаете, что поток в конечном итоге вызовет обратно и к которому приложение зарегистрировано, чтобы иметь возможность обрабатывать.

Результатом является объект WebAuthenticatorResult, который содержит все параметры запроса, проанализированные из URI обратного вызова:

var authResult = await WebAuthenticator.AuthenticateAsync(
        new Uri("https://mysite.com/mobileauth/Microsoft"),
        new Uri("myapp://"));

var accessToken = authResult?.AccessToken;

API WebAuthenticator обращается по URL-адресу в браузере и ожидает получения обратного вызова:

Typical Web Authentication Flow

Если пользователь отменяет поток в любой точке, возвращается исключение TaskCanceledException.

Закрытый сеанс проверки подлинности

В iOS 13 представлен временный API веб-браузера, позволяющий разработчикам запускать сеанс проверки подлинности как закрытый. В этом случае разработчики могут требовать, чтобы между сеансами проверки подлинности были недоступны общие файлы cookie или данные обзора и каждый раз устанавливался новый сеанс входа. Для этого используется новый класс WebAuthenticatorOptions, появившийся в Xamarin.Essentials 1.7 для iOS.

var url = new Uri("https://mysite.com/mobileauth/Microsoft");
var callbackUrl = new Uri("myapp://");
var authResult = await WebAuthenticator.AuthenticateAsync(new WebAuthenticatorOptions
    {
        Url = url,
        CallbackUrl = callbackUrl,
        PrefersEphemeralWebBrowserSession = true
    });

Различия между платформами

По возможности используются пользовательские вкладки, в противном случае для URL-адреса запускается намерение.

Вход с помощью Apple ID

В соответствии с правилами оценки приложений для App Store, если для проверки подлинности в приложении используются службы с поддержкой входа с учетной записью социальной сети, в приложении также должен предлагаться вход с помощью Apple ID.

Чтобы добавить такой вариант входа, нужно сначала настроить приложение соответствующим образом.

Для iOS 13 и более поздних версий необходимо вызвать метод AppleSignInAuthenticator.AuthenticateAsync(). При этом будет использоваться нативный API для входа с помощью Apple ID, чтобы обеспечить оптимальную работу пользователей на таких устройствах. Вы можете написать общий код для использования нужного API в среде выполнения следующим образом:

var scheme = "..."; // Apple, Microsoft, Google, Facebook, etc.
WebAuthenticatorResult r = null;

if (scheme.Equals("Apple")
    && DeviceInfo.Platform == DevicePlatform.iOS
    && DeviceInfo.Version.Major >= 13)
{
    // Use Native Apple Sign In API's
    r = await AppleSignInAuthenticator.AuthenticateAsync();
}
else
{
    // Web Authentication flow
    var authUrl = new Uri(authenticationUrl + scheme);
    var callbackUrl = new Uri("xamarinessentials://");

    r = await WebAuthenticator.AuthenticateAsync(authUrl, callbackUrl);
}

var authToken = string.Empty;
if (r.Properties.TryGetValue("name", out var name) && !string.IsNullOrEmpty(name))
    authToken += $"Name: {name}{Environment.NewLine}";
if (r.Properties.TryGetValue("email", out var email) && !string.IsNullOrEmpty(email))
    authToken += $"Email: {email}{Environment.NewLine}";

// Note that Apple Sign In has an IdToken and not an AccessToken
authToken += r?.AccessToken ?? r?.IdToken;

Совет

На устройствах, отличающихся от iOS 13, выполнение этого кода приведет к выполнению потока проверки подлинности в браузере. Этот код также можно использовать для включение входа с помощью Apple ID на устройствах Android и UWP. Вы можете войти в свою учетную запись iCloud в симуляторе iOS, чтобы проверить вход в Apple.


Серверный компонент ASP.NET Core

API WebAuthenticator можно использовать с любой серверной веб-службой. Для использования с приложением ASP.NET Core сначала нужно настроить веб-приложение, выполнив такие действия:

  1. В веб-приложении ASP.NET Core настройте необходимые поставщики проверки подлинности на основе учетной записи социальной сети.
  2. Задайте для схемы проверки подлинности по умолчанию значение CookieAuthenticationDefaults.AuthenticationScheme в вызове .AddAuthentication().
  3. Используйте .AddCookie() в вызове .AddAuthentication() Startup.cs.
  4. Для настройки всех поставщиков обязательно используйте .SaveTokens = true;.
services.AddAuthentication(o =>
    {
        o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    })
    .AddCookie()
    .AddFacebook(fb =>
    {
        fb.AppId = Configuration["FacebookAppId"];
        fb.AppSecret = Configuration["FacebookAppSecret"];
        fb.SaveTokens = true;
    });

Совет

Чтобы включить вход с помощью Apple ID, можно использовать пакет NuGet AspNet.Security.OAuth.Apple. Полный пример Startup.cs можно просмотреть в репозитории GitHub для Essentials.

Добавление пользовательского контроллера для проверки подлинности на мобильных устройствах

Поток проверки подлинности на мобильных устройствах желательно инициировать непосредственно для выбранного пользователем поставщика (например, путем нажатия кнопки "Майкрософт" на экране входа в приложение). Важно также реализовать возврат в приложение соответствующих сведений по конкретному URI обратного вызова для завершения потока проверки подлинности.

Для таких задач используйте контроллер API:

[Route("mobileauth")]
[ApiController]
public class AuthController : ControllerBase
{
    const string callbackScheme = "myapp";

    [HttpGet("{scheme}")] // eg: Microsoft, Facebook, Apple, etc
    public async Task Get([FromRoute]string scheme)
    {
        // 1. Initiate authentication flow with the scheme (provider)
        // 2. When the provider calls back to this URL
        //    a. Parse out the result
        //    b. Build the app callback URL
        //    c. Redirect back to the app
    }
}

Задача этого контроллера — определить запрашиваемую приложением схему (поставщика) и инициировать поток проверки подлинности с помощью поставщика социальных сетей. Когда поставщик отправляет обратный вызов во внутреннюю веб-службу, контроллер анализирует результат и перенаправляет его в URI обратного вызова приложения с параметрами.

Иногда может потребоваться вернуть данные, например access_token поставщика, в приложение, что можно сделать с помощью параметров запроса URI обратного вызова. Вы также можете создать свое удостоверение на сервере и передать собственный маркер в приложение. Этот процесс вы можете настроить на свое усмотрение.

Ознакомьтесь с полным примером контроллера в репозитории Essentials.

Примечание.

В приведенном выше примере показано, как вернуть маркер доступа из поставщика 3-й сторонней проверки подлинности (ie: OAuth). Чтобы получить маркер, который можно использовать для авторизации веб-запросов к самой внутренней веб-службе, вам потребуется создать собственный маркер в веб-приложении и реализовать его возврат. Дополнительные сведения о расширенных сценариях проверки подлинности в ASP.NET Core см. в статье Общие сведения о проверке подлинности в ASP.NET Core.


API