Перейти к содержимому

API: Аутентификация

Базовый URL: /api/v1/auth

Термины: JWT — JSON Web Token; LDAP — протокол доступа к каталогу; ADActive Directory. Полный список — в словаре терминов.

Вход в портал.

Тело запроса:

{
"login": "admin",
"password": "admin_change_me",
"authType": "local"
}
ПолеТипОписание
loginstringЛогин
passwordstringПароль
authTypelocal | domainТип учётной записи (логин/пароль в форме)

Ответ 200:

{
"success": true,
"data": {
"user": {
"id": "uuid",
"login": "admin",
"display_name": "Администратор портала",
"is_portal_admin": true
},
"token": "eyJ...",
"expiresIn": 900
}
}

JWT также устанавливается в httpOnly cookie portal_token. expiresIn — оставшееся время жизни в секундах; expiresAt — unix timestamp истечения. maxExpiresIn — полный срок из JWT_EXPIRES_IN.

Ошибки:

  • 401 — неверный логин или пароль
  • 400 — ошибка валидации
  • 429 — превышен лимит попыток (10/мин)

Пример curl:

Окно терминала
curl -X POST http://localhost/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"login":"admin","password":"admin_change_me","authType":"local"}' \
-c cookies.txt

Выход. Очищает cookie и отзывает JWT (jti в denylist до истечения TTL).

Продление сессии (sliding session). Требует действующий JWT в cookie. Предыдущий jti отзывается. Смена/сброс пароля увеличивает token_version — все старые JWT пользователя перестают действовать.

Ответ 200:

{
"success": true,
"data": {
"token": "eyJ...",
"expiresIn": 900
}
}

Cookie обновляется автоматически. Фронтенд вызывает endpoint проактивно (~50% оставшегося TTL), при возврате на вкладку, при фокусе окна и после каждой загрузки страницы.

Ошибки:

  • 401 — сессия истекла или пользователь заблокирован

Текущий пользователь. Требует авторизации.

Ответ 200:

{
"success": true,
"data": {
"user": {
"id": "...",
"login": "admin",
"display_name": "...",
"email": "admin@portal.local",
"auth_source": "local",
"is_portal_admin": true,
"is_active": true,
"last_login_at": "...",
"created_at": "...",
"groups": [
{ "id": "uuid", "name": "Читатели портала" }
]
}
}
}

groups — группы доступа, в которых состоит пользователь (для назначения прав через группы).

При authType: "domain" портал проверяет логин и пароль через LDAP bind. Пароли доменных пользователей не хранятся в Postgres.

При первом успешном входе создаётся запись в users с auth_source=domain (JIT-provisioning). При повторном входе обновляются display_name и email.

Настройка подключения: Админка → Службы → Синхронизация AD → Настройки (/services/ad-sync). По умолчанию LDAP не настроен.

Опциональный fallback для Docker/CI — переменные окружения:

ПеременнаяОписание
LDAP_URLURL сервера, напр. ldap://ldap:389
LDAP_BASE_DNБазовый DN, напр. dc=portal,dc=local
LDAP_BIND_DNService-account для поиска
LDAP_BIND_PASSWORDПароль service-account
LDAP_USER_FILTERФильтр входа, плейсхолдер {{username}}
LDAP_SEARCH_FILTERФильтр поиска, плейсхолдер {{query}}
LDAP_LOGIN_ATTRАтрибут логина: sAMAccountName (AD) или uid (OpenLDAP)

Локальный LDAP для разработки:

Окно терминала
docker compose --profile ldap up -d --build

После запуска контейнера ldap откройте Админка → Службы → Синхронизация AD → Настройки и укажите параметры из docker/ldap/.env.example (URL, Base DN, Bind DN, пароль, фильтры для OpenLDAP). Переменные LDAP_* в корневом .env — опциональный fallback; для ручной настройки через UI их можно не добавлять.

Тестовый пользователь: ivanov / domain123.

Ошибки доменного входа:

  • 400LDAP не настроен
  • 401 — неверный логин или пароль

См. также: directory.md

Публичный endpoint с доступными способами входа для экрана авторизации.

Ответ 200:

{
"success": true,
"data": {
"local": true,
"domain": true,
"keycloak": false
}
}

keycloak=true только если служба keycloak-sso включена и заполнены настройки OIDC.

Для входа через Keycloak используется OIDC Authorization Code + PKCE:

  1. Браузер открывает GET /auth/keycloak/login
  2. Portal редиректит пользователя в Keycloak
  3. Keycloak возвращает пользователя на GET /auth/keycloak/callback
  4. Portal создаёт/обновляет пользователя с auth_source=keycloak, ставит cookie portal_token и делает redirect на /

В этом сценарии POST /auth/login не используется.

После неуспешного OIDC-callback пользователь возвращается на / с параметром auth_error:

  • keycloak_disabled — вход через Keycloak выключен или не настроен
  • keycloak_missing_code — Keycloak не вернул code
  • keycloak_state_invalid — state устарел/не найден
  • keycloak_login_failed — ошибка обмена code/token или валидации id_token