ru:https://highload.today/blogs/gotovogo-resheniya-net-kak-postroit-flou-avtorizatsii-moj-opyt-raboty-v-neskolkih-proektah/ ua:https://highload.today/uk/blogs/gotovogo-rishennya-nemaye-yak-pobuduvati-flou-avtorizatsiyi-mij-dosvid-roboti-u-kilkoh-proyektah/
logo
Оптимизация      07/10/2022

Готового решения нет! Как построить флоу авторизации: мой опыт в нескольких проектах

Микола Коломієць BLOG

NET Developer у NIX

О построении флоу авторизации разработчики задумываются чуть ли не в каждом проекте. Единого правильного решения здесь нет и быть не может.

Хороший авторизационный флоу опирается на особенности бизнес-логики и архитектуры конкретного продукта, цели клиента и технические возможности команды разработки.

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

О чем мы поговорим?

  • Разберем два примера построения авторизационного флоу. В первом случае нашей команде требовалось создать авторизацию по принципу Single Sign On с разделением пермиссий пользователей между разными продуктами. Я покажу варианты решения задачки с конечным дизайном авторизации.
  • Во второй части посмотрим на legacy-проект, где нужно улучшить авторизационный флоу на фоне миграции фичи в Azure. Я опишу, как мы избавлялись от уязвимостей и адаптировали авторизацию под новый функционал. Причем с наработкой под будущую модернизацию продукта.
  • Как результат — вы узнаете, как в разных проектах можно находить интересные решения в зависимости от ваших условий и специфики задач.

Проект №1

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

Настроить такую ​​возможность и было нашей задачей. Вот только пермиссии на каждом домене для каждого пользователя разные. Где-то пользователь может создавать новые страницы, где только просматривать имеющиеся. Это явилось для нас главной сложностью при реализации авторизационного флоу. Прежде чем объяснить, как мы воплощали принцип Single Sign On, кратко напомню, как он работает.

Single Sign On — это технология, позволяющая авторизироваться один раз для использования нескольких продуктов.

Курс-професія "Junior Data Analyst" від robot_dreams.
Комплексний курc для всіх, хто хоче опанувати нову професію з нуля.На прикладі реальних датасетів ви розберете кожен етап аналізу даних.
Програма курсу і реєстрація

К примеру, есть решение Microsoft. Вы передаете креды для входа в аккаунт только раз, а затем открываете любые связанные ресурсы: OneDrive, Office и т.д. Это упрощает жизнь пользователя и экономит его время.

Что необходимо для реализации SSO? Берем браузер-клиент, два домена и единственный авторизационный сервер, где хранятся пользователи обоих доменов:

  • Когда неавторизованный пользователь пытается получить доступ к первому домену, происходит редирект на авторизационный сервер. Там обычно проверяются cookies клиента.
  • Если они чисты (т.е. пользователь еще не авторизовался на этом сервере), ему необходимо ввести креды — логин и пароль.
  • Информация об успешной авторизации хранится в cookies, система возвращает пользователя на первый домен — и пользователь может им пользоваться.
  • Благодаря записи в cookies при повторном мероприятии на этот домен пользователь сразу попадет в свой аккаунт.

Далее он обращается ко второму домену. Юзер там не авторизован, поэтому система перенаправляет его на тот же единственный авторизационный сервер. Он снова проверяет cookies, видит старую запись об успешной авторизации и открывает доступ и ко второму домену. Опять же без введения кредов.

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

Онлайн-курс "Computer Vision" від robot_dreams.
Застосовуйте Machine Learning / Deep Learning та вчіть нейронні мережі розпізнавати об’єкти на відео. Отримайте необхідні компетенції Computer Vision Engineer.
Дізнатись більше про курс

Но с авторизационным флоу возникли сложности сразу в нескольких моментах:

  • Динамические пермиссии для пользователей. Права пользователя на те или иные действия внутри продукта могут назначаться «на лету», комбинироваться и находиться в составе разных групп. То есть пермиссия — это не просто роль, предназначенная пользователю. Пользователь может просматривать страницы пациентов, но не может их обновлять. Или же будет обновлять, но не создавать новых пациентов. В таком случае SSO не подходит, ведь с ним роли статические, а пермиссии фиксированы.
  • Различные пермиссии на разных продуктах. Для каждого из трех доменов внутри проекта набор и структура пермиссий могут отличаться. Это также усложняет единый вход по принципу Single Sign On.
  • Невозможность смены авторизационного сервера. Мы не могли доработать KeyCloak под наши потребности. Ведь в состав сервера входят не только эти три продукта, но и другие. Модифицировать структуру нельзя, хотя при необходимости достаточно расширить сервер.
  • Производительность. Перфоманс должен быть высоким, а это было под вопросом. Скорость обработки запросов, прохождение авторизации и распределения пермиссий могли замедлить процесс, что вообще неприемлемо.

