- PVSM.RU - https://www.pvsm.ru -

Авторизация OAuth для Xamarin-приложений

Итак, сегодня мы продолжаем разбираться с различными механизмами авторизации пользователей в приложениях на Xamarin. После знакомства с SDK от Facebook и ВКонтакте (здесь [1] и здесь [2]), можем перейти к одному из самых популярных (на текущий момент) механизмов внешней авторизации пользователей — OAuth [3]. Большинство популярных сервисов вроде Twitter, Microsoft Live, Github и так далее, предоставляют своим пользователям возможность входа в сторонние приложения с помощью одного привычного аккаунта. Научившись работать с OAuth вы легко сможете подключать все эти сервисы и забирать из них информацию о пользователе.

Авторизация OAuth для Xamarin-приложений - 1

Авторизация OAuth для Xamarin-приложений - 2

Предполагается, что вы уже знакомы с тем, как работает OAuth, а если нет — рекомендуем вот эту хорошую статью на Хабре [4]. Если коротко, то при авторизации OAuth пользователь перенаправляется с одной веб-страницы на другую (обычно 2-3 шага) до тех пор, пока не перейдет на конечный URL. Этот финальный переход и будет отловлен в приложении (если писать логику самому) на уровне WebView, а нужные данные (token и срок его валидности) будут указаны прямо в URL.

Небольшой список популярных сервисов, которые предоставляют возможность авторизации пользователей по OAuth: Одноклассники, Mail.ru, Dropbox, Foursquare, GitHub, Instagram, LinkedIn, Microsoft, Slack, SoundCloud, Visual Studio Online, Trello.

Xamarin.Auth

Для того, чтобы работать с OAuth в Xamarin мы остановимся на простой и удобной библиотеке Xamarin.Auth [5], которая развивается уже не первый год и имеет все необходимые для нас механизмы:

  1. Отображение браузера со страницами авторизации
  2. Управление потоком редиректов и процессом авторизации
  3. Получение нужных данных
  4. Предоставление механизмов для дополнительных запросов к сервису, например для получения информации о пользователе

Также Xamarin.Auth поддерживает возможность хранения учетных данных пользователя в защищенном хранилище. В общем, зрелый и качественный компонент с необходимой функциональностью.

Рекомендуем устанавливать Xamarin.Auth из Nuget, так как версия в Xamarin Components уже давно устарела и не обновляется.

Авторизация OAuth для Xamarin-приложений - 3

Напомню, что мы уже ранее рассказывали про авторизацию с помощью SDK от Facebook и ВКонтакте. В нашем примере мы вынесли всю логику авторизации в платформенные проекты, оставив в PCL только интерфейсы. Для OAuth мы пойдем тем же путем, несмотря на поддержку PCL в самом Xamarin.Auth.

Помимо Xamarin.Auth можем также порекомендовать библиотеку Xamarin.Forms.OAuth [6] от Bruno Bernardo. Даже если вы используете классический Xamarin, в исходных кодах этого проекта можно найти множество готовых конфигураций для различных сервисов.

Мы же в качестве примера работы OAuth подключим авторизацию с помощью Microsoft. Первым делом создадим приложение на сайте https://apps.dev.microsoft.com [7] и получим там Client ID (ИД клиента или приложения).

Авторизация OAuth для Xamarin-приложений - 4

Подключаем авторизацию в PCL

На уровне PCL все как обычно — делаем простой интерфейс IOAuthService для платформенного сервиса, никаких новых зависимостей в проект не добавляем.

public interface IOAuthService
{
   Task<LoginResult> Login();
   void Logout();
}

Ну и, конечно же, будет необходимо добавить обращение к методам DependencyService.Get<IOAuthService>().Login() и DependencyService.Get<IOAuthService>().Logout() внутри нашей страницы авторизации.

Также нет проблем добавить поддержку нескольких OAuth-сервисов. Для этого можно добавить в методы Login() и Logout() аргумент providerName (тип string, int или enum) и в зависимости от его значения выбирать поставщика услуг.

Реализация платформенной части

Как уже отмечалось ранее, необходимо добавить библиотеки Xamarin.Auth из Nuget в каждый платформенный проект, в нашем случае — iOS и Android. Дальше пишем нашу реализацию IOAuthService для каждой платформы и регистрируем ее в качестве Dependency.

Теперь нам достаточно создать экземпляр класса OAuth2Authenticator с нужными параметрами:

         var auth = new OAuth2Authenticator
           (
               clientId: "ВАШ_CLIENT_ID",
               scope: "wl.basic, wl.emails, wl.photos",
               authorizeUrl: new Uri("https://login.live.com/oauth20_authorize.srf"),
               redirectUrl: new Uri("https://login.live.com/oauth20_desktop.srf"),
               clientSecret: null,
               accessTokenUrl: new Uri("https://login.live.com/oauth20_token.srf")
           )
           {
               AllowCancel = true
           };

Теперь повесим обработчик завершения авторизации:

auth.Completed += AuthOnCompleted;

Всё, можно показать модальное окно со встроенным веб-браузером для авторизации, получаемое через метод auth.GetUI(). На iOS это можно сделать примерно так:

UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(auth.GetUI(), true, null);

На Android при использовании Xamarin.Forms код может получится следующим:

Forms.Context.StartActivity(auth.GetUI(Forms.Context));

После успешной авторизации вызовется наш метод AuthOnCompleted(), и для iOS будет необходимо скрыть модальное окно с браузером (на Android само скроется):

UIApplication.SharedApplication.KeyWindow.RootViewController.DismissViewController(true, null);

Теперь можно получать нужные данные (access_token и время его жизни в секундах — expires_in)

var token = authCompletedArgs.Account.Properties["access_token"];                
var expireIn = Convert.ToInt32(authCompletedArgs.Account.Properties["expires_in"]);
var expireAt = DateTimeOffset.Now.AddSeconds(expireIn);

И нам остался последний шаг — получить расширенную информацию из профиля пользователя, включая email и ссылку на аватарку. Для этого в Xamarin.Auth есть специальный класс OAuth2Request с помощью которого удобно делать подобные запросы.

             var request = new OAuth2Request("GET", new Uri("https://apis.live.net/v5.0/me"), null, account);
var response = await request.GetResponseAsync();

Теперь нам приходит JSON с данными пользователя, и мы можем их сохранить и отобразить в приложении.

             if (response.StatusCode == HttpStatusCode.OK)
{
    var userJson = response.GetResponseText();
    var jobject = JObject.Parse(userJson);
    result.LoginState = LoginState.Success;
    result.Email = jobject["emails"]?["preferred"].ToString();
    result.FirstName = jobject["first_name"]?.ToString();
    result.LastName = jobject["last_name"]?.ToString();
    result.ImageUrl = jobject["picture"]?["data"]?["url"]?.ToString();
    var userId = jobject["id"]?.ToString();
    result.UserId = userId;
    result.ImageUrl = $"https://apis.live.net/v5.0/{userId}/picture";
}

Как видим, ничего сложного нет. Вопрос в том, чтобы правильно прописать URL для процесса авторизации. Ну и помнить, что поле expires_in содержит время в секундах (это вызывает частые вопросы).

Авторизация OAuth для Xamarin-приложений - 5

В реальных проектах также рекомендуем назначить обработчик ошибок на событие auth.Error, чтобы ни одна проблема не осталась без решения.

Заключение

Сегодня мы завершили рассмотрение всех популярных способов авторизации пользователей и получения базовой информации о них через внешние сервисы. Описанные механизмы подходят как для Xamarin.Forms, так и для классического Xamarin iOS/Android. Полные исходные коды проекта со всеми примерами можно найти в нашем репозитории:

https://bitbucket.org/binwell/login [8]

Задавайте ваши вопросы в комментариях к статье и оставайтесь на связи!

Об авторе

Авторизация OAuth для Xamarin-приложений - 6 Вячеслав Черников — руководитель отдела разработки компании Binwell [9], Microsoft MVP и Xamarin Certified Developer. В прошлом — один из Nokia Champion и Qt Certified Specialist, в настоящее время — специалист по платформам Xamarin и Azure. В сферу mobile пришел в 2005 году, с 2008 года занимается разработкой мобильных приложений: начинал с Symbian, Maemo, Meego, Windows Mobile, потом перешел на iOS, Android и Windows Phone. Статьи Вячеслава вы также можете прочитать в блоге на Medium [10].

Другие статьи автора:

Автор: Microsoft

Источник [19]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/mobil-ny-e-prilozheniya/260350

Ссылки в тексте:

[1] здесь: https://habrahabr.ru/company/microsoft/blog/323296/

[2] здесь: https://habrahabr.ru/company/microsoft/blog/321454/

[3] OAuth: https://oauth.net

[4] эту хорошую статью на Хабре: https://habrahabr.ru/company/mailru/blog/115163/

[5] Xamarin.Auth: https://github.com/xamarin/Xamarin.Auth

[6] Xamarin.Forms.OAuth: https://github.com/Bigsby/Xamarin.Forms.OAuth

[7] https://apps.dev.microsoft.com: https://apps.dev.microsoft.com

[8] https://bitbucket.org/binwell/login: https://bitbucket.org/binwell/login

[9] Binwell: http://www.binwell.com/

[10] блоге на Medium: https://medium.com/binwell/public/home

[11] Автоматизируем неавтоматизируемое, или про Xamarin в реальных проектах: https://habrahabr.ru/company/microsoft/blog/327900/

[12] Деплоим мобильный софт с помощью devops-конвейера Microsoft: https://habrahabr.ru/company/microsoft/blog/329908/

[13] DevOps на службе человека: https://habrahabr.ru/company/microsoft/blog/325184/

[14] Удобный REST для Xamarin-приложений: https://habrahabr.ru/company/microsoft/blog/310704/

[15] Быстрое создание MVP (minimum viable product) на базе Microsoft Azure и Xamarin.Forms: https://habrahabr.ru/company/microsoft/blog/281897/

[16] Готовим Xamarin.Forms: настройка окружения и первые шаги: https://habrahabr.ru/company/microsoft/blog/303630/

[17] Повышаем эффективность работы в Xamarin.Forms: https://habrahabr.ru/company/microsoft/blog/304678/

[18] Работаем с состояниями экранов в Xamarin.Forms: https://habrahabr.ru/company/microsoft/blog/307890/

[19] Источник: https://habrahabr.ru/post/332970/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best