1. Введение: Постановка задачи на проекте
Представьте, что вы — системный аналитик в крупной компании, управляющей интернет-магазином. У вас есть несколько платформ: фронт-система (веб-интерфейс магазина, где клиенты просматривают товары и оформляют заказы), платформа обработки заказов (backend, который управляет заказами и доставкой) и аналитическая платформа для отчётов. Прилетает задача: настроить доступ из фронт-системы магазина к платформе обработки заказов через общекорпоративный Keycloak — единый сервер аутентификации (Identity Provider, IdP). Цель — чтобы пользователи (например, менеджеры магазина) могли выполнять действия (скажем, подтверждать заказы), а JWT-токен, выдаваемый Keycloak, содержал нужные данные, такие как роль order_manager
или атрибут отдела.
Это не проектирование системы с нуля, а типичная задача аналитика: разобраться в существующей инфраструктуре, определить, какие роли и атрибуты нужны, и настроить интеграцию. Проблема в том, что без понимания, как работает Keycloak и OIDC, аналитик может "залипнуть". С кем общаться? С разработчиками фронт-системы, чтобы они добавили поддержку токенов? С админами Keycloak, чтобы настроили realm? С владельцами платформы заказов, чтобы уточнить роли? И что именно обсуждать: какие scopes, как маппить роли, как тестировать токены? Непонимание приводит к задержкам, ошибкам в доступах (например, менеджер видит чужие заказы) или даже уязвимостям.
Цель этой статьи — показать, как системному аналитику подойти к такой задаче. Мы разберём принципы Single Sign-On (SSO) и OpenID Connect (OIDC), изучим Keycloak как инструмент для их реализации, и на примере простого веб-приложения (React-frontend, Node.js-backend, Docker) покажем, как настроить доступ. В конце вернёмся к нашей задаче и объясним, как обеспечить, чтобы JWT содержал нужные данные, и что должен обсудить аналитик. Это поможет не только решить задачу, но и избежать типичных ошибок в корпоративных проектах.
Для разработчиков статья даёт практический пример OIDC с использованием PKCE и верификации JWT. Это поможет быстро внедрить SSO без написания сложной логики аутентификации. Для архитекторов статья объясняет, как Keycloak вписывается в микросервисную архитектуру, поддерживает масштабируемость (через PostgreSQL или Active Directory) и обеспечивает безопасность (PKCE, HTTPS).
2. Принципы SSO и OIDC
Single Sign-On (SSO) и OpenID Connect (OIDC) — ключевые технологии для нашей задачи: обеспечить доступ из фронт-системы (reports-frontend
) к API отчётов (reports-api
) через общекорпоративный Keycloak, чтобы JWT-токен содержал роль report_user
. В контексте e-commerce это можно представить как интерфейс интернет-магазина, где менеджеры запрашивают отчёты о продажах, а Keycloak управляет аутентификацией. Для системного аналитика понимание SSO и OIDC критично, чтобы правильно составить заявку на настройку и согласовать с командами (админы Keycloak, разработчики, владельцы API), какие данные должны быть в токене. Без этого аналитик может не знать, что обсуждать (роли, атрибуты) и с кем, что приведёт к ошибкам, например, отсутствию роли в JWT.
Для наглядности начнём с диаграммы, показывающей поток OIDC:

report_user
, а API отчётов проверяет токен, чтобы вернуть данные отчёта.Что такое SSO
SSO (Single Sign-On) позволяет пользователю войти один раз и получить доступ ко всем подключённым системам без повторного ввода логина и пароля. В нашей задаче это значит, что менеджер входит в reports-frontend
и сразу может запросить отчёты через reports-api
. SSO:
Упрощает опыт: Один логин для всех систем.
Повышает безопасность: Централизованное управление через Keycloak.
Снижает нагрузку: Меньше запросов в IT-поддержку.
SSO работает через Identity Provider (IdP), такой как Keycloak, который аутентифицирует пользователя и выдаёт токены. Аналитик должен понять, какие роли (например, report_user
) нужны в токене для доступа к API.
OpenID Connect (OIDC) и его роль
OIDC — протокол аутентификации, построенный поверх OAuth 2.0, решающий две задачи:
Аутентификация: Подтверждает, кто пользователь (например,
access1
).Авторизация: Определяет, что он может делать (например, доступ к отчётам через
report_user
).
OIDC использует Authorization Code Flow:
Пользователь заходит в
reports-frontend
и кликает "Войти".Фронт-система перенаправляет на Keycloak для логина.
Keycloak выдаёт authorization code, который обменивается на JWT-токены (ID Token для идентификации, Access Token для доступа).
reports-frontend
отправляет Access Token на/reports
, где API проверяет рольreport_user
.
Аналитик должен согласовать, чтобы JWT содержал report_user
, и обсудить это с админами Keycloak и разработчиками API.
Структура JWT
JWT (JSON Web Token) — компактный токен в формате JSON, выдаваемый Keycloak. Он состоит из трёх частей: Header, Payload, Signature (разделены точками, закодированы в base64). Payload важен для аналитика, так как содержит:
sub
: ID пользователя (например,access1
).name
,email
: Данные пользователя (например,access1@example.com
).realm_access.roles
: Роли на уровне realm (например,["report_user"]
).Кастомные атрибуты: Если нужны (например,
department
), их добавляют через мапперы в Keycloak.
Аналитик должен уточнить у владельцев API, какие роли (например, report_user
) нужны в токене, и передать это в заявке.
Сравнение с другими протоколами
OIDC — лучший выбор для веб-приложений, таких как reports-frontend
:
SAML: Использует XML, сложнее в настройке, для старых систем.
OAuth 2.0: Только авторизация, без аутентификации.
Kerberos: Для локальных сетей, не подходит для веба.
OIDC прост в интеграции благодаря JSON и поддержке Keycloak.
Риски и задачи аналитика
OIDC уязвим без правильной настройки:
CSRF-атаки: Злоумышленник подделывает запрос. Защищает параметр
state
(случайная строка, проверяемая клиентом).Перехват токенов: Требуется HTTPS.
Ошибки в токене: Если
report_user
отсутствует, доступ не сработает.
Аналитик должен обсудить:
Включение
state
для защиты.Роли в JWT (например,
report_user
).Тестирование токенов (например, декодирование на jwt.io).
Без понимания OIDC аналитик может не знать, что включить в заявку или с кем говорить, что приведёт к задержкам.
3. Keycloak как инструмент для реализации OIDC
Keycloak — это мощный open-source инструмент для управления идентификацией и доступом (Identity and Access Management, IAM), который идеально подходит для реализации Single Sign-On (SSO) через протокол OpenID Connect (OIDC). В нашей задаче Keycloak выступает как общекорпоративный Identity Provider (IdP), обеспечивая доступ из фронт-системы интернет-магазина (например, веб-интерфейса для менеджеров) к платформе обработки заказов. Keycloak берёт на себя аутентификацию пользователей и выдачу JWT-токенов с ролями (например, order_manager
) и атрибутами (например, department: sales
). Для системного аналитика это означает необходимость согласовать настройки Keycloak с разработчиками, администраторами и владельцами платформы, чтобы токен содержал нужные данные, а доступ работал корректно.
Для наглядности начнём с диаграммы, показывающей, как Keycloak связывает фронт-систему и платформу заказов:

store-realm
), где хранятся пользователи и роли. Фронт-система (store-frontend
) получает JWT после логина, а платформа заказов (orders-api
) проверяет токен, чтобы разрешить доступ.Преимущества Keycloak
Keycloak упрощает задачу аналитика в корпоративных проектах, таких как наш интернет-магазин:
Интеграция: Поддерживает OIDC для веб-приложений, обеспечивая JSON-токены (JWT) с ролями и атрибутами.
Гибкость: Позволяет настроить SSO между фронт-системой и платформой заказов, а также интегрироваться с Active Directory или Google.
Безопасность: Встроенные механизмы, такие как хэширование паролей, поддержка MFA и защита от атак (например, через параметр
state
).Интерфейс: Веб-админка позволяет аналитику настраивать пользователей, роли и клиентов без программирования.
Open-source: Бесплатен, с активным сообществом и возможностью кастомизации.
Аналитик должен обсудить с разработчиками фронт-системы, как она будет запрашивать токены, с админами Keycloak — как настроить роли в realm, и с владельцами платформы заказов — какие данные нужны в JWT.
Основные компоненты Keycloak
Keycloak состоит из нескольких элементов, которые аналитик должен понимать, чтобы координировать настройки:
Realms: Изолированные "домены" для пользователей, ролей и клиентов. Например,
store-realm
может содержать пользователей магазина и их роли.Clients: Приложения, подключающиеся к Keycloak. В нашей задаче это
store-frontend
(фронт-система) иorders-api
(платформа заказов). Clients определяют redirect URI и scopes (например, какие роли включать в JWT).Users и Roles: Пользователи (например,
access1
) и их роли (например,order_manager
). Роли бывают на уровне realm или клиента.Flows: Настраиваемые сценарии логина, например, требование пароля или добавление MFA.
Эти компоненты работают вместе: realm изолирует настройки, client запрашивает токены, а роли определяют доступ. Аналитик должен обеспечить, чтобы order_manager
попала в JWT для платформы заказов.
Установка и базовая настройка
Для тестирования или разработки Keycloak разворачивается через Docker с PostgreSQL для хранения данных. Это не задача аналитика, но он должен понимать процесс, чтобы обсудить его с DevOps или админами. Вот пример docker-compose.yml
:
services:
keycloak_db:
image: postgres:14
environment:
POSTGRES_DB: keycloak_db
POSTGRES_USER: keycloak_user
POSTGRES_PASSWORD: keycloak_password
volumes:
- ./postgres-keycloak-data:/var/lib/postgresql/data
ports:
- "5433:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U keycloak_user -d keycloak_db"]
interval: 5s
timeout: 5s
retries: 5
keycloak:
image: quay.io/keycloak/keycloak:21.1
environment:
KEYCLOAK_ADMIN: admin
KEYCLOAK_ADMIN_PASSWORD: admin
KC_DB: postgres
KC_DB_URL: jdbc:postgresql://keycloak_db:5432/keycloak_db
KC_DB_USERNAME: keycloak_user
KC_DB_PASSWORD: keycloak_password
command:
- start-dev
ports:
- "8080:8080"
depends_on:
keycloak_db:
condition: service_healthy
Разверните Keycloak командой:
docker compose up -d
-d
запускает в фоновом режиме. Если порт 8080 занят, проверьте с помощьюnetstat -tuln
(Linux) илиnetstat -aon
(Windows) и замените, например, на8081:8080
.Keycloak доступен по http://localhost:8080, логин/пароль:
admin/admin
.

Для настройки аналитик может:
В админ-панели выбрать "Add realm" и создать
store-realm
.Настроить пользователей и роли (например,
access1
с рольюorder_manager
).Создать clients (
store-frontend
,orders-api
) с нужными redirect URI.


store-realm
Аналитик должен обсудить с админами Keycloak, чтобы роли и атрибуты (например, department: sales
) были добавлены в JWT, и с разработчиками — чтобы фронт-система корректно запрашивала токены.
4. Погружение в realms Keycloak
Realms (домены) в Keycloak — это изолированные пространства для управления пользователями, ролями и клиентами. Они позволяют разделять настройки для разных систем, таких как фронт-система интернет-магазина и платформа обработки заказов в нашей задаче. Каждый realm содержит своих пользователей (например, access1
), роли (например, order_manager
) и клиентов (например, store-frontend
, orders-api
), обеспечивая безопасность и порядок. Для системного аналитика realms — ключ к настройке доступа: он должен определить, какие роли и атрибуты попадут в JWT-токен, и согласовать это с администраторами Keycloak и разработчиками платформ.
Для наглядности начнём с диаграммы, показывающей, как realms изолируют данные и связывают платформы:

