Всем привет! Меня зовут Екатерина Срибна, я Full Stack Developer в NIX. В этой статье я решила сравнить популярные инструменты аутентификации и авторизации, которые упростят работу с технологией единого входа — Single Sign On. Собранный мною материал будет полезен для новичков и специалистов с опытом. Статья ориентирована в основном на .NET-разработчиков, но есть здесь инсайты и для работающих с Java и JavaScript.

Что такое Single Sign On

Технология единого входа (Single Sign On) значительно упрощает жизнь пользователей. Для перехода между разными сервисами, количество которых растет день ото дня, достаточно одной аутентификации и авторизации. Сложность только в том, что Identity-провайдеров, которые поддерживают Single Sign On, существует много. На старте может быть не понятно, какой провайдер лучше выбрать, как его использовать и настраивать у себя на проекте. Эта статья поможет вам во всем разобраться. Мы познакомимся с IdentityServer 4, рассмотрим Azure B2C и интегрируемся с Keycloak.

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

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

Благодаря технологии Single Sign On этот процесс упрощается. Пользователь может всего один раз авторизоваться и ходить между ресурсами без повторного введения своих кредов, вспоминая пароли. Проверка пользователя происходит «под капотом» системы.

Рассмотрим принцип Single Sign On на следующей схеме. Есть пользователь, есть его браузер, и пользователь взаимодействует с ним, чтобы постучаться на первый сайт. Также есть Identity-провайдер, который мы настроили. У сайта есть ключ, по которому он может валидировать всю информацию, получаемую от Identity-провайдера, с которым установлены доверительные отношения.

Пользователь отправляет запрос на получение данных какого-то ресурса, но этот ресурс требует авторизации. Далее сайт 1 с помощью пользовательского браузера через  редирект отправляет запрос на Identity-провайдер, чтобы получить информацию о пользователе. Identity-провайдер смотрит, что у него нет никакой информации по этому запросу, он не знает, авторизован пользователь или нет, и выдает логин-страницу для него. Пользователь вводит свою информацию. Identity-провайдер ее валидирует и как бы говорит «О, все, привет! Я тебя вижу и знаю тебя», а затем отправляет токен обратно через пользовательский браузер редиректом на сайт. После валидации токена сайтом, выдаем пользователю ресурс и с ним — свои cookies. В будущем мы таким образом упростим взаимодействие нашего сайта и пользователя.

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

У этого подхода к аутентификации и авторизации есть два ключевых преимущества:

  • Удобство для пользователя. Он один раз залогинился и получил доступ ко всем необходимым ресурсам без постоянных переходов по разным логин-страницам.

  • Простота менеджмента. Мы со своей стороны можем централизованно управлять доступами. То есть в одном месте настраиваем пользователей, их доступы, роли, скоупы ресурсов и т.д. Это очень удобно для администрирования приложений.

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

Способы реализации flow, которые поддерживает OAuth 2.0

Протоколов для настройки аутентификации и авторизации достаточно много: OpenID Connect, OAuth 2.0, SAML и WSFed. Я остановлюсь на первых двух.

OpenID Connect — это надстройка над OAuth 2.0, которая позволяет проводить верификацию пользователя с помощью авторизационного сервера. Для аутентификации и авторизации пользователей мы можем подключать разные клиенты, веб- и мобильные приложения, JavaScript-клиент для получения информации об авторизационных сервисах и т.д.

Сам же OAuth 2.0 — это протокол авторизации, отвечающий за проверку доступов пользователя. В протоколе OAuth 2.0 есть разные flow для того, чтобы сделать механизм авторизации, который будет указывать, откуда получать информацию и какую конкретно, что и где сохранять:

Client Credentials Flow (он же Machine to Machine или Service to Service). С помощью этого flow можно настроить аутентификацию и авторизацию между несколькими сервисами. Причем не будет никакого взаимодействия с пользователем.

Device Authorization Flow. Подходит для приложений, которые должны работать еще на каком-то устройстве. То есть это не обязательно веб-приложение, а, например, приложение на Smart TV. В нем есть разные утилиты для просмотра онлайн-кинотеатров, видео на YouTube, торрент-видео и т.д. И почти все они сохраняют информацию о просмотрах пользователя и предлагают рекомендации, основываясь на опыте прошлых просмотров, что тоже требует авторизации. 

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

Implicit Flow. Позволяет получать на клиентскую часть Access токен и Refresh токен. Этот механизм можно быстро реализовать, но его безопасность далека от максимальной. 

Ситуацию можно описать так: мы отдаем на клиент наши токены и как бы говорим ему: «Храни наши токены, как хочешь, но мы будем ожидать, что ты будешь приходить к нам с конкретным токеном для получения информации». А потому нельзя быть уверенным в сохранности токенов. Такой flow стоит реализовывать, только если у вас защищенная сеть и нет утечек, когда злоумышленник попадает где-то на середине процессов.

