Содержание
- Зачем enterprise отдельный SSO-сервер
- Как устроен поток входа в CAS
- MFA как подпотоки, а не как «ещё один логин»
- Второй фактор: push, TOTP, RADIUS, FIDO2
- Политика MFA по приложениям и атрибутам
- Apereo CAS или Keycloak
- Интеграция со Spring Security
- Импортозамещение и контур без внешних провайдеров
- Как внедрять: этапы и риски
- FAQ
В крупной организации рано или поздно появляется один и тот же набор болей: десятки внутренних систем, у каждой свой логин, пароли гуляют по стикерам, а служба ИБ не может ответить на простой вопрос — кто, куда и когда заходил. Запрос «что мне делать как единственному ИТ-специалисту, чтобы контора была в информационной безопасности» в наших корпоративных каналах звучит почти дословно. Ответ начинается не с антивируса, а с единой точки аутентификации.
Эта статья — практический разбор того, как строить единый вход (SSO) и многофакторную аутентификацию (MFA) на Apereo CAS в корпоративном контуре: как устроен поток входа, почему MFA правильно делать подпотоками, какие вторые факторы выбирать и как не сломать уже работающие приложения. CAS написан на Java/Spring, поэтому материал особенно полезен командам на Java/Kotlin — а именно с таким стеком мы в Новакоме чаще всего и работаем.
Зачем enterprise отдельный SSO-сервер
SSO решает три задачи одновременно:
- Пользователь логинится один раз. Дальше переходы между порталом, CRM, BI и десятком внутренних сервисов идут без повторного ввода пароля — система устанавливает сессию единого входа и выдаёт билет приложению.
- Учётные записи живут в одном месте. Не нужно «придумывать способ аутентификации для каждой службы или для каждого приложения» — этим занимается центральный сервер, а приложения только доверяют ему.
- ИБ получает единую точку контроля. Все события входа, политика паролей, MFA и аудит сосредоточены в одном узле. Это и есть фундамент, на котором потом строятся PAM, Zero Trust и расследование инцидентов.
Apereo CAS — один из старейших open-source SSO-серверов (изначально Central Authentication Service от Yale). Он поддерживает протоколы CAS, SAML 2.0, OAuth 2.0 и OpenID Connect, то есть умеет быть identity provider'ом и для legacy-систем, и для современных SPA. Для enterprise критично, что это self-hosted решение без обязательной внешней SaaS-зависимости — об этом ниже в разделе про импортозамещение.
Как устроен поток входа в CAS
Ключевая особенность CAS, которую важно понять до внедрения: процесс входа управляется Spring Web Flow. Вся последовательность — от запроса метода аутентификации до выдачи билета и установки SSO-сессии — это управляемый flow с состояниями и переходами.
Упрощённо запрос обрабатывается так:
- Приходит запрос на аутентификацию для конкретного сервиса.
- CAS проверяет: есть ли уже SSO-сессия? Если да и её достаточно — пользователь сразу переходит к приложению.
- Если сессии нет — выбирается ветвь основного метода аутентификации (логин/пароль, LDAP, токен).
- После успешной аутентификации CAS генерирует service ticket, устанавливает SSO-сессию и передаёт управление приложению.
Главная мысль архитектуры — не усложнять то, что должно быть простым. Как формулируют сами разработчики CAS: «есть много способов сделать вход очень сложным», и задача сервера — спрятать эту сложность за предсказуемым flow. Приложения, которые уже работают, должны продолжать работать так же: добавление MFA не должно быть «навязчивым принудительным» изменением для каждого клиента.
MFA как подпотоки, а не как «ещё один логин»
Самая частая ошибка при внедрении многофакторки — прикрутить второй фактор как отдельный экран поверх существующего входа. В CAS это решено иначе и гораздо чище: MFA реализуется через подпотоки (subflows) внутри основного flow.
Логика такая. Есть один большой flow, который управляет входом. Внутри него можно ответвляться в более мелкие подпотоки и возвращаться обратно в основной. Аналогия от авторов CAS — съезд с шоссе: вы съезжаете на ответвление, выполняете дополнительную аутентификацию и снова возвращаетесь на основную трассу, где сервер делает то, что делал всегда: генерирует билет и устанавливает SSO.
Это даёт два важных свойства:
- API не меняется. Если вы писали собственные обработчики аутентификации (authentication handlers), их можно переиспользовать как есть — «взять один и поместить его в MFA-контекст». Не нужно проектировать новые API под каждый фактор.
- Факторы можно объединять в цепочку. Один подпоток может ответвляться к другому, тот — к третьему. Так из примитивов собирается аутентификация любой строгости: сначала логин/пароль, затем PIN с аппаратного токена, затем биометрия — пока не будет удовлетворено требование политики.
[основной flow: логин/пароль]
│
▼
нужен MFA? ──нет──▶ выдать ticket, установить SSO ──▶ приложение
│ да
▼
[subflow: второй фактор] ──(цепочка)──▶ [subflow: третий фактор]
│
└─▶ вернуться в основной flow ──▶ выдать ticket ──▶ приложение
Практический эффект: вы внедряете MFA точечно — для критичных систем и привилегированных пользователей — не ломая вход в остальные приложения.
Второй фактор: push, TOTP, RADIUS, FIDO2
CAS не навязывает один провайдер второго фактора. На практике в корпоративном контуре встречаются четыре подхода — у каждого свой профиль рисков.
Push-подтверждение. Пользователю прилетает уведомление «подтвердите вход», он жмёт «разрешить». Удобно, но есть известная проблема: пользователи «нередко даже не читают уведомление, просто подтверждают не глядя» — отсюда атаки MFA fatigue (засыпать жертву запросами, пока кто-нибудь не нажмёт «да»). Push без привязки к контексту входа — это удобство в обмен на риск. Классический корпоративный сценарий — push-OTP для доступа по RDP: клиент удалённого рабочего стола запрашивает одноразовый пароль, пользователь оставляет поле пустым, получает push в мобильное приложение и подтверждает отпечатком пальца.
TOTP (коды из приложения-аутентификатора). «Ставите любую офлайн-программу для генерации TOTP-кодов и будет счастье» — Google Authenticator, Яндекс.Ключ, встроенный менеджер паролей. Главные плюсы: работает офлайн, ничего никуда не передаёт, доступен даже без сотовой связи. Минус — код можно невольно ввести на фишинговом сайте, который его тут же перехватит.
RADIUS и собственные провайдеры. Многие организации уже имеют аппаратные токены с собственным провайдером через RADIUS. CAS умеет подключать такие схемы как ещё один способ второго фактора — это позволяет не выбрасывать существующую инфраструктуру токенов. Аналогично интегрируются коммерческие провайдеры вроде Duo: «добавить официальную поддержку конкретного поставщика двухфакторной аутентификации» — частый и хорошо проторённый путь.
FIDO2 / аппаратные ключи. Технология, изначально созданная против фишинга, которую «невозможно обмануть» перехватом кода: секрет привязан к домену и не покидает устройство. В российском контуре сюда относятся, например, носители Рутокен MFA. Это самый строгий из массовых факторов — его стоит требовать для администраторов и доступа к критичным системам.
Практический вывод для enterprise: пароль сам по себе уже не защита. SMS и одноразовые коды лучше, но их надёжность под вопросом из-за фишинга и перехвата. FIDO2-устройства дают уровень, реально соответствующий современным угрозам, — и именно их имеет смысл делать обязательными на верхних уровнях доступа.
Политика MFA по приложениям и атрибутам
Сильная сторона CAS — декларативная политика второго фактора через реестр сервисов (service registry). Вместо того чтобы зашивать логику в каждое приложение, вы описываете требования централизованно.
Это работает на двух уровнях:
- По приложению. В реестре сервисов для каждого приложения указывается обязательный метод аутентификации. Когда приходит запрос, «CAS проверяет реестр служб и понимает: вам нужно использовать двухфакторную аутентификацию — давайте сделаем это». Приложению ничего знать про MFA не нужно — оно просто доверяет билету.
- По атрибуту пользователя. Можно определить, что MFA включается, если определённый атрибут пользователя того требует — например, роль «администратор» или членство в группе с доступом к финансовым данным. Обычные сотрудники проходят базовый вход, привилегированные — усиленный.
Технически распознавание нужного метода устроено через extractor аргументов: компонент разбирает параметр в URL входа и сопоставляет его со списком поддерживаемых методов. Если метод распознан и настроен — CAS уводит пользователя в соответствующий MFA-подпоток; если запрошено что-то неизвестное — система честно отвечает, что не понимает запрос, вместо того чтобы молча пропустить.
Этот подход — основа для перехода к Zero Trust: уровень доверия к сессии определяется не фактом входа, а тем, какие факторы и при каких условиях были пройдены.
Apereo CAS или Keycloak
Два самых частых кандидата на роль self-hosted identity provider в Java-контуре — Apereo CAS и Keycloak. Мы подробно разбирали внедрение Keycloak + Spring Boot отдельно; здесь — короткое сравнение для выбора.
| Критерий | Apereo CAS | Keycloak |
|---|---|---|
| Происхождение | Central Authentication Service (Yale), Java/Spring | Red Hat, Java/Quarkus |
| Протоколы | CAS, SAML 2.0, OAuth 2.0, OIDC | OAuth 2.0, OIDC, SAML 2.0 |
| Модель кастомизации | Конфигурация + Java-обработчики, Spring Web Flow | Расширения (SPI), темы, REST Admin API |
| MFA | Подпотоки flow, политика по сервисам/атрибутам | Authentication flows, conditional MFA |
| Где силён | Глубокая интеграция с legacy, тонкая настройка flow, университеты и крупные внедрения | Быстрый старт, готовый Admin UI, user federation |
| Порог входа | Выше: нужен опыт Spring | Ниже: больше «из коробки» |
Грубое правило: если у вас много legacy-приложений на протоколе CAS, нестандартные требования к flow и команда с опытом Spring — CAS даёт больше контроля. Если нужен быстрый старт, готовый административный UI и федерация пользователей — обычно проще начать с Keycloak. В обоих случаях это self-hosted решение без обязательной внешней SaaS-зависимости.
Интеграция со Spring Security
Для приложений на Spring подключение к CAS как identity provider'у делается стандартными средствами. Если CAS отдаёт токены по OIDC, на стороне ресурс-сервера это обычный OAuth2 Resource Server:
@Configuration
@EnableWebSecurity
class SecurityConfig {
@Bean
fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
authorizeHttpRequests {
authorize("/actuator/health", permitAll)
authorize("/admin/**", hasAuthority("ROLE_ADMIN"))
authorize(anyRequest, authenticated)
}
oauth2ResourceServer {
jwt {
jwtAuthenticationConverter = keycloakRolesConverter()
}
}
}
return http.build()
}
}
Для веб-приложений с серверным рендерингом подключается spring-security-cas с CasAuthenticationFilter и CasAuthenticationProvider, которые валидируют service ticket на сервере CAS. Важная деталь, вытекающая из архитектуры подпотоков: на стороне приложения логику MFA реализовывать не нужно — приложение получает уже аутентифицированного пользователя с нужным уровнем доверия, а всю работу по факторам выполнил CAS. Это сильно упрощает приложения и убирает дублирование security-кода по сервисам.
Дальше поверх этого выстраивается доменная авторизация: роли из токена, проверки на уровне методов (@PreAuthorize), и при необходимости — связка с темами вроде JWT vs Session, если часть сервисов работает на собственных сессиях.
Импортозамещение и контур без внешних провайдеров
Для российского enterprise отдельный вес имеет то, что CAS полностью разворачивается в собственном контуре. Аутентификация — критичный компонент, и зависеть в ней от внешней SaaS, которая может отключить доступ, рискованно. Self-hosted SSO снимает этот риск: сервер, база, ключи и логи остаются внутри периметра.
Это ложится в общую логику импортозамещения ПО:
- второй фактор можно строить на отечественных носителях (Рутокен MFA, FIDO2) и российских MFA-сервисах;
- хранение событий аутентификации и сессионных данных остаётся под контролем — это упрощает выполнение требований 152-ФЗ;
- нет привязки к зарубежному identity-провайдеру как к единой точке отказа.
При этом миграция на self-hosted SSO — это не «всё и сразу». CAS специально спроектирован так, чтобы существующие приложения продолжали работать без изменений, а MFA включалась точечно. Это позволяет идти поэтапно, без простоя бизнеса.
Как внедрять: этапы и риски
На практике мы рекомендуем такую последовательность:
- Инвентаризация. Собрать список приложений, их протоколы (CAS/SAML/OIDC) и текущие способы входа. Часто здесь же выясняется, что часть систем вообще не логируют входы.
- Поднять CAS и подключить каталог пользователей (LDAP/AD или его аналог). На этом этапе — только основной фактор, без MFA. Цель — чтобы единый вход заработал и приложения начали доверять серверу.
- Подключить приложения по одному. Начать с некритичных, проверить, что SSO-сессия и билеты работают, и только потом двигаться к ключевым системам.
- Включить MFA точечно. Сначала — для администраторов и привилегированных ролей через политику в реестре сервисов. Выбрать факторы: FIDO2/аппаратные ключи для верхнего уровня, TOTP/push — для остальных.
- Настроить аудит и мониторинг. Все события входа должны писаться и анализироваться — это основа для расследования инцидентов и дальнейшего перехода к Zero Trust.
Типичные риски, которые стоит закрыть заранее:
- MFA fatigue. Не полагаться на «голый» push — добавлять number matching и контекст входа, а для критичных систем требовать FIDO2.
- Фишинг одноразовых кодов. TOTP и SMS перехватываются на фишинговых страницах; там, где цена компрометации высока, нужен фишинг-устойчивый фактор.
- Сломанный вход в legacy. Главная причина провальных внедрений — попытка включить MFA глобально. CAS позволяет этого избежать, но дисциплину «по одному приложению» нужно соблюдать.
- Восстановление доступа. Заранее продумать процедуру для потерянных токенов, иначе служба поддержки превратится в обходной путь вокруг всей системы безопасности.
SSO и MFA — это не разовый проект, а инфраструктурный слой, который потом несёт на себе PAM, Zero Trust и расследование инцидентов. Поэтому его стоит делать руками команды, которая понимает и Spring, и эксплуатацию в продакшене.
FAQ
Чем двухфакторная аутентификация отличается от двухэтапной? Двухфакторная требует факторов разной природы: что-то, что вы знаете (пароль), и что-то, что у вас есть (токен/телефон) или чем вы являетесь (биометрия). Двухэтапная может использовать два фактора одного типа (например, пароль и контрольный вопрос) — это слабее. На практике крупные сервисы нередко путают эти понятия.
Нужно ли переписывать приложения, чтобы добавить MFA? Нет. В архитектуре CAS второй фактор живёт в подпотоках flow на стороне сервера. Приложение получает уже аутентифицированного пользователя и логику MFA у себя не реализует.
Можно ли подключить уже имеющиеся аппаратные токены? Да. CAS интегрирует существующие схемы через RADIUS и собственных провайдеров второго фактора, а также коммерческие сервисы вроде Duo — это позволяет не выбрасывать инвестиции в токены.
Что выбрать как фактор для администраторов? Фишинг-устойчивый фактор — FIDO2/аппаратные ключи (включая Рутокен MFA). Для привилегированного доступа push и TOTP недостаточно надёжны.
CAS или Keycloak для старта? Если нужен быстрый запуск с готовым админ-UI — обычно Keycloak. Если важны тонкая настройка flow и интеграция с legacy на протоколе CAS — Apereo CAS. Оба — self-hosted и разворачиваются в своём контуре.
Если вы планируете единый вход и многофакторную аутентификацию в корпоративном контуре, мы в Новакоме проектируем и внедряем SSO/MFA на Java/Kotlin-стеке — от архитектуры flow до интеграции со Spring Security и аудита. Посмотрите наши услуги по разработке на Spring и аутстаффингу Java-команд или напишите нам с описанием вашего контура.