Как внедрить двухфакторную аутентификацию в веб-приложения, где ее изначально не было
Большинство современных веб-приложений поддерживают двухфакторную аутентификацию (2FA), но бывают случаи, когда такой функции нет. В этой статье я расскажу, как добавить 2FA в веб-приложения, где ее изначально не было. Способ, который я опишу, подойдет для большинства случаев.

В облачной инфраструктуре Cloud.ru используется несколько решений от вендоров, например, Cloud Director Availability и Horizon от VMware, Cloud Connect и Service Provider Console от Veeam и некоторые другие. Но в них либо вообще не предусмотрено двухфакторной аутентификации, либо реализация 2FA не устроила нас из-за сложного обслуживания оборудования или рисков для безопасности.
Например, Veeam Cloud Connect — приложение, которое работает в рамках нашей услуги «Резервное копирование в облако». Консоль сервиса позволяет администраторам управлять заданиями резервного копирования и отслеживать их статус. Это все происходит в тесной связке с VMware Cloud Director (vCD).
Часть наших клиентов использует Self-Service портал для управления услугой. Но в Veeam не получится защитить этот портал через 2FA путем подключения к SAML: аутентификация возможна только с локальными учетными записями, SAML для верификации пользователя подключить нельзя. От технической поддержки вендора мы получили такой ответ:
Я проверил нашу внутреннюю документацию и провел несколько тестов: к сожалению, BEM Self-Service портал для vCD не поддерживает SAML-аутентификацию. Как обходное решение, я могу предложить настроить SAML-аутентификацию в самом vCD, но работать это будет только при использовании Self-Service портала из консоли vCD: https://helpcenter.veeam.com/docs/backup/em/vcd_portal_access.html?ver=120#accessing-veeam-self-service-backup-portal-from-vmware-cloud-director
Также в нашей системе открыт Feature Request для добавления данного функционала. К сожалению, на данный момент, сроки внедрения данного функционала неизвестны.
С уважением,
Техническая поддержка Veeam

В итоге мы не можем повлиять на вендора и изменить код ПО, чтобы улучшить безопасность. Выход — защитить канал, который дает пользователям доступ к приложению. Часто для этого используют VPN, потому что VPN-клиенты поддерживают интеграцию с системами, которые перед подключением проверяют второй фактор. Однако в способе с VPN есть проблема с удобством и доступностью: надо устанавливать и настраивать VPN-клиент на ПК наших клиентов. Это не всегда удобно или противоречит политике безопасности компании, которая запрещает устанавливать стороннее ПО.
Чтобы решить эти проблемы, мы в Cloud.ru мы использовали другой способ: развернули систему для двухфакторной аутентификации, которую построили на Reverse Proxy с поддержкой OpenID и IAM (Identity Access Management).
Об аутентификаторе на Reverse Proxy и IAM
В этом разделе расскажу, из чего состоит наше решение, как оно работает, какие у него преимущества и возможные недостатки.
Основные компоненты
Чтобы обойти технические ограничения вендорского ПО и усилить защиту каналов доступа, мы использовали:
Reverse Proxy с поддержкой OpenID Client. Работали с находящимся в открытом доступе OAuth2 Proxy и разместили его в DMZ. Прокси проверяет запросы пользователя на наличие валидного токена аутентификации и перенаправляет пользователя в IAM, если он отсутствует или просрочен.
IAM (Identity Access Management) в роли OpenID-провайдера. С его помощью мы верифицируем оба фактора пользователя: пароль и одноразовый пин. Мы используем IAM собственной разработки, но у себя в инфраструктуре вы можете выбрать любой другой доступный: ADFS, Google, Keycloak или другой провайдер, который поддерживают OAuth2 Proxy.
Схема работы аутентификатора
Сначала пользователь в браузере открывает веб-приложение (на схеме ниже — 1). OAuth2 Proxy обрабатывает запрос: проверяет, есть ли сессионный cookie и насколько он актуален. Если все в порядке и cookie валиден, трафик проходит через прокси-сервер и идет в приложение (6). Если cookie пока нет или он просрочен, прокси направит пользователя на веб-страницу IAM (2).
Далее IAM запрашивает у пользователя первый фактор для аутентификации — у нас это логин и пароль от аккаунта в личном кабинете Cloud.ru (3). Эти данные могут быть другими в зависимости от потребностей компании, например, логин и пароль Active Directory. На следующем шаге запрашивается и проверяется второй фактор — одноразовый код (4), сгенерированный на телефоне в Google Authenticator, код из СМС или QR.
Если пользователь предоставил верные данные, IAM вернет OAuth2 Proxy информацию об успешной аутентификации (5), после чего прокси сгенерирует cookie и перенаправит трафик в веб-приложение (6). Пользователь этого процесса не заметит — он увидит в браузере приложение, к которому подключался изначально.

Плюсы и минусы решения
Пройдемся по преимуществам и недостаткам нашего аутентификатора на базе OAuth2 Proxy.
Плюсы подхода:
Простота реализации. Для запуска хватит виртуальной машины на Linux, бесплатного и размещенного в открытом доступе OAuth2 Proxy и любого OTP-приложения у пользователя: Google Authenticator, Яндекс.Ключа или Microsoft Authenticator. При этом в компании уже должен быть какой-то провайдер 2FA.
Независимость от вендора приложения. С нашим способом можно сделать двухфакторную аутентификацию даже если есть legacy-приложения в виде вендорских продуктов без возможности их изменить.
Удобство обслуживания. Мы, будучи провайдером, можем не закупать и не развозить физические токены и считыватели — все можно установить удаленно. А клиенту не нужно никакое дополнительное ПО на ПК, так как все настраивается в браузере и телефоне.
Безопасность. Двухфакторная аутентификация делает доступ в приложение более защищенным, а решение из статьи при наличии IAM в компании позволяет относительно быстро и дешево это реализовать.
У решения есть и минусы:
Возможный запрет от службы безопасности на использование OAuth2 Proxy. Сотрудники СБ в некоторых компаниях настороженно относятся к open source решениям, особенно если речь о зарубежных разработчиках.
Ограничения на интеграцию Single Sign-On (SSO). Иногда может не получиться настроить вход с единоразовым вводом идентификационных данных, то есть логина и пароля. Это уменьшит удобство аутентификатора: пользователь должен вводить логин и пароль дважды: на IAM-странице и в веб-приложении.
Развертывание Oauth2 Proxy в режиме Reverse Proxy
Расскажу о ключевых моментах, на которые надо обратить внимание перед развертыванием OAuth2 Proxy в режиме Reverse Proxy. Здесь не буду затрагивать установку и настройку IAM и подготовку инфраструктуры.
Перед установкой прокси-сервера надо сделать следующее:
Настроить IAM на работу по протоколам OpenID. Для этого понадобятся:
oidc_issuer_url — URL конфигурации OpenID. Пример для Keycloak: http://keycloakhost:keycloakport/auth/realms/{realm}/.well-known/openid-configuration;
client_id — идентификатор OpenID Client, который согласован и зарегистрирован в IAM;
client_secret — сложная парольная фраза.
Еще OAuth2 Prox и IAM можно настроить для работы по протоколам SAML, но в рамках этой статьи я говорю только об OpenID.
Зарегистрировать пользователя в IAM, включить ему двухфакторную аутентификацию. Настроить на телефоне пользователя OTP-приложение, например, Google Authenticator или Яндекс.Ключ.
Настроить виртуальную машину или физический сервер, чтобы установить туда OAuth2 Proxy. Для этого нужно:
выбрать и установить операционную систему — для OAuth2 Proxy на GitHub вы найдете готовые сборки для Linux, FreeBSD. Также доступны Docker Image и Kubernetes manifest (Helm);
сконфигурировать сетевые интерфейсы;
обеспечить сетевую связность между OAuth2 Proxy, IAM и защищаемым приложением;
настроить и проверить интернет-соединение, чтобы без проблем скачать дистрибутивы.
Зарегистрировать A-запись в DNS. Через нее пользователи будут подключаться к приложению (публичный интерфейс OAuth2 Proxy). Эта же запись потребуется при настройке IAM, адрес нужно будет использовать как Valid Redirected URL.
Выпустить SSL-сертификат и ключ. Они будут покрывать доменное имя, которое вы выбрали в пункте выше.
Подключение 2FA на виртуальной машине
В этом примере рассмотрим установку решения на OAuth2 Proxy для ВМ на Ubuntu 20.04.
В инструкции используются следующие адреса, которые вам надо заменить на свои:
Адрес IAM — https://iam.company.ru/auth/system
Внешний адрес приложения — https://webapp.company.ru
Внутренний адрес приложения — https://webapp.localcompany.ru (доступен только внутри локальной сети).
Пошаговая инструкция по запуску и установке:
1. Создайте каталог для установки
2. Скачайте архив с дистрибутивом
Актуальные ссылки для вашей операционной системы есть на GitHub. В этом примере мы установили v7.5.0:
3. Распакуйте архив и установите права
На этом шаге извлеките загруженный архив и сделайте файл исполняемым:
4. Сгенерируйте Cookie Secret
Понадобится для использования в файле конфигурации. Cookie Secret надо сгенерировать и сохранить:
5. Создайте файл конфигурации
Откройте редактор и создайте файл. Можно взять наш — пример приведем ниже. Еще есть вариант на GitHub от OAuth2 Proxy. Полный список настроек доступен в документации.
Обратите внимание: в документации команды приведены в синтаксисе для CLI (flag) и для файла конфигурации (toml) — они отличаются по оформлению. Так как мы используем файл конфигурации, ниже указали необходимые параметры в toml формате.
Пример файла конфигурации (oauth.cfg):
6. Запустите прокси и проверьте его работу.
Запустите OAuth2 Proxy с помощью команды:
7. Откройте в браузере внешний адрес вашего приложения https://webapp.company.ru. При корректной работе OAuth2Proxy автоматически перенаправит на страницу IAM:

После успешной аутентификации система автоматически запрашивает второй фактор.

Пользователь получит доступ к сайту только после того, как успешно пройдет проверку обоих факторов. В IAM настраивается количество попыток ввода и последствия, если введенная информация будет некорректна. Обычно это блокировка не некоторое время, уведомление пользователя и администратора о попытке подобрать пароль.
7. Настройте автоматический запуск сервиса
Если на предыдущих этапах все успешно, надо настроить автоматический запуск при загрузке системы. Для этого надо добавить Unit в systemd:
8. Запустите сервис.
Для этого нужна следующая команда:
9. Включите автозапуск при рестарте операционной системы
Готово!
Теперь сервис автоматически запустится при старте системы и обеспечит стабильную работу с двухфакторной аутентификацией.
Подведем итоги
Аутентификатор позволил без больших затрат финансов и времени внедрить 2FA в приложение, где этого функционала изначально не было. Так как за основу взят бесплатный прокси, нет нужды закупать дорогостоящее ПО. А еще решение обеспечивает удобный доступ к веб-приложениям в согласии с современными требованиями к безопасности аутентификации.