Authorization Code Flow. Этот flow может быть альтернативой предыдущему, поскольку считается весьма безопасным. И хотя в нем клиентская часть знает Client ID и Client Secret, взаимодействие происходит уже с помощью Authorization-кода — это рандомно сгенерированный код. Обычно этот flow рекомендуют использовать для сервер-сайт приложений. Ярким примером является ASP.NET MVC приложение. Влезть в то, что генерируется сервером, сложно даже с какими-либо сторонними библиотеками.

Authorization Code Flow with Proof Key for Code Exchange (PKCE). Это усовершенствованный вариант прошлого flow. В нем происходит генерация еще двух рандомных кодов: Code Verifier и Code Challenge. На авторизацию мы идем с Code Challenge, после введения пользователем своих данных отдаем Authorization Code, за токеном мы идем с только что выданным Authorization Code и плюс с Code Verifier. В результате Identity-провайдер валидирует на основании трех кодов. 

Если злоумышленник вытащит один код из системы, он ничего не сможет сделать с ним — нужны все три кода. Примерами, где можно задействовать такой flow, являются Single Page Applications: Angular приложения, React JS приложения, и нативные приложения под Android/iOS.

Hybrid Flow. Этот гибридный flow объединяет Implicit Flow и Authorization Code. Разработчики попытались усложнить его, чтобы сделать чуточку безопаснее, но он фактически содержит в себе плюсы и минусы обоих «прародителей».

Плюсы и минусы трех популярных Identity-провайдеров

Далее рассмотрим готовые решения для использования в приложениях. Я бы выделила три: IdentityServer 4, Azure B2C и Keycloak.

IdentityServer 4

Этот провайдер поддерживает протоколы OpenID Connect и OAuth 2.0, а также внешние Identity-провайдеры. Можем подключить авторизацию с помощью Google, Facebook, Microsoft, Twitter, Instagram и т.д. Процесс установки и развертывания достаточно простой. Для этого надо создать приложение, установить Nuget-пакеты (IdentityServer4, IdentityServer4.EntityFramework, IdentityServer4.AspNetIdentity), а на клиентскую часть (если, например, MVC приложение в качестве клиента) — пакет IdentityModel. Он поможет нам получать «под капотом» информацию об Access токене и там же перенаправлять запросы, как нам нужно.

Преимуществами данного Identity-провайдера являются:

  • Гибкость настройки и возможность вносить кастомные валидаторы. Так как мы сами создаем приложение и туда инсталим Nuget-пакеты, то можем сами же переопределить, допустим, валидацию токена, если решили, что нужна еще одна дополнительная проверка.

  • Возможность создания UI. Мы можем создавать пользовательский интерфейс для страничек регистрации пользователей, логин-страниц, профиля пользователя и т.д. Существует реализация от создателей провайдера, но она подойдет не под любой случай. Поэтому сейчас IdentityServer 4 поставляется без пользовательского интерфейса, чтобы мы его не перекраивали, а просто сделали свой.

  • Поддержка flow. Он работает со всевозможными flow, которые мы уже рассматривали (Auth Code, Device Flow и т.д.).

  • Детализированная документация. У этого решения очень хорошая документация. Вы можете быстро разобраться со всем функционалом и подключить его. За такую документацию стоит благодарить обширное комьюнити.

  • Бесплатно для коммерческого использования. Не думаю, что стоит как-то особо комментировать этот пункт. Здесь и так понятно преимущество.

  • Подходит для CloudBase и On-Premise решений. Единственное, что стоит добавить к этому пункту: нам самим нужно позаботиться о том, как развернуть его в облаке.

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

Azure B2C

Этот Identity-провайдер поддерживает те же протоколы, что и IdentityServer 4, а также SAML и внешние провайдеры. По умолчанию у него предустановлены еще и пользовательские flow (Sign in, Sign up, Edit Profile, Password Reset), поддержка мультифакторной аутентификации и управление пользовательскими доступами.

Чтобы установить и настроить Azure B2C, потребуется подписка на Azure. Дальше мы создаем B2C Tenant ресурс, регистрируем API и клиентов с помощью App registrations. Чтобы все это подключить, понадобится один Nuget-пакет — Microsoft.Identity.Web, после чего у нас из кода все заведется.

На данном слайде можно оценить дизайн админки этого провайдера и функциональность App registrations. Для примера я создала одну API и два клиентских приложения. Для них формируется удобный список, где можно посмотреть разную информацию (как к ним подключиться, какие есть айдишники, скопы и т.д.). А еще можно добавить какую-то новую регистрацию.

Слева в меню мы видим меню Identity-провайдеров — здесь можно подключить внешние продукты. Есть меню пользователей и меню ролей с детальной статистикой. Мы можем увидеть, насколько часто юзеры логинятся в системе, увидеть их базовые цифры по взаимодействию с системой. И еще отмечу пункт User Flow. Я для примера выбрала парочку, которые созданы в несколько кликов — они предустановленные в Azure B2C. По итогу здесь нет никаких сложностей, когда нужно идти в какие-то конфиги, что-то настраивать и прописывать — с Azure B2C все легко и быстро.

