Какой Identity-провайдер выбрать для реализации технологии Single Sign On
Всем привет! Меня зовут Екатерина Срибна, я 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 авторизации, нужно выполнить следующий сценарий:
Создать realm. Это точно такое же понятие, как и Tenant в Azure B2C, — то есть некая область или группа, в которые мы будем добавлять наше приложение в дальнейшем.
Добавить клиентов. Ими выступают наши приложения, которые должны быть в этой системе.
Добавить конфигурацию для этих приложений.
Создать скопы.
Создать роли.
Ниже вы можете видеть админку 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-провайдеров: