Привет! Меня зовут Артем Ивлев, и я занимаюсь архитектурой идентификации клиентов банка ВТБ.
Наша задача — ответить на вопрос, кто пользуется нашим банковским сервисом: мобильный или онлайн-банк, голосовой помощник или просто один из многочисленных офисов.
Для этого существует множество инструментов — и я хочу рассказать о разработке одного из них.
Пролог На дворе 2019 год, банковская экосистема растет семимильными шагами, и нам все больше нужна единая точка входа для клиентов и поставщика удостоверений.
Но есть только каталог аккаунтов и отдельные решения для разных команд аутентификации.
У нас еще не было требований, как все должно выглядеть.
При этом мы сразу заговорили об аутентификации физических лиц не только в онлайн-банкинге, но и на партнерских ресурсах.
Та же кнопка «Войти через ВТБ».
Вот как будет выглядеть вход через ВТБ Из этого следовало, что нам нужно взять самое универсальное решение и начать его использовать.
В процессе использования мы могли узнать, что именно нам нужно, каких функций не хватает и т.д. Мы выбираем, по какому пути мы пойдем Порывшись в интернете и покурив магические квадраты Gartner, мы начали искать решения с открытым исходным кодом и поддержкой в России: • Сервер идентификации WSO2 • Кейклоак • ОпенАМ Судя по отзывам в сети и документации, решение от WSO2 с шиной для возможности подключения нескольких провайдеров аутентификации, провайдеров пользовательских данных и т.д. показалось нам наиболее универсальным.
Архитектура сервера идентификации WSO2 Первый прототип мы показали еще в 2019 году на общей демонстрации розничного бизнеса.
Есть серебряная пуля (извини, Брукс) — это символ.
Первое, что мы поняли, это то, что в OAuth 2 лучше всего использовать токен JWT ID, который не требует обращения к серверу аутентификации для проверки при каждом запросе.
Короче говоря, JWT — это пирамида из трёх частей: 1. Заголовок (HEADER) сообщает, что это за токен, как он был подписан и кем выпущен.
2. Тело (PAYLOAD) — набор параметров — позволяет узнать, каким сервисом и для какого пользователя был выдан этот токен, как долго этот токен будет жить.
3. Криптографическая подпись (SIGNATURE) позволяет проверить, что данные в теле токена не были изменены и что токен был выпущен сервером идентификации, которому мы доверяем.
Структура веб-токена JSON (JWT) Все эти части представляют собой одну большую линию, разделенную точками на блоки.
Первые два блока кодируются с использованием алгоритма Base64. Использование токена JWT ID значительно облегчило жизнь: при каждом запросе с мобильного устройства или браузера вам больше не нужно было идти в базу данных и проверять, кому и когда был выдан токен.
Вся информация находится в самом токене.
Достаточно просто разместить перед потребителями API-шлюз, который будет проверять подпись токена с помощью открытого ключа.
Как добить пулю напильником Токен, выданный на X минут, будет действителен, даже если пользователь нажмет «Выйти» или система безопасности банка получит сигнал о срочном выходе этого пользователя из приложения.
Решение было придумано давно — хранить списки отозванных токенов и проверять их на уровне API Gateway. Да, это тоже сверка с базой данных, но здесь набор значительно меньше и его можно легко реализовать на кэше Redis с помощью TimeToLive. Как мы можем помешать злоумышленникам украсть токен, выданный конкретному мобильному приложению или браузеру пользователя? Ведь технически у пользователя можно что-то украсть из браузера и даже из приложения.
То есть нужно сделать так, чтобы злоумышленник, даже украв токен, не смог им воспользоваться.
Кадр из заставки мультсериала «Симпсоны».
Как обычно, проблема не нова и ее решение «уже было в «Симпсонах» ((с) «Южный парк»).
Создаем безопасный файл cookie (HttpOnly, SameSite, Secure) и помещаем в него UUID. Затем делаем из этого UUID хэш, например CRC32, и помещаем его в тело JWT. Вот и все.
Теперь достаточно при каждом запросе проверять, что хэш от нашего cookie равен написанному в теле токена.
Безопасный файл cookie труднее украсть, поэтому пара токен-файл cookie дает нам достаточную уверенность.
Адаптивная аутентификация, или Почему нам пришлось пойти своим путем В процессе входа пользователя в систему задействовано много дополнительной магии.
Сюда входит и проверка пользователя, его устройства, статистики входов, географии, и аудит действий, и открытие сессий в задних системах, и выяснение необходимости второго фактора, и выбор этого самого второго фактора (СМС, пуш, что-то еще).
Это задача адаптивной аутентификации.
И, с одной стороны, использование модуля позволяло вводить все эти задачи с помощью скриптового интерфейса WSO2 IS, но, с другой стороны, невозможно было реализовать красивый API для мобильных устройств или SPA. Дело в том, что вся адаптивная аутентификация происходит на уровне сервера по мере генерации интерфейсов с помощью JSP. Это сложно адаптировать даже для современной веб-разработки, не говоря уже об API для мобильного приложения.
После первых прототипов и попыток адаптировать универсальность под пожелания коллег с мобильных и веб-платформ, мы поняли, что эту часть придётся переписывать.
Для мобильного приложения и онлайн-банкинга мы решили реализовать всю логику, используя всего один хендл API/oauth2/токена — в зависимости от входящих параметров он выдает токен или ошибку с просьбой перейти к нужному шагу второго фактора.
запрос.
Мы решили реализовать бизнес-логику непосредственно в Grant_type — параметре /oauth2/token, который отвечает на вопрос о требуемом типе аутентификации.
В результате мы получили стройную логику.
Есть поставщик услуг — потребитель аутентификации.
Имеет настройки, в том числе набор типа гранта.
Таким образом, мы прекрасно понимаем, кто и под какими логинами может к нам зайти.
Все, что не роняет продукт, делает нас сильнее Следующей проблемой, которую мы обнаружили, была низкая производительность из-за довольно сложного использования базы данных для сценария аутентификации, где мы контролируем «что и почему» на уровне нашего кода.
WSO2 IS слишком много читает и записывает в базу данных.
Нам пришлось заново переписать часть логики генерации токенов.
Сессии были удалены из PostgreSQL в Redis. Это снизило нагрузку на основание на порядок.
Комментарии не нужны :) Но, как оказалось, этого тоже недостаточно.
Зависимость от самой базы для такого критического сервиса – далеко не лучшее решение.
Если база данных падала или становилась недоступной (где в основном хранятся настройки и выданные токены, мы уже удалили оттуда сессии), мы не могли пустить пользователя в банк.
Добавлена проверка, если база данных недоступна - выдавать токены в экстренном случае, если их невозможно продлить через пять минут. То есть пользователи по-прежнему смогут работать в приложении банка — но только пока жив первый выпущенный токен.
Следующим шагом стал переход от двух дата-центров из режима активно-активный в режим активно-пассивный, что снизило риски рассинхронизации PostgreSQL и Redis. В худшем случае, если дата-центр выйдет из строя, некоторым пользователям придется заново заходить в приложение.
Ну и последний гвоздь в коде выпуска токенов — решение полностью переписать остатки WSO2 IS. Последняя версия вообще больше не взаимодействует с базой данных во время аутентификации пользователя.
Остается только Redis, в котором хранятся сеансы аутентификации, JWT и выданные в них токены обновления.
Что дальше? Новые горизонты Когда токен будет выпущен, от вендора WSO2 IS останется так мало, что вскоре мы сможем перейти от монолита, который может делать слишком много, к микросервисам, которые могут делать только то, что нам нужно, и с той производительностью, которая нам нужна.
Теперь у нас есть доступ к банковскому приложению в мобильной и веб-версии.
Но этого недостаточно.
Ведь у ВТБ есть много других продуктов.
Это «Мультибонус», «ВТБ Мобайл» и десятки, если не сотни других наших проектов.
Все требуют аутентификации и единой точки входа.
Кадр из мультсериала «Рик и Морти» А еще очень много внешних партнеров и поставщиков, которые, конечно, будут только рады «четким» пользователям с паспортом и другими данными.
Поэтому мы работаем над единым логином ВТБ.
Это даст пользователю возможность максимально безопасно и удобно идентифицировать себя в каршеринге, страховке, стриминге или «Рогах и Копытах» (согласитесь, проще нажать на кнопку «Войти через ВТБ», чем брать фото паспорта и введите данные вручную).
А для потребителя аутентификации ВТБ это очень удобный способ идентифицировать и предоставить данные пользователя в соответствии с федеральным законодательством.
Эпилог Прошел почти год с тех пор, как наши первые релизы пошли в производство.
Решение развивается и приобретает новые возможности.
Разве мы не должны были сразу же начать писать свои собственные? Была ли вообще необходима WSO2? История не терпит сослагательного наклонения, но я думаю, что в условиях крайне сжатых сроков и итеративной разработки нам, скорее всего, ничего не удалось бы сделать - а даже если бы и удалось, то это не дошло бы до наших стандартов и не имело бы позволили нам развиваться дальше.
Поэтому мы выбрали вендорское решение и одновременно использовали его для развития собственных достижений и компетенций команды — и это дало отличный результат. ПС: Буду рад обсудить вопросы о SSO, токенах и аутентификации в целом.
ЗЗЫ: О чем вы хотите прочитать в следующий раз? Аутентификация, биометрия или цифровой профиль и использование Tarantool Data Grid? Теги: #информационная безопасность #oidc #аутентификация #vtb #SSO #oauth2 #wso2
-
Межзвездная Коммуникация
19 Oct, 24 -
Утилита Winknock
19 Oct, 24 -
Путь К Активной Ссылке
19 Oct, 24 -
Размышления На Тему Аутсорсинга!
19 Oct, 24