У данного решения следующие плюсы:

  • Легкость конфигурации базовых user flows.

  • Cloud base решение.

  • User management «из коробки».

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

  • Простота старта. Для начала работы нужно совсем немного кода. Все настраивается в несколько кликов на Azure-портале, затем происходит подключение в самом приложении — и все работает уже на базовом flow.

  • Средний порог вхождения.

Несмотря на большое количество плюсов, есть у Azure B2C и минусы:

  • Платное решение. Кроме подписки на Azure, следует упомянуть еще один финансовый момент. Если у нас в течение месяца более 50 тысяч активных пользователей, то за это придется доплачивать. Мультифакторная аутентификация тоже платная и со своими сроками использования.

  • Сложность конфигурации flow. Для изменения даже базовых flow, например, добавления валидации или дополнительной информации, нужно создавать Custom Policy и много работать с конфигурационными XML и т.д.

  • Не подойдет для On-Premise решений. Azure B2C разворачивают только в Cloud, а такие решения обычно даже устанавливаются и там, где может не быть доступа к интернету в принципе.

Keycloak

Поддерживает все те же протоколы, что и Azure B2C: OpenID Connect, OAuth 2.0 и SAML — как и тех же Identity-провайдеров. У него также есть предустановленные пользовательские flow и — что тоже важно — LDAP и Active Directory. С их помощью можно интегрировать пользователей из других систем. Также отмечу предустановленное управление пользователями и их доступами.

Сам Keycloak написан на Java. Но так как сейчас в основном используется кроссплатформенность, и .NET Core является ярким представителем таких технологий, почему бы не попробовать интегрироваться с другим языком программирования? Keycloak как сервис предоставляется с помощью разных площадок (Kubernetes, Podman, Openshift, Docker). Лично я работала из Docker. Там нет никаких сложностей: запускаешь одну команду, чтобы загрузить нужные пакеты, а затем все установилось и запустилось.

Чтобы базово настроить flow авторизации, нужно выполнить следующий сценарий:

  1. Создать realm. Это точно такое же понятие, как и Tenant в Azure B2C, — то есть некая область или группа, в которые мы будем добавлять наше приложение в дальнейшем.

  2. Добавить клиентов. Ими выступают наши приложения, которые должны быть в этой системе.

  3. Добавить конфигурацию для этих приложений.

  4. Создать скопы.

  5. Создать роли.

Ниже вы можете видеть админку Keycloak. В первую очередь здесь приводится список клиентов в системе. Базово для аккаунта у нас есть уже клиент, он создается как часть сервиса. Но я также создала и зарегистрировала свое демо-приложение.

 

После перехода в меню приложения перед вами открывается множество возможностей для его конфигурации. Здесь представлены Client-скоупы, то есть стандартные скоупы (тот же e-mail, профайл и роли), но можно добавить и свои и подключить их на приложения.

В меню слева также собрано много полезной информации: мы можем смотреть и роли, и Identity-провайдеров, и пользователей, и сессии.

Плюсы Keycloak:

  • Гибкая настройка приложений и доступов к ним.

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

  • Stand-alone приложение. Нам не надо заботиться, как его развернуть — все уже хостится само и полностью готово к работе.

  • Подходит для Cloud и On-Premise решений.

  • Бесплатное использование сервиса.

Среди минусов Keycloak:

  • Высокий порог вхождения. Продвинутому пользователю с ним будет проще. Из-за обилия настроек надо детально разбираться, как это все скорректировать.

  • Нет готовых официальных библиотек для .NET Core. Несмотря на это, мы можем из приложений интегрироваться с этим Identity-провайдером через тот же пакет Microsoft.AspNetCore.Authentication.JwtBearer. Он стандартно заложен в .NET Core.

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

  • Все сервисы поддерживают примерно одни и те же протоколы.

  • По стоимости проигрывает Azure B2C из-за оплаты подписки и пользовательской активности.

  • По части .NET Core проигрывает Keycloak. 

  • Насчет менеджмента есть интересный нюанс. В IdentityServer 4 мы можем все реализовать из кода сами (управление ролями, где их передавать и в каком виде). В Azure B2C весь роль-менеджмент проходит через Access Policy. Но роль-менеджмент в Azure-портале распространяется только на сам портал, а не на приложения, которые мы добавляем. А вот Keycloak содержит плюсы обоих Identity-провайдеров. Он позволяет использовать keycloak-роли, чтобы дать юзеру доступ к страничке о пользователе, которая хостится самим Keyclock. В то же время мы можем добавлять роли на ресурсы и пользователям. Таким образом настройка ролей и их добавление происходит более гибко, и в результате роль можно получить из того же токена.

  • По сложности настройки самый замысловатый Azure B2C. Если требуется какой-то базовый вариант, то все относительно нормально, на среднем уровне. Но чтобы что-то поменять, нужно сильно постараться.

В теме авторизации и аутентификации нельзя сказать: выбирайте только один flow, только один Identity-сервер или делайте только так. Более того, приведенные выше варианты — не единственные. Я советую сравнить разные готовые решения, взвесить их преимущества и недостатки и определить, что лучше всего подойдет именно в вашей ситуации.

Также делюсь полезными ссылками на официальную документацию перечисленных Identity-провайдеров: