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

Не ограничивайтесь исправлением переключателя организации в интерфейсе. Проверьте, откуда backend берет organization_id и разрешено ли текущему user_id работать с этой организацией.

Коротко: что сделать

  • Ограничить проблемный маршрут или функцию
  • Зафиксировать user_id, session_id и ошибочный tenant_id
  • Проверить claims SSO и локальную привязку аккаунта
  • Проверить серверную авторизацию каждого запроса
  • Оценить журналы доступа и масштаб инцидента

Почему возникает проблема

В multi-tenant системе организация должна определяться из подтвержденного членства пользователя, а не из параметра URL, cookie или последнего значения в общем кэше.

  • organization_id принимается от клиента без проверки членства
  • Кэш построен без tenant_id в ключе
  • SSO-сопоставление связывает аккаунты по неуникальному email
  • Сессия сохраняет организацию предыдущего пользователя
  • Фоновая задача обновляет записи без tenant scope
  • Роль проверяется глобально, а не внутри организации

Пошаговая диагностика

Проверку лучше проводить на одном воспроизводимом примере и фиксировать результат каждого шага. Так можно быстро отделить первопричину от побочных ошибок и не менять несколько компонентов одновременно.

  • Воспроизвести на тестовых пользователях двух организаций
  • Проследить формирование tenant context от SSO callback до SQL
  • Проверить все запросы к данным на фильтр tenant_id
  • Проверить ключи Redis и серверный кэш
  • Проверить смену аккаунта в одном браузере
  • Проанализировать audit log без изменения доказательств

Как исправить

Исправление должно быть серверным и централизованным: пользователь получает tenant context только после проверки активного членства.

  • Ввести обязательный middleware проверки организации
  • Строить запросы через tenant-scoped repository
  • Добавить tenant_id во все ключи кэша и очередей
  • Исправить SSO linking по устойчивому issuer + subject
  • Инвалидировать затронутые сессии
  • Добавить проверки доступа к файлам, экспорту и API

Как проверить результат

  • Проверить прямой запрос к чужому tenant_id
  • Проверить смену организаций для пользователя с несколькими членствами
  • Проверить logout и вход другим аккаунтом
  • Проверить фоновые задачи и выгрузки
  • Убедиться, что попытки доступа фиксируются в audit log

Как не допустить повторения

Изоляция арендаторов должна быть системным ограничением на уровне доступа к данным, а не соглашением разработчиков.

  • Добавить автоматические cross-tenant тесты
  • Использовать уникальные SSO-идентификаторы
  • Проводить ревизию запросов без tenant scope
  • Настроить аудит административных действий

Чего не стоит делать

  • Не скрывать чужие данные только CSS или frontend-проверкой
  • Не удалять журналы до разбора инцидента
  • Не связывать SSO-аккаунты только по email без правил
  • Не оставлять старые сессии активными после исправления

Что подготовить для диагностики

  • Идентификаторы тестовых пользователей и организаций
  • SSO claims без токенов
  • Пример ошибочного запроса
  • Схема таблиц членства и ролей
  • Логи доступа за период инцидента

Частые вопросы

Достаточно ли исправить organization_id в сессии?

Нет. Backend обязан проверять членство при каждом чувствительном запросе, иначе параметр можно подменить.

Нужно ли сбрасывать сессии?

Для затронутых пользователей обычно да, особенно если в сессии или кэше хранился неверный tenant context.

Это считается утечкой данных?

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

Когда стоит обратиться за помощью

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

Итог

Главное исправление — серверная проверка членства и tenant scope в запросах, кэше и фоновых задачах. Провести технический разбор можно через @rabotator_support.