Представьте сотрудника, который утром открывает панель мониторинга. Его перебрасывает на страницу Authentik, он вводит пароль, подтверждает второй фактор и попадает в панель. Через час он открывает вторую внутреннюю панель, например админку очередей, и входить заново не нужно: браузер уже несёт сессию Authentik, а сервис её принимает. Выглядит как единый вход, и ощущение правильное. Но удобство заканчивается ровно там, где какой-то сервис остался доступен напрямую, в обход всей этой красивой цепочки. Дальше разберём, как цепочка устроена, где она рвётся и что с этим делать.

Что происходит между браузером и первой панелью

Когда человек открывает адрес внутренней панели, запрос сначала приходит не в само приложение, а на reverse proxy, который стоит перед ним. Прокси не решает, пускать ли пользователя. Он задаёт отдельный вопрос компоненту Authentik, который называется outpost: «этот запрос уже аутентифицирован и разрешён?». Если ответ положительный, прокси передаёт запрос приложению. Если нет, пользователя отправляют на страницу входа Authentik, а после успешного входа возвращают на исходный адрес.

Такая схема описана в документации как forward auth: трафик приложения продолжает обслуживать уже существующий reverse proxy, а outpost проверяет аутентификацию и авторизацию. Прокси должен направлять запросы проверки доступа в outpost, при этом само приложение по-прежнему обслуживается upstream (документация Authentik: Forward auth). Важная деталь: приложению не нужно ничего знать про Authentik. Оно может вообще не уметь в OIDC или SAML. Весь вход происходит «снаружи» него.

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

Два разных способа подключить приложение

Здесь легко запутаться, потому что в интерфейсе Authentik приложение, провайдер и способ интеграции соседствуют, и всё называется «подключением». Полезно разделить два разных случая.

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

Второй: защита перед приложением через forward auth. Приложение ничего не знает. Решение «пустить или нет» принимается до того, как запрос до него дойдёт. Внутри приложение видит просто запрос, который прошёл фильтр.

Разница принципиальная, и она определяет, что именно вы получаете.

Чем отличаются два способа подключения
ВопросПротокольная интеграцияForward auth
Кто знает пользователя внутри приложенияПриложение получает данные о нём и ведёт свою учётную записьПриложение видит лишь запрос, прошедший проверку на прокси
Что решается на входеВход в приложение и сопоставление личностиДопуск к адресу целиком
Нужна ли поддержка в приложенииДаНет
Права внутри приложенияМожно связать с данными от провайдера, если приложение это умеетОстаются на совести приложения

Последняя строка таблицы важнее остальных, и к ней мы ещё вернёмся.

Один домен — одно приложение или общий вход для многих

В документации Authentik forward auth описан в нескольких режимах. Режим для одного приложения рассчитан на один домен или поддомен и предполагает отдельные провайдер, политики и привязки (Forward auth). Это удобно, когда у каждой панели свой круг людей: мониторинг видит вся инфраструктурная команда, админку очередей только двое, а панель бухгалтерских выгрузок только бухгалтерия.

Цена такого подхода — больше сущностей: на каждый поддомен свой провайдер и свои привязки. Зато права читаются буквально: открыл настройки одной панели и видишь, кто в неё допущен. Для небольшой команды это разумный размен, потому что три-пять панелей легко держать в голове, а вот общий допуск «всем сотрудникам ко всему» через год превращается в загадку.

Если вы только разворачиваете сам Authentik, подробности установки есть в статье Как установить и настроить Authentik на VPS. Здесь мы исходим из того, что он уже работает, а перед ним уже стоит прокси, которому можно добавить проверку.

Прямой путь, о котором забывают

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

Forward auth защищает путь через прокси. Он не защищает сам сервис, если до сервиса можно добраться другим путём. Это не дефект Authentik, а свойство схемы: решение принимается в одном месте, и если запрос это место обошёл, решение не принималось вообще.

Закрывать прямой путь нужно отдельно. Варианты, из которых можно выбирать:

  • привязать приложение к локальному интерфейсу (127.0.0.1) или к внутренней сети контейнеров, чтобы единственный путь к нему вёл через прокси;
  • если прокси и приложение на одном VPS, закрыть порт приложения правилами файрвола для внешних адресов;
  • если приложение на другом сервере, разрешить входящие соединения на его порт только с адреса прокси;
  • проверить, не отвечает ли сервис по другому имени: старый поддомен, прямой адрес, тестовая запись DNS, которую забыли удалить.

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

Тут пригодится то, что VPS даёт root-доступ: правила файрвола и привязку служб к интерфейсам вы настраиваете сами, и не нужно просить об этом кого-то ещё. Обратная сторона та же: никто не сделает это за вас по умолчанию, поэтому закрытие прямых портов стоит считать частью подключения каждой новой панели, а не отдельной задачей на потом.

MFA: где она действует, а где нет

Второй фактор в такой схеме подтверждается при входе в Authentik, а не в каждом приложении по отдельности. Пользователь прошёл пароль и второй фактор, получил сессию, и дальше прокси через outpost узнаёт, что сессия действительна. Поэтому в схеме с forward auth второй фактор защищает вход на все панели сразу, и это хорошо: настроили один раз, а не в пяти местах пять разных способов.

Но из этого вытекают два следствия, о которых полезно знать заранее.

Первое: MFA действует только на пути через Authentik. Если у приложения есть собственный вход по логину и паролю, доступный напрямую, то второй фактор на нём не требуется, хотя перед ним красуется общий экран входа. Значит, помимо закрытия прямого пути, стоит отключить или ограничить собственные способы входа приложения, если оно позволяет.

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

В режиме forward auth есть ещё один нюанс: решение принимает политика, привязанная к провайдеру. Если вы хотите, чтобы в админку очередей входили только двое, нужна привязка именно на этом провайдере. Общий факт «пользователь вошёл в Authentik» ничего не говорит о том, что ему разрешено открывать этот конкретный адрес.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации Россия, США, Франция и Великобритания. Оплата картой РФ и по СБП.

АРЕНДОВАТЬ СЕРВЕР

Чего forward auth не знает про ваше приложение

Теперь ключевое ограничение, ради которого стоило оговориться в начале. Forward auth отвечает на вопрос «допускается ли этот человек к этому адресу?». Он не отвечает на вопрос «какие объекты внутри приложения этот человек вправе видеть и менять?».

Пример для наглядности, условный. Внутренняя панель отчётов показывает отчёты по клиентам. Через forward auth вы допустили к ней всех сотрудников отдела. Дальше любой допущенный сотрудник сам попадает в приложение, и если приложение отдаёт отчёт по номеру в адресе, то подставив чужой номер, он может открыть отчёт, который ему видеть не положено. Прокси этого не заметит: пользователь аутентифицирован, адрес разрешён, запрос законный. Различать объекты должно само приложение.

Поэтому честная формулировка такая: forward auth закрывает вход, но не заменяет модель прав приложения. Если внутри приложения права различаются по ролям или по объектам, нужна либо протокольная интеграция с передачей данных о пользователе, либо собственная логика приложения. Некоторые приложения умеют доверять заголовкам с именем пользователя от прокси, но это нужно проверять по документации самого приложения, и нужно убедиться, что внешний клиент не может подставить такие заголовки сам, в обход прокси. Не стоит считать, что это включено или безопасно «из коробки».

API-клиент, который не умеет в браузер

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

Forward auth по своей природе ориентирован на браузерный сценарий: перенаправление, сессия в cookie, интерактивный вход. Поэтому нельзя считать, что он автоматически защищает все API, и нельзя просто закрыть API тем же способом и надеяться, что клиенты как-нибудь приспособятся. Либо клиент ломается, либо, что хуже, кто-то «на минутку» открывает путь к API мимо проверки, и это «на минутку» живёт годами.

Разумные пути, из которых выбирать по ситуации:

  1. Развести пути. Браузерный интерфейс идёт через проверку Authentik, а API на отдельном адресе или отдельном префиксе защищён тем, что умеет проверять машинного клиента: токеном, ключом, взаимным TLS, ограничением по адресу. Важно, чтобы у этого пути была своя явная защита, а не её отсутствие.
  2. Использовать возможности самого API. Если приложение выдаёт API-токены и проверяет их, пусть проверяет. Тогда forward auth не должен мешать этому пути, но и считать его защищённым «за счёт Authentik» нельзя.
  3. Ограничить сетью. Если клиент находится на известном адресе или в закрытой сети, ограничить доступ к API этим адресом. Это дополняет токены, но не заменяет их.

Какой вариант взять, зависит от приложения, и универсального ответа нет. Но в любом случае у каждого маршрута к сервису должен быть названный механизм проверки. Фраза «API закрыт, потому что перед сайтом стоит Authentik» ничего не значит, если API живёт на другом адресе.

Практическая проверка проста: возьмите адрес API и обратитесь к нему без каких-либо учётных данных. Ожидаемый результат — отказ, а не данные. Затем с токеном, который должен работать, и без токена, который не должен. Если без токена данные приходят, значит, схема держалась на предположении, а не на проверке.

Ресурсы под такую связку

Authentik, прокси и несколько панелей — это несколько постоянно работающих служб, и в простое они обычно нетребовательны, но у Authentik есть собственное хранилище данных, а входы всей команды утром случаются почти одновременно. Какой тариф нужен, заранее не скажешь: ресурсы в линейке VPS MAATRIX, от небольшого Ba с 1 vCPU и 2 ГБ RAM до более крупных, нужны как ориентир, а не как обещание ёмкости. Разумнее развернуть связку, посмотреть на реальную загрузку при утреннем входе команды и уже по ней решать, нужен ли переход на тариф выше. Если панели и Authentik находятся на одном сервере, это ещё и упрощает закрытие прямых портов: всё общается через локальные адреса, а наружу смотрит только прокси.

Отзыв доступа, когда панель уже открыта

Последняя ситуация самая неприятная. Сотрудник уходит из компании или меняет роль. Вы отключаете его учётную запись в Authentik. Но у него в браузере открыта панель, и он вроде бы продолжает с ней работать. Значит ли это, что отзыв не сработал?

Тут нужно различать несколько слоёв, и ответ зависит от каждого.

  • Сессия Authentik. Её нужно завершить явно, а не только отключить учётную запись. Посмотрите в интерфейсе, какие активные сессии есть у пользователя, и убедитесь, что они прекращены. Не предполагайте, что отключение учётной записи сразу обрывает всё остальное.
  • Сессия на стороне прокси и outpost. Проверка при очередном запросе должна заметить, что доступ больше не разрешён. Как часто решение пересматривается и что кешируется, зависит от настроек и версии, поэтому проверьте это на тестовой учётной записи, а не на живой.
  • Собственная сессия приложения. При протокольной интеграции приложение выдаёт свою сессию, и она может жить независимо от Authentik. Отзыв в Authentik не обязан немедленно закрыть вход в приложение. Нужно знать срок этой сессии и уметь завершить её в самом приложении.
  • Токены и ключи. Всё, что было выдано для API, не зависит от браузерной сессии вообще. Токены, выпущенные сотруднику или на его имя, нужно отозвать отдельно.

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

Маршруты, которые стоит пройти руками

Настройка закончена не тогда, когда красиво выглядит экран входа, а когда каждый путь к сервису проверен. Вот маршруты пользователя и ожидаемое поведение каждого:

  • открыть адрес панели в чистом браузере без сессии — вас отправляют на вход Authentik, а после входа возвращают на исходную страницу;
  • войти сотруднику без права на эту панель — доступ отклонён, хотя вход в Authentik прошёл;
  • войти сотруднику с правом на панель, но без второго фактора, если политика его требует — вход не завершается;
  • обратиться к сервису по прямому адресу и порту с внешней машины — соединение не устанавливается;
  • обратиться к старому или тестовому имени сервиса — либо тот же вход, либо отсутствие ответа;
  • собственная форма входа приложения, если она есть, — отключена или недоступна снаружи;
  • запрос к API без токена — отказ, с действующим токеном — данные, с отозванным — отказ;
  • отзыв доступа у пользователя с открытой панелью — панель перестаёт отвечать в срок, который вы измерили и записали;
  • внутри приложения попытка открыть объект, не принадлежащий пользователю, — решает логика самого приложения, и она проверена отдельно.

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