store-realm
для магазина, orders-realm
для заказов). Пользователь access1
из store-realm
получает JWT с ролью order_manager
, который платформа заказов проверяет через клиент orders-api
. Федерация между realms позволяет настроить SSO. Что такое realms и зачем они нужны
Realm — это "контейнер" в Keycloak, который изолирует данные и настройки. Без realms все пользователи и клиенты смешивались бы, что привело бы к хаосу и рискам (например, менеджер магазина мог бы случайно получить доступ к аналитике). В нашей задаче realms решают следующие проблемы:
Изоляция: Пользователи и роли
store-realm
не пересекаются сorders-realm
, что безопасно.Гибкость: Каждый realm может иметь свои настройки логина (например, MFA для платформы заказов).
Федерация: Realms могут связываться для SSO, позволяя менеджеру из
store-realm
работать с заказами вorders-realm
.Управление: Аналитик может настроить роли (например,
order_manager
) в одном realm и маппить их в другом.
Для аналитика realms — инструмент для структурирования доступа. Он должен обсудить с владельцами платформы, какие роли нужны (например, edit_orders
для подтверждения заказов), и с админами Keycloak — как их настроить.
Настройка realms
Realms настраиваются двумя способами: вручную через админ-панель Keycloak или автоматически через импорт JSON-файла. Аналитик чаще работает с админ-панелью, так как это не требует кодирования.
Ручная настройка
Зайдите в админ-панель Keycloak (http://localhost:8080, логин/пароль:
admin/admin
).Нажмите "Add realm" (или "Create Realm") в левом меню.
-
Укажите имя (например,
store-realm
) и включите (Enabled: true).В новом realm настройте:
-
Users: В разделе "Users" → "Add user" создайте пользователя (например,
access1
, email:access1@example.com
). В "Credentials" задайте пароль (accesspass1
, temporary: false). -
Roles: В "Realm Roles" → "Create role" добавьте роль
order_manager
с описанием "Manager for order operations". -
Clients: В "Clients" → "Create client" создайте клиент
store-frontend
(publicClient: true, redirectUris:http://localhost:3000/*
) иorders-api
(bearerOnly: true). -
Role Mappings: В "Users" →
access1
→ "Role Mappings" присвойте рольorder_manager
.
-
Настройка через импорт JSON
Для автоматизации (например, в CI/CD) аналитик может подготовить JSON-файл с конфигурацией realm и передать его админам Keycloak. Пример для store-realm
:
{
"realm": "store-realm",
"enabled": true,
"roles": {
"realm": [
{
"name": "order_manager",
"description": "Manager for order operations"
}
]
},
"users": [
{
"username": "access1",
"enabled": true,
"email": "access1@example.com",
"credentials": [
{
"type": "password",
"value": "accesspass1",
"temporary": false
}
],
"realmRoles": ["order_manager"]
}
],
"clients": [
{
"clientId": "store-frontend",
"enabled": true,
"publicClient": true,
"redirectUris": ["http://localhost:3000/*"]
},
{
"clientId": "orders-api",
"enabled": true,
"clientAuthenticatorType": "client-secret",
"secret": "oNwoLQdvJAvRcL89SydqCWCe5ry1jMgq",
"bearerOnly": true
}
]
}
Импортируйте файл: в админ-панели выберите "Import" → загрузите JSON → подтвердите.

Передача логинов и паролей в реальной жизни
В production-средах логины и пароли обрабатываются безопасно:
Хранение: Пароли хэшируются (PBKDF2 или Argon2). В JSON-файле они в plain-text только для импорта; в базе данных — зашифрованы.
Передача: Логины/пароли передаются по HTTPS. Аналитик должен убедиться, что Keycloak настроен на SSL (в production это обязательно).
Регистрация: Пользователи могут регистрироваться через интерфейс Keycloak (с email-верификацией) или импортироваться из Active Directory (подробно в следующем разделе). Например, менеджеры магазина синхронизируются из AD, а их роли маппятся в
store-realm
.Безопасность: Аналитик должен согласовать политики паролей (минимальная длина, expiration) и включение MFA для платформы заказов. Пароли хранятся в secrets (например,
KEYCLOAK_ADMIN_PASSWORD
в Docker) или HashiCorp Vault.
Для нашей задачи аналитик должен обеспечить, чтобы пользователь access1
получил роль order_manager
в store-realm
, а JWT-токен содержал эту роль для доступа к orders-api
.
Схема настройки ролей в realm
Вот диаграмма, показывающая, как аналитик настраивает роли в realm:

5. Хранение пользовательской информации в Keycloak
Keycloak хранит данные пользователей (логины, хэшированные пароли, роли, email) в рамках realms, чтобы обеспечить аутентификацию и авторизацию. В нашей задаче — доступ из фронт-системы (reports-frontend
) к API отчётов (reports-api
) с JWT, содержащим роль report_user
— важно понять, где хранятся пользователи (например, access1
) и как их данные (роль report_user
) попадают в токен. В контексте e-commerce это можно представить как менеджеров магазина, чьи данные хранятся централизованно. Keycloak поддерживает два основных подхода: локальное хранение в PostgreSQL (типичный выбор для многих проектов) и интеграцию с Active Directory (AD) или LDAP для корпоративных систем. Аналитик должен указать в заявке, откуда брать пользователей и какие данные включать в JWT, координируя с админами Keycloak, разработчиками и владельцами API.
Для наглядности начнём с общей схемы, показывающей, как данные пользователей связаны с хранилищами:

reports-realm
, используя PostgreSQL или AD. Пользователь access1
получает JWT с ролью report_user
, которая проверяется reports-api
.1. Локальное хранение в PostgreSQL
Keycloak часто использует PostgreSQL для хранения данных пользователей, ролей и клиентов. Данные хранятся в таблицах:
Users: Логины, email (например,
access1
,access1@example.com
).Credentials: Хэшированные пароли (с PBKDF2 или Argon2 для безопасности).
Roles: Роли на уровне realm (например,
report_user
).
Почему это важно: PostgreSQL — стандартный выбор для прототипов или небольших проектов благодаря простоте настройки. Пользователи и роли (например, access1
с report_user
) сохраняются в базе и используются для создания JWT.
Пример настройки: В Keycloak задаётся подключение к PostgreSQL через параметры вроде KC_DB_URL
. Конкретная реализация с Docker будет показана в части 8.
Преимущества: Простота, всё в одном месте. Недостатки: Не масштабируется для тысяч пользователей, единая точка отказа.
Схема хранения в PostgreSQL:

2. Распределённое хранение
Для крупных систем с тысячами пользователей Keycloak поддерживает кластеризацию с PostgreSQL или другими базами (MySQL, Oracle) через Infinispan (встроенный кэш Keycloak):
Infinispan: Синхронизирует данные между нодами Keycloak.
Настройка: Требует нескольких нод Keycloak и включения кэша (например,
KC_CACHE=ispn
).
Почему это важно: Обеспечивает масштабируемость для множества пользователей (например, менеджеров магазина).
Преимущества: Высокая доступность. Недостатки: Сложная настройка, требует инфраструктуры (например, Kubernetes).
Схема кластеризации:

3. Интеграция с Active Directory или LDAP
В корпоративных системах, как наш e-commerce пример, пользователи часто хранятся в Active Directory (AD) или LDAP. Keycloak синхронизирует их через User Federation:
Как работает: Keycloak подключается к AD, импортируя пользователей и группы. Группа AD
ReportUsers
маппится на рольreport_user
вreports-realm
.-
Настройка:
В админ-панели: "User Federation" → "Add provider" → "ldap".
Укажите URL (
ldap://
ad.example.com
), bind DN, фильтры ((objectClass=user)
).Маппинг: группа
ReportUsers
→ рольreport_user
.
Почему это важно: Позволяет использовать корпоративные учётные записи, как для менеджеров магазина.
Преимущества: Централизованное управление. Недостатки: Требуется доступ к AD, сложнее настройка.
Схема синхронизации с AD:

4. Передача логинов и паролей
В продакшене данные обрабатываются безопасно:
Хранение: Пароли хэшируются (PBKDF2/Argon2). В JSON-импорте (как в части 8) они в plain-text только для настройки.
Передача: Логины/пароли передаются по HTTPS. Keycloak требует SSL в продакшене.
Регистрация: Пользователи регистрируются через интерфейс Keycloak (с email-верификацией) или синхронизируются из AD.
Безопасность: Аналитик указывает в заявке политики паролей (длина, expiration) и MFA. Пароли хранятся в secrets (например, в переменных окружения).
Схема потока логина:

6. PKCE для защиты от атак в OIDC
PKCE (Proof Key for Code Exchange) — это расширение протокола OpenID Connect (OIDC), которое повышает безопасность для public clients, таких как фронт-система интернет-магазина (store-frontend
) в нашей задаче. Public clients — это приложения, работающие в браузере (например, React-приложение), где нельзя безопасно хранить секрет клиента. PKCE предотвращает атаки, связанные с перехватом authorization code, когда злоумышленник может украсть код и обменять его на JWT-токен, получив доступ к платформе заказов (orders-api
). Для системного аналитика PKCE важно, так как он должен согласовать с разработчиками фронт-системы включение этой защиты и убедиться, что токены (содержащие, например, роль order_manager
) выдаются безопасно.
Проблема без PKCE: уязвимость в Authorization Code Flow
В стандартном Authorization Code Flow OIDC фронт-система перенаправляет пользователя на Keycloak для логина, после чего получает authorization code через redirect URI (например, http://localhost:3000/*
). Этот код обменивается на JWT-токены (ID Token и Access Token) через Token Endpoint. Проблема в том, что код передаётся через браузер и может быть перехвачен злоумышленником, например:
Подмена redirect URI: Злоумышленник перенаправляет код на свой сервер.
Вредоносное приложение: Другое приложение с тем же redirect URI использует украденный код.
Без защиты Keycloak не может проверить, что код запрошен именно легитимным клиентом (store-frontend
), и злоумышленник может получить токен с ролью order_manager
.
Вот диаграмма, показывающая атаку без PKCE:

Решение с PKCE: защищённый поток
PKCE защищает от таких атак, добавляя одноразовый секрет, который подтверждает, что запрос токенов исходит от легитимного клиента. Вот как это работает:
Фронт-система генерирует случайную строку — code_verifier (секрет, например,
E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
).Из
code_verifier
создаётся code_challenge — его SHA-256 хеш, закодированный в base64-URL (например,dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
).code_challenge
отправляется в запросе на логин, аcode_verifier
— при обмене кода на токены. Keycloak проверяет, что хеш verifier совпадает с challenge.
Если злоумышленник перехватит код, он не сможет обменять его на токены без code_verifier
, известного только фронт-системе.
Вот диаграмма для защищённого потока с PKCE:

Как работает PKCE в деталях
PKCE — стандарт, рекомендованный RFC 7636, и обязателен для public clients, таких как наш store-frontend
. Ключевые шаги:
Генерация: Фронт-система создаёт
code_verifier
— случайную строку (43–128 символов, base64-URL без=
,+
,/
). Затем вычисляетcode_challenge
— SHA-256 хеш verifier, тоже в base64-URL.Запрос на логин: В Authorization Endpoint отправляется
code_challenge
иcode_challenge_method=S256
(рекомендуемый метод;plain
менее безопасен).Обмен на токены: Фронт-система отправляет
code_verifier
вместе с кодом. Keycloak хэширует verifier и сравнивает с challenge.Настройка в Keycloak: Аналитик должен попросить админов включить PKCE для клиента
store-frontend
в админ-панели (раздел "Clients" →store-frontend
→ "Advanced Settings" → "Proof Key for Code Exchange Policy" = Enforced). Разработчики фронт-системы добавляют поддержку PKCE в коде (например, в React с@react-keycloak/web
).

Аналитик должен:
Согласовать с разработчиками фронт-системы включение PKCE.
Убедиться с админами Keycloak, что клиент настроен на
S256
.Проверить, что JWT содержит нужные роли (например,
order_manager
) после логина.
Роль аналитика
Аналитик координирует безопасность фронт-системы:
Обсуждение с разработчиками: Убедиться, что фронт-система отправляет
code_challenge
и обрабатываетcode_verifier
.Обсуждение с админами Keycloak: Настройка PKCE для клиента
store-frontend
.Тестирование: Проверить, что токены выдаются только легитимным клиентам, декодируя JWT (например, на jwt.io).
Без PKCE фронт-система уязвима, что может привести к несанкционированному доступу к платформе заказов. PKCE — обязательная мера для безопасного SSO в нашей задаче.
7. Схема простого веб-приложения и роль Keycloak в нём
Keycloak в нашей задаче выступает как центральный сервер аутентификации (Identity Provider, IdP), связывающий фронт-систему интернет-магазина (store-frontend
) с платформой обработки заказов (orders-api
). Для системного аналитика важно понять, как эти компоненты взаимодействуют через Keycloak, чтобы обеспечить доступ (например, для роли order_manager
) и правильное содержимое JWT-токена (роли, атрибуты). В этой части мы разберём архитектуру типичного веб-приложения, использующего Keycloak, и покажем, как аналитик координирует настройку, чтобы токен содержал нужные данные.
Для наглядности начнём с диаграммы, показывающей, как Keycloak интегрируется с приложением:

order_manager
, а платформа заказов проверяет токен, чтобы разрешить действия (например, подтверждение заказов). PostgreSQL хранит данные пользователей и роли.Архитектура веб-приложения
Типичное веб-приложение состоит из трёх основных компонентов:
Фронт-система (Frontend): Веб-интерфейс, где пользователи (например, менеджеры магазина) взаимодействуют с системой. В нашем случае — React-приложение (
store-frontend
), которое перенаправляет на Keycloak для логина.Платформа заказов (Backend): Сервер, обрабатывающий запросы, например, подтверждение заказов. В нашем случае — Node.js-приложение (
orders-api
), которое верифицирует JWT-токены.Keycloak: IdP, управляющий аутентификацией и выдающий токены с ролями и атрибутами.
Аналитик должен:
Согласовать с разработчиками фронт-системы, как она будет запрашивать токены (например, через OIDC Authorization Code Flow).
Убедиться с админами Keycloak, что роли (например,
order_manager
) и атрибуты (например,department: sales
) добавлены в JWT.Попросить разработчиков платформы заказов настроить верификацию токенов.
Роль Keycloak в приложении
Keycloak выступает как "посредник" между фронт-системой и платформой заказов:
Аутентификация: Пользователь заходит в фронт-систему и перенаправляется на Keycloak для логина (например, вводит
access1
/accesspass1
).Выдача токенов: Keycloak возвращает JWT (ID Token для идентификации, Access Token с ролями, например,
order_manager
).Верификация: Фронт-система отправляет Access Token на платформу заказов, которая проверяет его (например, через JWKS — JSON Web Key Set).
Доступ: Если токен содержит нужную роль, платформа разрешает действия (например, подтверждение заказа).
Аналитик должен обсудить с командами:
Какие роли и атрибуты включать в JWT (например,
order_manager
,department
).Как настроить clients в Keycloak (
store-frontend
,orders-api
).Как тестировать токены (например, декодировать на jwt.io).
Поток взаимодействия
Вот подробный поток, показывающий, как Keycloak связывает компоненты:

Роль аналитика
Аналитик координирует настройку:
С разработчиками фронт-системы: Убедиться, что клиент (
store-frontend
) использует OIDC и корректные redirect URI.С админами Keycloak: Настроить realm (
store-realm
) с пользователями (access1
) и ролями (order_manager
).С разработчиками платформы заказов: Проверить, что backend верифицирует JWT и извлекает роли.
Тестирование: Декодировать JWT (например, на jwt.io) и убедиться, что он содержит
order_manager
иdepartment: sales
.
Связь с задачей
В нашей задаче Keycloak объединяет фронт-систему и платформу заказов через SSO. Аналитик должен:
Согласовать, какие роли и атрибуты нужны в JWT для доступа к заказам.
Проверить настройки clients (
store-frontend
,orders-api
) в Keycloak.Убедиться, что интеграция безопасна (например, использует HTTPS).
Эта архитектура масштабируема: можно добавить новые платформы (например, аналитику) в тот же realm или создать новый, сохранив SSO.
8. Реализация проекта: практический пример
Эта часть показывает, как работает веб-приложение, реализующее доступ из фронт-системы (reports-frontend
) к API отчётов (reports-api
) через Keycloak, используя протокол OpenID Connect (OIDC). Мы представляем это в контексте e-commerce, где фронт-система может быть интерфейсом интернет-магазина, а API отчётов — платформой для обработки данных. Пример включает React-frontend, Node.js-backend и Keycloak, запущенные через Docker Compose. Мы продемонстрируем, как код настраивает Keycloak, интегрирует фронт- и бэкенд-приложения, и как JWT-токен с ролью report_user
обеспечивает доступ к отчётам. Это поможет понять, как технически реализуется Single Sign-On (SSO). Полный код доступен в репозитории https://github.com/vasilokb/keycloak, где вы можете клонировать проект и попробовать его локально.
Для наглядности начнём с диаграммы, показывающей поток запросов:

report_user
, а API отчётов проверяет токен и возвращает данные (например, отчёт { id: 123, title: "Usage Report 45" }
).Структура проекта
Проект организован как микросервисная архитектура, где каждый компонент (фронт-система, бэкенд, Keycloak, база данных) изолирован и запускается в отдельном Docker-контейнере. Это обеспечивает:
Модульность: Компоненты независимы, что упрощает разработку и тестирование.
Масштабируемость: Сервисы можно масштабировать отдельно (например, добавить ноды Keycloak).
Оркестрацию: Docker Compose объединяет компоненты в сеть для взаимодействия.
Хранение данных: PostgreSQL сохраняет пользователей и роли Keycloak.
Структура проекта:
.
├── .gitignore
├── docker-compose.yml
├── README.md
├── backend
│ ├── Dockerfile
│ ├── package.json
│ ├── server.js
├── frontend
│ ├── .env
│ ├── Dockerfile
│ ├── nginx.conf
│ ├── package.json
│ ├── public
│ │ ├── index.html
│ ├── src
│ │ ├── App.tsx
│ │ ├── index.tsx
│ │ ├── components
│ │ │ ├── ReportPage.tsx
├── keycloak
│ ├── realm-export.json
├── postgres-keycloak-data
Пояснения к структуре:
.gitignore: Исключает временные файлы (например,
node_modules
) из репозитория.docker-compose.yml: Определяет сервисы (Keycloak, PostgreSQL, frontend, backend) и сеть
sprint-8-network
.README.md: Документация с описанием запуска и настройки.
-
backend: Node.js-приложение (
reports-api
):Dockerfile
: Инструкции для сборки Docker-образа.package.json
: Зависимости (express, jwks-rsa для верификации JWT).server.js
: Обрабатывает запросы/reports
.
-
frontend: React-приложение (
reports-frontend
):.env
: Переменные окружения (например,REACT_APP_KEYCLOAK_URL
).Dockerfile
: Сборка React-приложения.nginx.conf
: Конфигурация веб-сервера для фронт-системы.package.json
: Зависимости (react, @react-keycloak/web).public/index.html
: Главная HTML-страница.src
: Код фронт-системы, включаяApp.tsx
(логика OIDC) иReportPage.tsx
(интерфейс отчётов).
-
keycloak: Конфигурация Keycloak:
realm-export.json
: Настройки realm, пользователей, ролей, клиентов.
postgres-keycloak-data: Volume для хранения данных PostgreSQL.
Настройка Keycloak
Keycloak настроен через JSON-импорт, создающий realm reports-realm
, пользователя access1
, роль report_user
и клиентов reports-frontend
, reports-api
.
Импорт realm
Файл realm-export.json
:
{
"realm": "reports-realm",
"enabled": true,
"roles": {
"realm": [
{
"name": "user",
"description": "Regular user role"
},
{
"name": "administrator",
"description": "Administrator role"
},
{
"name": "report_user",
"description": "Prothetic user role with report access"
}
]
},
"users": [
{
"username": "regular1",
"enabled": true,
"email": "regular1@example.com",
"firstName": "Regular",
"lastName": "One",
"credentials": [
{
"type": "password",
"value": "userpass1",
"temporary": false
}
],
"realmRoles": ["user"]
},
{
"username": "superadmin1",
"enabled": true,
"email": "superadmin1@example.com",
"firstName": "Super",
"lastName": "Admin",
"credentials": [
{
"type": "password",
"value": "adminpass1",
"temporary": false
}
],
"realmRoles": ["administrator"]
},
{
"username": "access1",
"enabled": true,
"email": "access1@example.com",
"firstName": "Access",
"lastName": "One",
"credentials": [
{
"type": "password",
"value": "accesspass1",
"temporary": false
}
],
"realmRoles": ["report_user"]
}
],
"clients": [
{
"clientId": "reports-frontend",
"enabled": true,
"publicClient": true,
"redirectUris": ["http://localhost:3000/*"],
"webOrigins": ["http://localhost:3000"],
"directAccessGrantsEnabled": true
},
{
"clientId": "reports-api",
"enabled": true,
"clientAuthenticatorType": "client-secret",
"secret": "oNwoLQdvJAvRcL89SydqCWCe5ry1jMgq",
"bearerOnly": true
}
]
}
Пояснения к коду:
"realm": "reports-realm"
: Создаёт изолированный домен для приложения, где хранятся пользователи, роли и клиенты."roles"
: Определяет роли, включаяreport_user
, дающую доступ к отчётам."users"
: Создаёт пользователяaccess1
с паролемaccesspass1
и рольюreport_user
, которая включается в JWT."clients"
: Настраиваетreports-frontend
(public client для React, с redirect URI для OIDC) иreports-api
(bearer-only для backend, с секретом для верификации).
Docker Compose
Файл docker-compose.yml
запускает сервисы:
services:
keycloak_db:
image: postgres:14
environment:
POSTGRES_DB: keycloak_db
POSTGRES_USER: keycloak_user
POSTGRES_PASSWORD: keycloak_password
volumes:
- ./postgres-keycloak-data:/var/lib/postgresql/data
ports:
- "5433:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U keycloak_user -d keycloak_db"]
interval: 5s
timeout: 5s
retries: 5
keycloak:
image: quay.io/keycloak/keycloak:21.1
environment:
KEYCLOAK_ADMIN: admin
KEYCLOAK_ADMIN_PASSWORD: admin
KC_DB: postgres
KC_DB_URL: jdbc:postgresql://keycloak_db:5432/keycloak_db
KC_DB_USERNAME: keycloak_user
KC_DB_PASSWORD: keycloak_password
command:
- start-dev
- --import-realm
volumes:
- ./keycloak/realm-export.json:/opt/keycloak/data/import/realm-export.json
ports:
- "8080:8080"
depends_on:
keycloak_db:
condition: service_healthy
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
ports:
- "3000:3000"
environment:
REACT_APP_API_URL: http://localhost:8000
REACT_APP_KEYCLOAK_URL: http://localhost:8080
REACT_APP_KEYCLOAK_REALM: reports-realm
REACT_APP_KEYCLOAK_CLIENT_ID: reports-frontend
depends_on:
- backend
- keycloak
backend:
build:
context: ./backend
dockerfile: Dockerfile
ports:
- "8000:8000"
depends_on:
- keycloak
networks:
default:
name: sprint-8-network
Пояснения к коду:
keycloak_db: PostgreSQL для хранения данных пользователей, ролей и клиентов (
keycloak_db
, логин:keycloak_user
, пароль:keycloak_password
).keycloak: Keycloak-сервер подключается к PostgreSQL, импортирует
realm-export.json
(--import-realm
), доступен наhttp://localhost:8080
.frontend: React-приложение на порту 3000, использует переменные окружения для связи с Keycloak (
reports-realm
,reports-frontend
) и backend (http://localhost:8000
).backend: Node.js-приложение на порту 8000, зависит от Keycloak для верификации токенов.
networks: Объединяет сервисы в сеть
sprint-8-network
.
Frontend-интеграция
Фронт-система (reports-frontend
) использует React и библиотеку @react-keycloak/web
для OIDC-аутентификации. Вот код App.tsx
:
import React from 'react';
import { ReactKeycloakProvider } from '@react-keycloak/web';
import Keycloak, { KeycloakConfig } from 'keycloak-js';
import ReportPage from './components/ReportPage';
const keycloakConfig: KeycloakConfig = {
url: process.env.REACT_APP_KEYCLOAK_URL,
realm: process.env.REACT_APP_KEYCLOAK_REALM || "reports-realm",
clientId: process.env.REACT_APP_KEYCLOAK_CLIENT_ID || "reports-frontend"
};
const keycloak = new Keycloak(keycloakConfig);
const App: React.FC = () => {
return (
<ReactKeycloakProvider
authClient={keycloak}
initOptions={{
onLoad: 'login-required',
pkceMethod: 'S256'
}}
>
<div className="App">
<ReportPage />
</div>
</ReactKeycloakProvider>
);
};
export default App;
Пояснения к коду:
keycloakConfig: Задаёт параметры подключения к Keycloak: URL (
http://localhost:8080
), realm (reports-realm
), client (reports-frontend
).ReactKeycloakProvider: Оборачивает приложение, обеспечивая OIDC-аутентификацию.
initOptions:
onLoad: 'login-required'
требует логин при входе;pkceMethod: 'S256'
включает PKCE для защиты.ReportPage: Компонент, отображающий интерфейс отчётов.
Компонент ReportPage
Компонент ReportPage.tsx
отображает интерфейс и запрашивает отчёт через /reports
:
import React, { useState } from 'react';
import { useKeycloak } from '@react-keycloak/web';
const ReportPage: React.FC = () => {
const { keycloak, initialized } = useKeycloak();
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const [reportData, setReportData] = useState<any | null>(null);
const downloadReport = async () => {
if (!keycloak?.token) {
setError('Not authenticated');
return;
}
try {
setLoading(true);
setError(null);
const response = await fetch(`${process.env.REACT_APP_API_URL}/reports`, {
headers: {
'Authorization': `Bearer ${keycloak.token}`
}
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
setReportData(data);
console.log('Report data:', data);
} catch (err) {
setError(err instanceof Error ? err.message : 'An error occurred');
} finally {
setLoading(false);
}
};
if (!initialized) {
return <div>Loading...</div>;
}
if (!keycloak.authenticated) {
return (
<div className="flex flex-col items-center justify-center min-h-screen bg-gray-100">
<button
onClick={() => keycloak.login()}
className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"
>
Login
</button>
</div>
);
}
return (
<div className="flex flex-col items-center justify-center min-h-screen bg-gray-100">
<div className="p-8 bg-white rounded-lg shadow-md">
<h1 className="text-2xl font-bold mb-6">Usage Reports</h1>
<button
onClick={downloadReport}
disabled={loading}
className={`px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 ${
loading ? 'opacity-50 cursor-not-allowed' : ''
}`}
>
{loading ? 'Generating Report...' : 'Download Report'}
</button>
{error && (
<div className="mt-4 p-4 bg-red-100 text-red-700 rounded">
{error}
</div>
)}
{reportData && (
<div className="mt-4 p-4 bg-green-100 text-green-700 rounded">
<h2 className="text-lg font-bold">Report Data</h2>
<p>ID: {reportData.id}</p>
<p>Title: {reportData.title}</p>
<p>Content: {reportData.content}</p>
<p>User: {reportData.user}</p>
</div>
)}
</div>
</div>
);
};
export default ReportPage;
Пояснения к коду:
useKeycloak: Хук из
@react-keycloak/web
, предоставляет доступ к состоянию Keycloak (keycloak.token
,initialized
,authenticated
).downloadReport: Отправляет запрос на
/reports
с JWT-токеном в заголовкеAuthorization: Bearer ${keycloak.token}
. Если токен отсутствует, выводит ошибку.Состояние:
loading
показывает процесс загрузки,error
отображает ошибки (например, 403, если нет ролиreport_user
),reportData
хранит ответ от/reports
.Интерфейс: Если пользователь не аутентифицирован, показывается кнопка "Login". После логина — кнопка "Download Report" и отображение данных отчёта (например,
{ id: 123, title: "Usage Report 45" }
).fetch: Запрашивает
/reports
, ожидая JSON. Проверяетresponse.ok
и обрабатывает ошибки.
Backend-интеграция
API отчётов (reports-api
) проверяет JWT-токены. Вот код server.js
:
const express = require('express');
const jwt = require('jsonwebtoken');
const jwksClient = require('jwks-rsa');
const cors = require('cors');
const app = express();
app.use(cors({
origin: 'http://localhost:3000',
methods: ['GET', 'POST', 'OPTIONS'],
allowedHeaders: ['Content-Type', 'Authorization'],
}));
app.use(express.json());
app.use((req, res, next) => {
console.log(`Received ${req.method} request to ${req.url}`);
next();
});
const keycloakRealm = 'reports-realm';
const keycloakUrl = 'http://keycloak:8080';
const issuerUrl = 'http://localhost:8080';
const jwksUri = `${keycloakUrl}/realms/${keycloakRealm}/protocol/openid-connect/certs`;
const client = jwksClient({
jwksUri: jwksUri,
});
function getKey(header, callback) {
client.getSigningKey(header.kid, (err, key) => {
if (err) {
console.error('Error fetching signing key:', err);
callback(err, null);
} else {
const signingKey = key?.getPublicKey();
callback(null, signingKey);
}
});
}
const verifyToken = (req, res, next) => {
const authHeader = req.headers['authorization'];
if (!authHeader) {
console.log('No Authorization header provided for', req.url);
return res.status(401).json({ error: 'No token provided' });
}
const token = authHeader.split(' ')[1];
if (!token) {
console.log('Invalid token format for', req.url);
return res.status(401).json({ error: 'Invalid token format' });
}
console.log('Token for', req.url, ':', token);
jwt.verify(token, getKey, {
issuer: `${issuerUrl}/realms/${keycloakRealm}`,
algorithms: ['RS256'],
}, (err, decoded) => {
if (err) {
console.error('Token verification failed for', req.url, ':', err.message);
return res.status(401).json({ error: 'Token verification failed', details: err.message });
}
if (decoded.azp !== 'reports-frontend') {
console.log('Invalid azp for', req.url, ':', decoded.azp);
return res.status(401).json({ error: 'Invalid client', details: 'azp does not match reports-frontend' });
}
if (!decoded.realm_access?.roles.includes('report_user')) {
console.log('User does not have required role for', req.url, ':', decoded.realm_access?.roles);
return res.status(403).json({ error: 'Insufficient permissions', details: 'report_user role required' });
}
console.log('Decoded token for', req.url, ':', decoded);
req.user = decoded;
next();
});
};
app.get('/reports', verifyToken, (req, res) => {
const report = {
id: Math.floor(Math.random() * 1000),
title: `Usage Report ${Math.floor(Math.random() * 100)}`,
content: `This is a sample report generated on ${new Date().toISOString()}.`,
user: req.user.preferred_username,
};
res.json(report);
});
app.listen(8000, () => console.log('Backend running on port 8000'));
Пояснения к коду:
CORS: Разрешает запросы с
http://localhost:3000
(фронт-система), чтобы избежать ошибок кросс-доменного доступа.Логирование:
app.use((req, res, next))
выводит в консоль все запросы для отладки.Keycloak настройки:
keycloakRealm
,keycloakUrl
,jwksUri
указывают realm (reports-realm
) и адрес Keycloak для получения публичных ключей (JWKS).getKey: Получает публичный ключ для проверки подписи JWT.
-
verifyToken: Middleware проверяет JWT:
Извлекает токен из
Authorization: Bearer <token>
.Проверяет подпись с помощью JWKS (
jwt.verify
).Убеждается, что токен выдан для
reports-frontend
(decoded.azp
).Проверяет наличие роли
report_user
вrealm_access.roles
.Сохраняет декодированный токен в
req.user
.
Эндпоинт /reports: Возвращает данные отчёта (например,
{ id: 123, title: "Usage Report 45" }
) только для пользователей с рольюreport_user
.
Тестирование
Запустите проект:
docker compose up -d
Проверьте порты (8080, 3000, 8000) с
netstat -tuln
(Linux) илиnetstat -aon
(Windows).-
Доступ:
Фронт-система: http://localhost:3000.
Keycloak: http://localhost:8080 (логин:
admin/admin
).Backend: http://localhost:8000/reports (требуется токен).
Шаги тестирования:
Откройте http://localhost:3000, введите
access1
/accesspass1
.В DevTools (вкладка Network) найдите запрос к
/reports
, проверьте заголовокAuthorization: Bearer <JWT>
.Декодируйте JWT на jwt.io, убедитесь, что он содержит
realm_access.roles: ["report_user"]
,sub: access1
.Проверьте ответ от
/reports
(например,{ "id": 123, "title": "Usage Report 45" }
).

access3

/reports

/reports
в браузере, показывающий данные отчёта Проблемы и решения
CORS: Если фронт-система не получает ответ, проверьте CORS в
server.js
(origin: '
http://localhost:3000
'
).JWT: Если токен не содержит
report_user
, проверьте маппинг ролей в Keycloak ("Role Mappings").Логи: Используйте консольные логи в
server.js
для отладки (например, ошибки верификации).
9. Решение исходной задачи: интеграция платформ через Keycloak
Мы начали с задачи: обеспечить доступ из фронт-системы (reports-frontend
) к API отчётов (reports-api
) через общекорпоративный Keycloak, чтобы JWT-токен содержал роль report_user
. В контексте e-commerce это можно представить как интерфейс интернет-магазина, где менеджеры запрашивают отчёты о продажах, а Keycloak управляет аутентификацией через Single Sign-On (SSO). После изучения SSO, OIDC, Keycloak и практического примера (часть 8) мы готовы показать, как системный аналитик решает эту задачу. В крупных компаниях аналитик не настраивает Keycloak сам, а подаёт заявку (например, в Jira) и координирует с администраторами Keycloak, разработчиками фронт-системы и API, а также владельцами бизнес-логики. Непонимание OpenID Connect (OIDC) или Keycloak может привести к ошибкам в заявке (например, отсутствие роли report_user
в токене) или задержкам из-за неясности, с кем обсуждать детали.
Для наглядности начнём с диаграммы, показывающей поток доступа:

reports-frontend
получает JWT с ролью report_user
, а reports-api
проверяет токен для доступаАналитика: подача заявки и координация
В крупных системах аналитик инициирует заявку на настройку Keycloak, а не выполняет её сам. Это требует чёткого описания требований и взаимодействия с командами. Без понимания OIDC и Keycloak заявка может быть неполной, что приведёт к ошибкам (например, токен без report_user
). Вот шаги аналитики:
-
Сбор требований:
С владельцами API отчётов: Какие роли нужны? Например,
report_user
для доступа к отчётам,administrator
для управления.Какие данные в JWT? Роль
report_user
обязательна, возможно, кастомные атрибуты (например,department
для фильтрации отчётов).Риски: Неправильные роли (доступ к чужим отчётам), отсутствие атрибутов, низкая производительность.
-
Подача заявки:
-
Для админов Keycloak: Включить в заявку:
Создание realm
reports-realm
(или использование существующего).Добавление пользователей (
access1
) или синхронизацию с Active Directory (AD).Создание роли
report_user
и её маппинг на пользователей.Настройку клиентов:
reports-frontend
(public, redirect URI:http://localhost:3000/*
, PKCE: Enforced),reports-api
(bearer-only, с секретомoNwoLQdvJAvRcL89SydqCWCe5ry1jMgq
).
-
Пример текста заявки:
Создать realm reports-realm. Добавить пользователя access1 с ролью report_user. Настроить клиенты: - reports-frontend: public, redirect URI http://localhost:3000/*, включить PKCE (S256). - reports-api: bearer-only, секрет oNwoLQdvJAvRcL89SydqCWCe5ry1jMgq.
-
-
Координация с командами:
Разработчики фронт-системы: Убедиться, что
reports-frontend
использует OIDC с PKCE (как вApp.tsx
,ReportPage.tsx
, часть 8).Разработчики API отчётов: Настроить верификацию JWT с проверкой
report_user
(как вserver.js
, часть 8).DevOps: Подтвердить запуск Keycloak и приложений (как в
docker-compose.yml
, часть 8).
-
Проверка инфраструктуры:
Источник пользователей: AD (для корпоративных пользователей) или PostgreSQL (для прототипа)?
Безопасность: HTTPS для всех запросов, PKCE для
reports-frontend
, MFA для продакшена.Масштабируемость: Поддерживает ли Keycloak нагрузку от множества пользователей?
Схема процесса аналитики:

Аналитик должен:
С владельцами API: Уточнить роли (
report_user
).С админами Keycloak: Подать заявку на настройку
reports-realm
, ролей, клиентов.С разработчиками: Проверить OIDC, PKCE, верификацию JWT.
Тестировать: Декодировать JWT в DevTools, проверить доступ к
/reports
.
10. Заключение
Мы начали с задачи: обеспечить доступ из фронт-системы (reports-frontend
) к API отчётов (reports-api
) через общекорпоративный Keycloak, чтобы JWT-токен содержал роль report_user
. В контексте e-commerce это можно представить как интерфейс интернет-магазина, где менеджеры запрашивают отчёты о продажах, а Keycloak управляет аутентификацией через Single Sign-On (SSO). Разобрав принципы SSO, OIDC, компоненты Keycloak (realms, хранилища, PKCE) и практический пример (часть 8), мы показали, как системный аналитик решает эту задачу через заявки и координацию с командами: администраторами Keycloak, разработчиками фронт-системы и API, а также владельцами бизнес-логики.
Для наглядности вот финальная схема, показывающая роль аналитика в координации:

reports-realm
, согласовывает роли, и тестирует JWT в DevTools, чтобы убедиться, что доступ работает.Итоги
Keycloak упрощает задачу интеграции платформ через SSO:
Централизация: Пользователи логинятся один раз через
reports-realm
, получая доступ кreports-frontend
иreports-api
.Безопасность: Роль
report_user
в JWT обеспечивает доступ, а PKCE и HTTPS защищают от атак.Гибкость: Keycloak поддерживает PostgreSQL или Active Directory для хранения пользователей.
Для аналитика ключевые уроки:
Чёткая заявка: Указывайте в заявке (например, в Jira) создание
reports-realm
, добавление пользователей (access1
), ролей (report_user
), клиентов (reports-frontend
,reports-api
), и включение PKCE.Координация: Обсуждайте с владельцами API, какие роли нужны, с разработчиками — интеграцию OIDC, с админами — настройку Keycloak.
Тестирование: Проверяйте JWT в DevTools (как в частях 8–9), декодируя токен на jwt.io, чтобы убедиться, что он содержит
realm_access.roles: ["report_user"]
.
Типичные проблемы
Непонимание OIDC: Аналитик может не знать, какие данные (роли, атрибуты) нужны в JWT или с кем их обсуждать.
Ошибки в заявке: Неполные требования (например, отсутствие
report_user
) приводят к неправильным токенам.Задержки: Несогласованность между командами тормозит настройку.
Что дальше
Для улучшения интеграции:
MFA: Включите многофакторную аутентификацию в Keycloak для продакшена.
AD-интеграция: Настройте User Federation для синхронизации пользователей из Active Directory.
Документация: Ведите реестр ролей и клиентов для аудита.
Тестирование: Используйте penetration testing для проверки безопасности.
Аналитикам стоит изучить документацию Keycloak (https://www.keycloak.org/docs) и попробовать пример из части 8: запустите проект, подайте тестовую заявку на настройку reports-realm
, и проверьте JWT в DevTools. Это поможет уверенно решать задачи интеграции платформ!
svetayet
отличная исчерпывающая статья, какие уже редко попадаются. спасибо за труд!
B4sil Автор
Приятно! Спасибо)