Учитывая эти проблемы и технические возможности, наша команда начала искать решения в рамках SSO. О каждом из путей расскажу по отдельности.

Авторизационный флоу с репликацией

Этот вариант показался очевидным. Что нас натолкнуло на такой выбор, так это использование в проекте репликации, когда один продукт копирует данные с другого. Тогда флоу выглядел бы следующим образом:

  • пользователь проходит авторизацию на KeyCloak;
  • Онлайн-курс "Digital Marketing" від Laba.
    Розширте пул навичок у роботі з аудиторією.Навчіться запускати рекламні кампанії без зайвих витрат бюджету з сучасними інструментами діджитал-маркетингу, включаючи AI.
    Детальніше про курс
  • получает Bearer Token;
  • и дальше с ним переходит на любой из трех продуктов.

На этом этапе понадобится Authorization Service — хранилище пермиссий. Все три сервиса, с которыми общается клиент, будут использовать данные Authorization Service и реплицировать пермиссии. Они могут храниться как в базе данных, так и в кэше.

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

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

Но и у этого подхода есть недостатки:

  • Дублирование больших массивов данных. Каждый продукт копирует информацию пользователей. Из-за этого в системе возникает экстраколл к БД или кэшу для получения пермиссий конкретного пользователя. Это серьезно ударит по перфомансу сервиса.
  • Необходимость разработки механизма отображения пермиссий в UI. К примеру, если пользователю запрещено создавать новых пациентов, то в меню нужно блокировать кнопки, отвечающие за это действие.
  • Онлайн-курс "Створення електронної музики" від Skvot.
    Практичний курс про те, як знайти власний стиль та написати й зарелізити свій перший трек.
    Програма курсу і реєстрація

Так что мы снова начали размышлять над оптимальным решением…

Авторизационный флоу с информацией в Bearer-токене

Следующий вариант — размещение информации о правах пользователя в Bearer Token. При авторизации пользователя KeyCloak может получить пермиссии из хранилища Authorization Service.

Сценарий получился бы следующим: пользователь вводит логин и пароль, генерируется Bearer-токен, и в него записываются предназначенные авторизованному юзеру пермиссии.

Когда клиент пошлет запрос на тот или иной продукт, сервис уже на своей стороне сам валидирует его:

Вот два ощутимых плюса:

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

Но и в этом варианте была пара серьезных недостатков:

Курс Python від Mate academy.
Python дозволяє тобі не тільки розробляти сайти та займатись аналітикою даних, а ще й будувати алгоритми, тестувати програми та навіть створювати штучні інтелекти. Стань різноплановим фахівцем!
Реєстрація на курс
  • Размер токена. При большом количестве пермиссий Bearer-токен может превысить допустимое значение хедеров в запросе. Это потенциально серьезная проблема. При этом реальной потребности в переносе пермиссий нет. Пользователь может переходить с токеном на другие продукты. Как показали наши эксперименты, при добавлении пермиссий мы не достигли даже половины допустимого размера хедера. Сказалась ограниченное количество политик на проекте. Но он не будет значительно увеличиваться в будущем.
  • Отсутствие обновления пермиссий. Получив токен, пользователь может оставаться долго в системе. Если в течение этого периода пермиссии изменятся, это никак не отразится на токене и возможностях работы с сервисом. То есть если право на определенные деяния пользователя уже отозвано, он все равно сумеет их делать.

Итак, продолжаем поиски дальше…

Авторизационный флоу со вторым токеном

Оптимальным для нас вариантом оказалось добавление в систему еще одного токена. В таком случае после ввода логина и пароля в KeyCloak клиент получает с авторизационным Bearer-токеном еще и JWT Auth Token.

Именно в нем и содержится информация о пользовательской пермиссии (в пределах одного продукта). Далее клиент с парой токенов отправляется к любому продукту, который сам и будет валидировать оба «ключа»: отдельно для авторизации и определения прав пользователя:


Есть следующие преимущества:

  • Отсутствие дублирования. Как и в прошлом сценарии, здесь нет ненужного копирования данных и сложной логики.
  • Привязка пермиссий к продукту. Отдельный JWT Auth Token работает только в одном продукте и не дублируется на весь сервис.
  • Простая интеграция в систему. Для внедрения такого механизма не нужно изменять авторизационный флоу и писать отдельную логику для реплицирования данных.
  • Онлайн-курс "Корпоративна культура" від Laba.
    Як з нуля побудувати стабільну корпоративну культуру, систему внутрішньої комунікації та бренд роботодавця, з якими ви підвищите продуктивність команди, — пояснить HR-директор Work.ua.
    Детальніше про курс

Издержки у этого флоу тоже были. Но ситуация оказалась некритической из-за определенных обстоятельств:

  • Дополнительный шаг в авторизации. Необходимо добавить механизм получения пользователем второго токена. Впрочем, для модернизации флоу с KeyCloak нам, так или иначе, пришлось бы писать новые логики и инструменты. Этот вариант — самый сложный для реализации с учетом его преимуществ.
  • Лаг при обновлении пермиссий. Это тот же риск, что и в предыдущем флоу. Но для нашего заказчика это не проблема. Сценарии использования всех трех продуктов фармацевтического сервиса предполагают частое сложение прав пользователей, но реже — лишение их этих прав. Поэтому маловероятна ситуация, когда пользователя ограничили в возможностях, а он все равно имеет определенные доступы. Если он получает новые права с текущим токеном, то ему нужно заново ввести логин и пароль. Тогда у пользователя будет токен с обновленными пермиссиями. Проблема сама по себе не решается, но это не трагично для этого проекта.

Дизайн авторизационного флоу

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

Как показано на схеме ниже, вся система состоит из нескольких основных элементов. Первый — это клиент или UI. Также есть авторизационный сервер KeyCloak. За ним следует Istio, представляющий Gateway Load Balancer. Для кэша предусмотрен Redis. Еще есть User Service, выполняющий роль упомянутого Authorization Service, хранилища для пермиссий. Последним здесь идет Service — это остальные сервисы, к которым присылают запросы на какую-то информацию.


Авторизационный флоу организован следующим образом:

  • Пользователь логинится на авторизационном сервере.
  • Далее выполняет запрос, допустим, посмотреть данные о пациенте. Для этого Istio пытается получить JWT-токен. Это выполняет балансер, а не клиент, что делает последний очень легким.
  • Если запрашиваемого балансером токена нет в Redis, этот ключ генерируется и сохраняется в кэш. Если же такой токен в кэше наличествует, он извлекается в ответ на запрос от Istio.
  • Онлайн-курс "PR Basis" від Skvot.
    Дізнайся нюанси різних сфер і обрери свою.Як результат — матимеш стратегію бренду у своєму портфоліо та зможеш стартувати в піарі. Інсайтами ділиться лекторка, яка має 9+ років досвіду.
    Детальніше про курс
  • После этого JWT-токен добавляется в хедер запроса, и выполняется запрос на получение нужной пользователю информации.

Замечу, что в нашем проекте эта система имплементирована не до конца, поскольку пока нет процесса кэширования второго токена. Но мы добавим это в будущем и приведем процесс к идеалу.

Проект №2

Здесь мы имеем дело с многолетним legacy-проектом. В какой-то момент понадобилось перенести его на Azure. В этом случае центральная часть — это Image Service, хранилище изображений пользователей. Они могут загружать картинки и фотографии, просматривать и редактировать их. Клиентами выступают два элемента: веб-клиент и десктопное приложение. 

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

Авторизационный флоу в legacy-проекте

Начальная авторизация в Image Service сделана просто. При попытке загрузить изображение в хранилище в теле запроса отправлялись три поля: специальный ключ и Поле 2 и Поле 3.

Первый ключ — единственная для всех пользователей и системы GUID-стринга. Она выполняла роль валидации по пользователю и его запросу. Поле 2 и Поле 3 помогали аутентификации и использовались для группирования картинок в папки:

Эта система имела много рисков:

  • Один специальный ключ на систему. В случае его кражи будет скомпрометирован весь сервис.
  • Курс-професія "Копірайтер" від Skvot.
    40 занять — і ти з упевненістю, скілами та портфоліо зможеш тиснути Apply на вакансії копірайтера.Досвідом і ключами поділяться 2 лекторки та запрошені спікери.
    Детальніше про курс
  • Статические параметры. Указанные параметры для добавления картинок не динамичны. Это ограничивает функционал и снижает безопасность.
  • Нестандартный протокол. Флоу выполнен не по привычным канонам, не покрывает всех аспектов безопасности и может вызвать вопросы у новых разработчиков.

Хотя в целом система работала и устраивала заказчика… Пока не возник вопрос миграции загрузок и хранения изображений на Azure. С основной частью функционала было понятно: мы частично переиспользовали логику из легаси-системы. Но авторизационный флоу стоило улучшить.

Миграция фич на Azure

Для контекста коротко расскажу о самой миграции. При загрузке фотографий Azure общается с легаси-системой для сохранения определенных метаданных.

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

Ключевым же фактором было сохранение клиентов во время миграции на Azure. Упомянутые веб-клиент и десктопное приложение не изменяли свои контракты, логику и процессы. Изменения могли затрагивать только Subscription Key и не более. Поэтому наша команда создала сразу два решения: промежуточное для «здесь и сейчас» и более дальновидное:


Дизайн авторизационного флоу

На сегодняшний день для авторизации на Azure мы используем API Management. Эта система может проксиировать запросы и объявлять сценарии выполнения. То есть, в какой последовательности добавлять данные или хедеры, как модифицировать запросы и т.п. Причем, первым шагом в API Management является получение JWT-токена. Это происходит за теми же полями, которые изначально были в легаси-проекте. Единственное исключение — Subscription Key. Мы избавились от него и добавили свой ключ, который может быть динамичным.

Валидирует его непосредственно API Management:

После получения JWT-токена система передает в ажуровскую Auth Function параметры авторизации пользователя. Речь идет об упомянутых выше Поле 2 и Поле 3. По этим значениям функции происходит извлечение JWT-токена из Redis, если раньше он был там размещен.

Онлайн-курс "Business English for Marketers" від Laba.
Опануйте професійну англійську для маркетингу.Розширте карʼєрні можливості для роботи з іноземними колегами: від розробки нових продуктів до презентації стратегії бренду.
Детальніше про курс

Если же токена в хранилище отсутствует, выполняется запрос к легаси-системе из Image Service по поводу валидности запроса по указанным параметрам. При подтверждении генерируется новый JWT-токен. Потом он размещается в Redis, а оттуда возвращается в API Management.

Как работает API Management

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

Чтобы лучше объяснить идею, покажу пример кода API Management. Система описывается простым XML-файлом:

Здесь есть первая проверка, где из реквеста из хедеров достается Subscription Key. Это именно то, что валидирует сам API Management. Он его сравнивает со своей переменной окружающих. В нашем случае это как раз сгенерированный самим API Management ключ. То есть он проверяет, есть ли такой ключ в запросе. Если есть, система переходит к следующему шагу — send-request:

Запрос отправляется в Auth Function для получения JWT-токена. Для этого создается запрос и передается тело с необходимыми параметрами. А дальше функция возвращает либо закэшированный, либо сгенерированный токен. Его природа не важна — важно возвращение функцией этого ключа:

Затем этот токен с добавлением Bearer сохраняется. Здесь доступен такой функционал как set-header к запросу. Благодаря этому мы можем сетить общепринятый хедер Authorization для Bearer-токена:

Онлайн-курс "Data Science with Python" від robot_dreams.
Навчіться користуватися бібліотеками Python для розв’язання задач дата-саєнтистики, обробки масивів даних та побудови ML-моделей.
Програма курсу і реєстрація

Появляется validate-jwt, позволяющий валидировать авторизационный токен, созданный на предыдущем этапе. В случае успешной валидации запрос посылается уже в Azure Function:

Обратите внимание: все это производится только для десктопного приложения. Веб-клиент этого не требует — там и без того безопасный канал общения. Далее остается выполнить запрос:

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

А дальше обновим API Management, и на этом модернизация мигрировавшей в Azure системы закончится. Все готово к изменениям в виде самостоятельной авторизации клиентом с помощью JWT-токена.


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

Основи Python для школярів від Ithillel.
Відкрийте для вашої дитини захопливий світ програмування з нашим онлайн-курсом "Програмування Python для школярів". Ми вивчимо основи програмування на прикладі мови Python, надаючи зрозумілі пояснення та цікаві практичні завдання.
Зареєструватися

If you have found a spelling error, please, notify us by selecting that text and pressing Ctrl+Enter.

Онлайн-курс "Створення текстів" від Skvot.
Великий практичний курс для розвитку скілів письма та створення історій, які хочеться перечитувати Результат курсу — портфоліо з 9 робіт та готовність братися за тексти будь-яких форматів.
Детальніше про курс

Этот материал – не редакционный, это – личное мнение его автора. Редакция может не разделять это мнение.

Топ-5 самых популярных блогеров марта

PHP Developer в ScrumLaunch
Всего просмотровВсего просмотров
2434
#1
Всего просмотровВсего просмотров
2434
Founder at Shallwe, Python Software Engineer (Django/React)
Всего просмотровВсего просмотров
113
#2
Всего просмотровВсего просмотров
113
Career Consultant в GoIT
Всего просмотровВсего просмотров
95
#3
Всего просмотровВсего просмотров
95
CEO & Founder в Trustee
Всего просмотровВсего просмотров
94
#4
Всего просмотровВсего просмотров
94
Рейтинг блогеров

Ваша жалоба отправлена модератору

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: