Авторизация через сторонние сервисы. Что это и зачем? – Обзоры | Amiro.CMS

Описание системы blitz identity provider и протокола авторизации oauth 2.0

Blitz Identity Provider реализует более простой доступ к системам заказчика и бесшовное переключение между различными приложениям. Этому способствуют технологии однократной аутентификации и единого входа (Single Sign-On), а также работа с механизмами аутентификации устройств доступа пользователей.

Blitz Identity Provider предлагает разные варианты аутентификации — это привычная парольная аутентификация, различные способы двухфакторной аутентификации (OAuth 2.0), использование смарт-карт и ключей с электронной подписью.

Описание механизма авторизации внутри системы

Получение токена доступа react-приложением от back-приложения описано в разделе “Схема работы с blitz”.

После получения токена front-приложение передает в каждом запросе на back этот токен параметром либо в заголовках запроса. Так происходит до тех пор пока не истечет срок хранения токена в куках, либо от back не вернется код ответа 401, что будет означать окончание действия токена и станет сигналом для его обновления.

Авторизация через сторонние сервисы. что это и зачем? – обзоры | amiro.cms

В версии Amiro.CMS 5.12 появилось API авторизации, позволяющее минимальными усилиями осуществить интеграцию с любой внешней системой. Формат новости не позволил полностью описать, что это даёт создателям сайтов и их посетителям, поэтому давайте устраним этот пробел в блоге.

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

Похожее:  АБР ИНТЕРНЕТ БАНК ВХОД В ЛИЧНЫЙ КАБИНЕТ

Задача API авторизации как раз и заключается в упрощении регистрации. Даже не так: регистрация вообще становится ненужной.

Большинство посетителей уже имеют профиль во «В контакте»
(зарегистрировано 97 миллионов человек), «Фейсбуке», «Твиттере» или
другой сети. И им достаточно нажать иконку своего любимого сервиса и
подтвердить передачу данных, чтобы сайт на Amiro.CMS «узнал»
пользователя и автоматически создал ему учётную запись с уже
заполненными полями.

Именно модули для «В Контакте», «Фейсбука» и «Твиттера» уже включены в
версию 5.12. Они сделаны на новом API и являются не только полностью
рабочим инструментом, но и примером для реализации модулей интеграции с
абсолютно любой внешней системой. В будущих версиях появятся новые
примеры, но владельцам сайтов на Amiro.CMS ничего не мешает сделать свои
прямо сейчас. Это могут быть модули для уже существующего форума на
отдельном движке, внутренней корпоративной системы или любой из
социальных сетей. 

В документации можно найти иллюстрированный пример для настройки авторизации на своем сайте и руководство по разработке нового драйвера.

Приглашаем вас опробовать авторизацию, непосредственно на нашем сайте, например в форуме или комментариях к этому блогу.

Требования к системе авторизации

При проектировании расширения я руководствовался следующими принципами:

  1. Необходимость абстрагироваться от тонкостей авторизации через различные типы сервисов, использование адаптеров для каждого сервиса.
  2. Получение уникального идентификатора авторизации, который можно использовать для регистрации пользователя в нашем приложении.
  3. Возможность расширения стандартных классов авторизации для получения дополнительных данных о пользователе.
  4. Возможность работать с API социальных сетей путем расширения класса авторизации необходимого сервиса.
  5. Возможность настраивать список поддерживаемых сайтом сервисов, переопределять внешний вид виджета авторизации. Возможность использовать popup окно для авторизации без закрытия нашего приложения.

Расширение EAuth

В результате реализации всех требований выше на свет появилось расширение EAuth.


На данный момент расширение содержит:

Установка

Для начала необходимо

1 Зависимости

Расширение использует

2 Настройка


В конфигурацию

`main.php`

необходимо добавить:

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

В качестве примера возьмем стандартное приложение Yii, сгенерированное командой

`yiic webapp create`

, и добавим возможность авторизации через Google и Яндекс (OAuth провайдеров подключать не будем, чтобы не возиться с ключами). Посмотреть готовую

2 Редактирование SiteContoller


Вторым шагом будет изменение действия

`site/login`

. Добавим следующий код в начало действия:

3 Редактируем представление `protected/views/site/login.php`

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


Для изменения внешнего вида виджета можно скопировать файл

`protected/extensions/eauth/views/auth.php``[theme_name]/views/EAuthWidget/auth.php`

4 Результат

После всех проделанных действий мы можем открыть наш сайт и перейти на страницу Login. После стандартной формы авторизации появятся иконки сервисов авторизации:

При клике, например, по иконке Google откроется popup окно: Popup окно авторизации

Authorization flow

Соответственно, для регистрации надо вызвать navigator.credentials.create.

В результате этого в Authenticator-е пользователя сохранится закрытый ключ для определенного сайта, а в Relying Party сохранится открытый ключ.

После этого процесс аутентификации будет таким:

Credential management api

Разработкой занимается та же организация, что и WebAuthn — W3C.

позволяет:


Пример реализации Credential Management API, известный всем — это диспетчер паролей в Google:

Oauth = fetch request token redirect to authorization fetch access token call api

В примере с GMail мы использовали 2 вида удаленных вызовов: а) редирект через браузер; б) обращение к API изнутри скрипта.

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

Oauth 2.0


Начнем с самого известного протокола OAuth 2.0. Он был опубликован в 2022 году, как RFC 6749:

Oauth 2.0 лабораторная работа (github)

Существует множество инструкций, как реализовать OAuth 2.0 авторизацию, используя соцсети. Мне лично понравилась следующая статья:

Openid

В сети есть

Openid connect


С OAuth 2.0 немного разобрались. Теперь выясним зачем нужен OpenID Connect, который является надстройкой над OAuth 2.0:

Давайте посмотрим на стандарт с технической стороны.

OpenID Connect (OIDC) — открытый стандарта OpenID, который разрабатывает консорциум OpenID Foundation. OIDC расширяет OAuth 2.0 следующими основными возможностями:


Диаграмма взаимодействия в OpenID Connect выглядит так же, как и в случае OAuth. Единственная разница в содержимом запросов:

Openid connect: лабораторная работа (google)

Теперь посмотрим, чем нас по данной теме порадует Google. Есть подробная инструкция по конфигурации и использованию

и “песочница” по использованию Google API:

Здесь, как и в случае с OAuth 2.0, мы пройдем путь по шагам и посмотрим на приходящие данные. Аналогично считаем, что приложение зарегистрировано, Client ID и Client Secret получены, Шаг 1 пройден. Шаг 2 из call flow — это вызов в REST формате:

Saml 2.0 (security assertion markup language)

Зрелый протокол 2005 года, но имеет ограниченный набор сценариев для построения систем SSO. Использует формат данных на основе XML. Подробнее можно посмотреть в статье:

Webauthn

(also known as WebAuthn):

Авторизация через внешние сервисы

Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core

Последнее обновление: 31.10.2022

Инфраструктура OWIN и AspNet Identity позволяют производить авторизацию через внешние сервисы с помощью аккаунтов в Google, Twitter, Facebook и т.д. Хотя
подобная функциональность была доступна и предыдущей версии – в MVC 4, в MVC 5 ее механизм существенно изменился, и за аутентификацию отвечают компоненты OWIN.

Возьмем стандартный проект MVC 5, использующий AspNet Identity, то есть имеющий в качестве типа аутентификации Individual User Accounts. В проекте
в папке App_Start мы можем увидеть файл Startup.Auth.cs, который отвечает за настройку конфигурации OWIN:

using System;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.Google;
using Owin;
using GoogleAuthApp.Models;

namespace GoogleAuthApp
{
    public partial class Startup
    {
        public void ConfigureAuth(IAppBuilder app)
        {
            app.CreatePerOwinContext(ApplicationDbContext.Create);
            app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
            app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);

            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                LoginPath = new PathString("/Account/Login"),
                Provider = new CookieAuthenticationProvider
                {
                    OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                        validateInterval: TimeSpan.FromMinutes(30),
                        regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
                }
            });            
            app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

            app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5));

            app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);

            //app.UseMicrosoftAccountAuthentication(
            //    clientId: "",
            //    clientSecret: "");

            //app.UseTwitterAuthentication(
            //   consumerKey: "",
            //   consumerSecret: "");

            //app.UseFacebookAuthentication(
            //   appId: "",
            //   appSecret: "");

            //app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions()
            //{
            //    ClientId = "",
            //    ClientSecret = ""
            //});
        }
    }
}

В конце метода ConfigureAuth можно увидеть ряд закомментированных по умолчанию строк, предназначенных для аутентификации через внешние сервисы. Например:

//app.UseFacebookAuthentication(
//   appId: "",
//   appSecret: "");

При регистрации нашего приложения в социальной сети Facebook мы получаем идентификатор приложения в рамках этой соцсети и секретное слово.
Эти значения мы указываем для параметров appId и appSecret соответственно. И после этого, если у нас есть аккаунт в сети Facebook, мы можем авторизоваться
в приложении через этот аккаунт. Довольно удобно – всего три строчки, а все остальное за нас сделает инфраструктура ASP.NET MVC.

Для примера выберем самый простой вариант – аутентификацию через Google. Чтобы подключаться к провайдерам аутентификации Google или
Facebook, нам надо настроить проект на использование SSL. Для этого перейдем к панели свойств проекта и установим там параметр SSL Enabled равным
True.

SSL in ASP.NET MVC

Вместе с установкой SSL также Visual Studio устанавливает и новый адрес для SSL-соединения: https://localhost:44300/, который мы
будем использовать для аутентификации Google.

Теперь нам надо изменить адрес запуска проекта. Для этого скопируем ssl-адрес и перейдем в настройки проекта на вкладку Web. Вставим скопированный адрес в поле
Project Url:

Изменение адреса запуска в ASP.NET MVC

Прежде всего нам надо будет создать в аккаунте Google некоторые настройки, которые будут использоваться нашим приложением. Для этого авторизуемся в Google и перейдем к странице Google Developers Console:

Авторизация Google в Asp.Net MVC 5

На странице нажмем на кнопку Create Project. В появившемся окне введем название проекта и его ID:

Авторизация Google в Oath2

Google автоматически генерирует некоторые значения, как на рисунке выше. И в принципе мы можем эти значения оставить. И через некоторое время будет
создан новый проект, а перед нами откроется панель настроек проекта.

В левой колонке меню выберем пункт APIs & auth и далее выберем Consent screen. Здесь нам надо установить
название приложение в поле Product Name, а также укажем email:

Авторизация через сторонние сервисы. Что это и зачем? - Обзоры | Amiro.CMS

В моем случае название приложения TestAppForGoogleAuth. Сохраним, нажав внизу страницы на кнопку Save. После этого перейдем
в левой панели меню к пункту Credentials и на открывшейся странице нажмем на кнопку Create New Client ID.
Нам отобразится следующее диалоговое окно:

Авторизация через сторонние сервисы. Что это и зачем? - Обзоры | Amiro.CMS

Тут есть несколько опций, которые надо установить. Во-первых, в поле APPLICATION TYPE оставим Web Application

В поле Authorized JavaScript введем ssl-адрес нашего приложения, который был установлен выше. Как правило, это
https://localhost:44300/

После это в поле Authorized redirect URI введем https://localhost:44300/signin-google

После ввода всех данных нажмем на кнопку Create Client ID. После этого Google сгенерирует нам ряд аутентификационных настроек, которые мы будем
использовать в приложении:

Подключение к Google в ASP.NET MVC

После получения аутентификационных настроек обновим файл Startup.Auth.cs:

app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions()
{
    ClientId = "144182......................79hr.apps.googleusercontent.com",
    ClientSecret = "p-xu..............L"
});

Затем перейдем в меню на вкладку APIs. Найдем пункт Google API и нажмем на кнопку OFF:

Авторизация Google  и ASP.NET MVC

После всех настроек установим соответствующий атрибут ssl для контроллера HomeController:

[RequireHttps]
public class HomeController : Controller
{
}

Запустим проект и обратимся к методу Login, увидим, что теперь нам доступно два способа входа на сайт: стандартный и через Google.

Авторизация через сторонние сервисы. Что это и зачем? - Обзоры | Amiro.CMS

После этого приложение попросит принять некоторые разрешения для доступа к нашему аккаунту::

Авторизация через сторонние сервисы. Что это и зачем? - Обзоры | Amiro.CMS

Нажмем на кнопку Принять, и после этого мы перейдем к поледнему шагу – регистрации внешнего логина, который будет отображаться на сайте для данного аккаунта:

Авторизация через сторонние сервисы. Что это и зачем? - Обзоры | Amiro.CMS

И после этого в меню начнет отображаться логин

Авторизация через сторонние сервисы. Что это и зачем? - Обзоры | Amiro.CMS

За отображение логина в представлении отвечает частичное представление _ExternalLoginsListPartial.

Данные пользователя после завершения визита на сайт не пропадают. Если мы откроем в окне Server Explorer используемую базу данных, то мы сможем увидеть,
что в таблицу AspNetUserLogins, которая отвечает за связь логинов сайта с внешними аккаунтами, была добавлена новая запись:

Авторизация через сторонние сервисы. Что это и зачем? - Обзоры | Amiro.CMS

Кроме того, так как был добавлен новый пользователь, соответствующая запись добавляется в таблицу AspNetUsers.

Таким образом, мы можем воспользоваться преимуществами OWIN и OAuth2 и добавить в приложение идентификацию с помощью внешних сервисов.

НазадСодержаниеВперед

Грабли вторые: «подслушивание» секретного ключа

Предположим, мы как-то защитили retpath, и он теперь может указывать только на наш сайт. Но проблема с параметром secret остается.

Secret можно подсмотреть из-за спины или перехватить методом прослушивания WiFi-трафика. Или на вашем сайте когда-нибудь найдется XSS-уязвимость, позволяющая «утянуть» секретный ключ. Имея значение secret, злоумышленник сможет прочитать вашу адресную книгу. Значит, нужно обезопасить secret от перехвата (в идеале — вообще его не передавать через URL).

Грабли первые: подмена адреса возврата retpath

Ну конечно же, вы догадались, что злоумышленник на своем сайте первым делом разместит ссылку

и заставит вас на нее кликнуть. В результате он получит секретный ключ, который вернул GMail, а значит, и ваши контакты:

Грабли третьи: слишком много редиректов


Если для каждого вызова API требуется разный secret, то нам придется организовывать столько редиректов на сайт Service Provider-а, сколько у нас вызовов. При интенсивном использовании API это работает очень медленно, да и неудобно порядком…

Грабли четвертые: плохая идентификация consumer-а

GMail, конечно, хочет знать, кто пользуется его API. Разрешить доступ одним сайтам и запретить — другим… Значит, при формировании запроса в форме импорта контактов Consumer (сайт) должен «представляться» Service Provider-у (GMail-у). В нашем случае эту функцию частично выполняет retpath (имя сайта в нем), но данный способ не универсален, т.к. механизм «представления» должен быть задейстсован еще и при вызове API-методов.

Демонстрация работы oauth на примере простого приложения

Чтобы «вживую пощупать» OAuth, нам потребуются две вещи:

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


На примере Ruby/Rack/Sinatra приложения:

Gemfile:…gem ‘oa-enterprise’, :require => ‘omniauth/enterprise’…

Приложение:…set :login_page, “/auth/cas”

Критка и мифы

CAS — старый проект, не развивается. Текущая версия сервера — 3.4.8, последняя ревизия протокола — 2005 год.


Последнее обновление —

Об изобретении велосипедов

Хороший способ понять что-то — сделать это самому, наступив попутно на все разложенные грабли. Сейчас мы будем изобретать велосипед: попробуем представить, как бы мы решали задачу взаимодействия Consumer-а и Service Provider-а без всяких стандартизированных протоколов.

Во-первых, напишем саму форму импорта контактов с GMail:

Далее попросим разработчиков GMail сделать так, чтобы при переходе пользователя по URI /auth.php ему бы выдавалась форма авторизации (в нашем веломире GMail написан на PHP). После успешного ввода пароля пользователь должен редиректиться на сайт, чей URL указан в параметре retpath.

Итак, после ввода пароля пользователь будет возвращаться к нам на сайт по следующему адресу:

А мы из скрипта /import.php обратимся к API GMail, передадим в него ключ Y49xdN0Zo2B5v0RR и загрузим контакты:

Ну что же, давайте теперь считать грабли (потому что шишки считать будет уже поздно).

План этой статьи

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

  1. Рассмотрим проблемы, которые возникают при «ручной» реализации кросс-авторизации.
  2. Поговорим о том, что такое «приложение» и кто такой Consumer.
  3. Коснемся основ криптографии.
  4. Обозначим демо-приложение, которое мы будем писать в этой статье.
  5. Определимся с тестовым сервером OAuth, на котором будем экспериментировать.
  6. Пройдем по всем шагам протокола OAuth и приведем исходники скрипта.

Полезные ссылки по oauth

См. также:

Приложение = consumer доступ к api

При работе с OAuth важно, что термин Consumer не ограничивается смыслом «сайт». Consumer — это некоторое

приложение

, а уж где оно размещено, не так важно. Примеры Consumer-ов из реальной жизни:

Но из одного OAuth каши не сваришь. Действительно, все, что дает OAuth, — это возможность авторизоваться на удаленном сервисе (Service Provider) и делать автризованные запросы к API. Не важно, как устроен этот API: это может быть чистый SOAP, REST-подход т. д. Главное, чтобы каждый метод API принимал на вход специальные параметры, передаваемые согласно протоколу OAuth.

Приложение: остальные протоколы идентификации


Для полноты картины перечислю остальные актуальные протоколы и технологии, используемые для идентификации пользователей:

Принцип работы

Первый вход.

1. Пользователь заходит на страницу, доступ к которой есть только у зарегистрированных пользователей.

Проверка токена авторизации

При заходе пользователя в личный кабинет react-приложение проверяет, есть ли в куках браузера пользователя access_token. Если токен присутствует, то front отправляет запрос на back для получение нужных ему данных, передавая в параметре или в заголовках access_token.

Процедура авторизации

Сначала со стороны react-приложения отправляется запрос на back-приложения для получения адреса страницы системы Blitz, чтобы перенаправить туда пользователя для авторизации.

В системе Blitz сотрудник вводит свои учетные данные, авторизуется по номеру телефона или по сеансу ОС, если находится во внутренней сети заказчика.

При успешном прохождении процедуры авторизации на стороне Blitz пользователь перенаправляется на личный кабинет с get параметром code по адресу, указанному в параметрах, при переходе в Blitz.

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


Поговорим о том, откуда появляются приложения и как Service Provider о них узнает. Все достаточно просто: Service Provider имеет специальную форму регистрации приложений, которой может воспользоваться любой желающий. Вот пример такой формы:

Авторизация через сторонние сервисы. Что это и зачем? - Обзоры | Amiro.CMS
После регистрации приложения вам выдается 5 параметров, которые требуются для работы с OAuth. Вот как они могут выглядеть:

Сообщение = документ цифровая подпись

«Цифровая подпись» — звучит страшно, но на самом деле это достаточно очевидная вещь. Когда вы ручкой подписываетесь на каком-либо документе, вы удостоверяете, что этот документ написан вами, а не кем-то другим. Ваша подпись как бы «добавляется» к документу и идет с ним в «одном комплекте».

Аналогично, цифровая подпись добавляется к некоторому блоку данных, удостоверяя: тот, кто сформировал эти данные, не выдает себя за другого. Цифровая подпись не шифрует документ, она лишь гарантирует его подлинность! Поставить подпись позволяет тот самый Shared Secret, который известен получателю и отправителю, но более никому.

Как это работает? Пусть наш $sharedSecret = 529AeGWg, и мы сообщили его шепотом на ухо принимающей стороне. Мы хотим передать сообщение «Мой телефон 1234567» с гарантированной защитой от фальсификации злоумышленником.

  1. Consumer добавляет цифровую подпись к сообщению, в общем виде —
    $transfer = $message . "-" . md5($message . $sharedSecret);
    // $transfer = "Мой телефон 1234567" . "-" . md5("Мой телефон 1234567" . "529AeGWg")
  2. Service Provider принимает данные, разбивает их обратно на 2 части — $message и $signature — и проделывает точно такую же операцию:
    $signatureToMatch = md5($message . $sharedSecret);
    // $signatureToMatch = md5("Мой телефон 1234567" . "529AeGWg");

    Дальше остается только сравнить получившееся значение $signatureToMatch с тем, что было в полученных данных $signature и рапортовать о подделке, если значения не совпали.

Ссылки

UPDATE:

в пункте «3.2 Настройка» не хватало расширения loid, добавил.

UPDATE 2:

Актуальная версия и инструкция по настройке доступны на

Удачные решения для менее универсальных случаев

В реальной жизни бывает не так всё запущено, как в том случае, который мы рассматриваем, и порой кажется, что можно обойтись решением с

, но как только появляется внешний домен, либо пропадает общая БД для хранения сессий, решение отпадает.

Можно испльзовать вариант, описанный здесь, но в комментариях довольно много негатива по поводу iframe, javascript и прочего.

Установка

1. Ruby version manager

bash < <(curl -s

Фундамент oauth

Примечательно, что «подводных граблей» осталось еще много. Я не буду их здесь описывать, потому что эти грабли лежат в Марианской впадине (глубоко, 10920 м). На описание уязвимостей пришлось бы потратить с десяток страниц. Так что я сразу перейду к описанию OAuth, где все проблемы уже решены.

Выводы

It’s only the beginning!

Конец скрипта: вывод виджета

Окончание скрипта должно быть понятно и без подробных разъяснений.

Заключение

Выбранный стек технологий для реализации проекта и наличие системы единой авторизации у заказчика породило необходимость реализации “двойной авторизации”: авторизации web-приложения личного кабинета в blitz и авторизации react-приложения для работы с back по Rest Api.

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *