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

DocPlatform поддерживает локальную аутентификацию (email + пароль) сразу после установки, с опциональным входом через Google и GitHub OIDC для команд, использующих этих провайдеров.

Локальная аутентификация (по умолчанию)

Локальная аутентификация работает без какой-либо настройки. Пользователи регистрируются с email и паролем и входят с теми же учетными данными.

Как это работает

  1. Регистрация — пользователь отправляет email + пароль. Пароль хешируется с помощью argon2id (рекомендованный OWASP 2024 алгоритм).
  2. Вход — пользователь отправляет учетные данные. Сервер проверяет хеш пароля и возвращает JWT-токены.
  3. Сессия — access token (RS256, срок жизни 15 минут) отправляется с каждым API-запросом. Refresh token (срок жизни 30 дней) используется для получения новых access token без повторной аутентификации.

Хеширование паролей

DocPlatform использует argon2id со следующими параметрами (стандарт OWASP 2024):

Параметр Значение
Алгоритм argon2id
Память 64 МБ
Итерации 3
Параллелизм 4
Длина соли 16 байт
Длина ключа 32 байта

Эти параметры не настраиваются — они соответствуют лучшим практикам безопасности. Хеши паролей хранятся в базе данных SQLite и никогда не покидают сервер.

Сброс пароля

Когда пользователь запрашивает сброс пароля:

  • С настроенным SMTP — на email пользователя отправляется одноразовая ссылка для сброса
  • Без SMTP — токен сброса выводится в stdout (логи сервера)
# Check server logs for the reset token
docplatform serve 2>&1 | grep "password reset"

Токен истекает через 1 час и может быть использован только один раз.

JWT-токены

DocPlatform выдает JWT-токены RS256 (RSA-SHA256) для аутентификации.

Жизненный цикл токенов

User logs in
    │
    ▼
┌─────────────────────────────────┐
│ Access Token (15 min)            │  ──►  Sent with every API request
│ Refresh Token (30 days)          │  ──►  Used to get new access tokens
└─────────────────────────────────┘
    │
    │  Access token expires
    ▼
┌─────────────────────────────────┐
│ POST /api/v1/auth/refresh        │
│ Body: { refresh_token: "..." }   │
└─────────────────────────────────┘
    │
    ▼
┌─────────────────────────────────┐
│ New Access Token (15 min)        │  ──►  Old refresh token rotated
│ New Refresh Token (30 days)      │  ──►  Old one invalidated
└─────────────────────────────────┘

Ротация refresh token

Каждый раз при использовании refresh token выдается новый refresh token, а старый инвалидируется. Это ограничивает окно уязвимости в случае компрометации токена.

Конфигурация

Переменная По умолчанию Описание
JWT_SECRET_PATH {DATA_DIR}/jwt-key.pem Путь к приватному ключу RS256
JWT_ACCESS_TTL 900 Срок жизни access token (в секундах)
JWT_REFRESH_TTL 2592000 Срок жизни refresh token (в секундах)

Управление ключами

Пара ключей RS256 автоматически генерируется при первом запуске, если файл не существует. Для ротации ключей:

  1. Остановите сервер
  2. Удалите файл ключа ({DATA_DIR}/jwt-key.pem)
  3. Запустите сервер — новый ключ будет сгенерирован

Все существующие сессии инвалидируются при ротации ключей. Пользователи должны войти заново.

Вход через Google OIDC (опционально)

Позвольте пользователям входить с помощью учетной записи Google.

Настройка

  1. Перейдите в Google Cloud Console
  2. Создайте новый проект (или используйте существующий)
  3. Перейдите в APIs & Services -> Credentials
  4. Нажмите Create Credentials -> OAuth 2.0 Client ID
  5. Тип приложения: Web application
  6. Добавьте авторизованный redirect URI: https://your-domain.com/api/v1/auth/callback/google
  7. Скопируйте Client ID и Client Secret

Установите переменные окружения:

export OIDC_GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
export OIDC_GOOGLE_CLIENT_SECRET=your-client-secret

Перезапустите сервер. На странице входа появится кнопка Sign in with Google.

Создание пользователей

Когда пользователь впервые входит через Google:

  • Создается учетная запись DocPlatform с его Google email
  • Ему назначается роль по умолчанию (permissions.default_role) в любом workspace, куда он приглашен
  • Пароль не устанавливается (можно добавить позже в профиле)

Вход через GitHub OIDC (опционально)

Позвольте пользователям входить с помощью учетной записи GitHub.

Настройка

  1. Перейдите в GitHub Developer Settings
  2. Нажмите New OAuth App
  3. Установите authorization callback URL: https://your-domain.com/api/v1/auth/callback/github
  4. Скопируйте Client ID и сгенерируйте Client Secret

Установите переменные окружения:

export OIDC_GITHUB_CLIENT_ID=your-client-id
export OIDC_GITHUB_CLIENT_SECRET=your-client-secret

Перезапустите сервер. На странице входа появится кнопка Sign in with GitHub.

Создание пользователей

Аналогично Google — учетная запись DocPlatform создается с использованием основного email GitHub. Если у учетной записи GitHub нет публичного email, пользователю предлагается указать его.

Управление сессиями

DocPlatform отслеживает активные сессии по каждому пользователю:

Поле Описание
Device Строка user-agent
IP-адрес IP клиента (для целей аудита)
Создана Когда была установлена сессия
Последняя активность Последний API-запрос

Пользователи могут просматривать и отзывать сессии на странице профиля. Администраторы могут просматривать все сессии в панели администрирования.

Отзыв сессий

  • По инициативе пользователя — Profile -> Sessions -> Revoke
  • По инициативе администратора — Admin -> Users -> выберите пользователя -> Revoke All Sessions
  • Ротация ключей — удаление JWT-ключа инвалидирует все сессии глобально

Политика паролей

Ограничение Значение
Минимальная длина 8 символов
Максимальная длина 128 символов
Хеширование argon2id (64 МБ памяти, 3 итерации, параллелизм 4)

Пароли проверяются при регистрации и сбросе пароля. DocPlatform не требует наличия определенных классов символов (заглавных, специальных) — длина является основной мерой безопасности в соответствии с текущими рекомендациями NIST.

Аутентификация WebSocket

WebSocket-соединения используют паттерн одноразового ticket, чтобы избежать раскрытия JWT-токенов в URL (которые могли бы появиться в логах сервера и истории браузера).

Процесс:

  1. Клиент вызывает POST /api/v1/auth/ws-ticket с валидным JWT
  2. Сервер возвращает случайный ticket (действителен 30 секунд, одноразовый)
  3. Клиент подключается к ws://host/ws?ticket={ticket}
  4. Сервер проверяет ticket, устанавливает WebSocket и уничтожает ticket

Это прозрачно для пользователей — веб-редактор обрабатывает получение ticket автоматически.

Рекомендации по безопасности

  • Включите OIDC для команд с учетными записями Google или GitHub — делегирует управление паролями проверенным провайдерам
  • Используйте HTTPS в production — JWT-токены являются bearer-токенами; перехваченные токены дают полный доступ
  • Сохраняйте короткий срок жизни токенов — 15-минутные access token ограничивают окно уязвимости
  • Следите за сессиями — периодически проверяйте активные сессии на наличие неожиданных устройств или IP-адресов
  • Ротируйте ключи ежегодно или после любого подозрения на компрометацию
  • Используйте HttpOnly cookies — DocPlatform хранит токены в cookies HttpOnly + Secure + SameSite=Strict, предотвращая кражу токенов через XSS