Аутентификация
SecureCodingHub поддерживает несколько методов аутентификации. Браузерные сессии используют JWT bearer-токены; публичный API использует долгоживущие API-ключи с авторизацией на основе областей и лимитами запросов на ключ.
Методы аутентификации
Выберите метод аутентификации, который лучше всего подходит Вашей организации:
Magic Code (Email OTP)
Беспарольный вход через 6-значный код, отправленный на email. Метод по умолчанию для всех пользователей. Коды истекают через 10 минут. Никаких паролей для управления или запоминания.
OIDC (OpenID Connect)
Корпоративный SSO через Azure AD, Okta или совместимых провайдеров. Поток кода авторизации с PKCE. Рекомендуется для организаций.
SAML 2.0
SSO на основе федерации для корпоративных сред. Поток входа, инициированный SP.
Поток Magic Code
Беспарольный поток аутентификации по умолчанию работает следующим образом:
Пользователь вводит свой email-адрес
Сервер отправляет 6-значный OTP на email
Пользователь вводит код
Сервер проверяет код и выпускает JWT
JWT хранится в браузере для управления сессией
Поток SSO
Когда SSO настроен для Вашей организации, поток аутентификации меняется:
Пользователь открывает точку входа SSO для своей организации (ссылка включает org slug; сегодня нет автоматического определения email → домен)
Браузер перенаправляет на настроенный поставщик идентификации
Пользователь аутентифицируется с корпоративными учётными данными
IdP возвращает код авторизации (OIDC) или SAML-утверждение в callback SecureCodingHub
Сервер валидирует ответ, JIT-провизионит пользователя при первом входе и выпускает JWT
Пользователь вошёл в систему
JWT-токены
Все браузерные аутентифицированные сессии управляются с использованием JSON Web Tokens, выпускаемых бэкендом после успеха шага с magic-кодом или SSO.
| Свойство | Значение |
|---|---|
| Алгоритм | HS256 |
| Срок жизни | 30 дней с момента выпуска. В приложении нет потока обновления; пользователи повторно аутентифицируются через magic-код или SSO, как только токен истекает. |
| Claims | User id, organization id, role, name, email, expiry. |
| Передача | Заголовок Authorization: Bearer … на каждом внутреннем API-вызове. |
| Хранилище | Хранится на стороне клиента в localStorage под ключом sch-token. Сегодня нет опции HttpOnly cookie. |
API Key Bearer (публичный API)
Публичная REST и webhook-поверхность под /api/public/v1/* использует долгоживущие API-ключи вместо JWT. Ключи создаются из админ-консоли в Организация → API-ключи и отправляются на каждом запросе как стандартный bearer-заголовок:
Authorization: Bearer scs_live_…| Свойство | Значение |
|---|---|
| Формат | scs_live_ + 32 случайных base62-символа. 41 символ всего. |
| Хранилище | На сервере хранятся только SHA-256-хеш, префикс и последние четыре символа. Полный токен показывается один раз при создании и не может быть получен снова. |
| Области | 16 точных областей (например, users:read, assignments:write, sarif:ingest). Запрос без требуемой области возвращает 403 insufficient_scope. |
| Срок жизни | По умолчанию бессрочный. Опциональная дата истечения может быть установлена при создании. Ключи можно отозвать в любой момент; отзыв вступает в силу немедленно. |
| Отслеживание последнего использования | Каждый успешный вызов обновляет поле lastUsedAt ключа для аудита и гигиены ротации. |
Полная справка в API → Аутентификация и области доступа.
Лимитирование запросов
Каждый публичный API-ключ ограничен двумя скользящими окнами, защищающими платформу от убегающих скриптов и не дающими одному тенанту лишать другого:
| Окно | Лимит | Заголовки ответа |
|---|---|---|
| В минуту | 60 запросов | Retry-After, X-RateLimit-Window: per_minute, X-RateLimit-Limit: 60 |
| В час | 1 000 запросов | Retry-After, X-RateLimit-Window: per_hour, X-RateLimit-Limit: 1000 |
Запросы, превышающие любое окно, получают 429 rate_limited с заголовком Retry-After в секундах. Отдельный IP-лимитер (5 запросов / 15 минут) покрывает анонимную веб-форму контакта. Внутренний браузерный трафик сессии против JWT-защищённого админ-API сегодня не лимитируется.
Подробное руководство по повторным попыткам и пример клиента с экспоненциальным backoff в API → Лимиты запросов.
Аудит-логирование
Каждое мутирующее действие — независимо от того, исходит ли оно от admin-пользователя в браузере или от публичного API-ключа — записывается в таблицу аудит-лога на уровне организации. Действия только для чтения (list, get, запросы к панели) не аудируются; фокус на изменениях с downstream-влиянием.
| Поле | Значение |
|---|---|
action | Точечный идентификатор того, что произошло (например, user.updated, assignment.created, apikey.revoked, sarif.ingested). |
actorEmail / actorRole | Email и роль актора. Изменения админ-интерфейса несут email человека и org_admin. Изменения API-ключа несут apikey:<api-key-uuid> и роль api_key. |
targetType, targetId, targetLabel | Ресурс, который был изменён. Метка — это короткое человекочитаемое описание, используемое в интерфейсе аудит-лога. |
metadata | JSON-стрингифицированный контекст, точно описывающий, что изменилось (например, новые области на API-ключе, срок до vs после на задании). |
ipAddress | Source IP запроса, вызвавшего изменение. |
createdAt | Временная метка UTC. |
Полный аудит-поток можно запросить из админ-интерфейса (Организация → Журнал аудита) или программно через GET /api/public/v1/audit-log. Обе поверхности поддерживают фильтрацию по действию, актору и диапазону дат, а админ-интерфейс выставляет экспорт CSV для паков доказательств.
Безопасность сессий
- Токены валидируются на каждом API-запросе
- Неверные или истёкшие токены отклоняются
- Сессии SSO уважают политики сессий IdP
- Magic-коды одноразовые и ограниченные по времени
Дизайн-решения аутентификации SecureCodingHub и их обоснование
Путь аутентификации по умолчанию в SecureCodingHub — беспарольный. Мы приняли это решение намеренно. Подавляющее большинство компрометаций учётных данных, которые мы видим в данных обучения клиентов, по-прежнему восходят к переиспользованию паролей, слабым выборам паролей и фишингу статических секретов. Удаление пароля из основного потока входа устраняет класс режимов отказа, которые ни одна политика не может полностью смягчить. Для организаций, требующих традиционного парольного резерва, мы навязываем минимумы, соответствующие текущим рекомендациям NIST: минимум длины, а не правила сложности, проверка против известных корпусов скомпрометированных паролей и отсутствие принудительной ротации при отсутствии доказательств компрометации.
Восстановление по email намеренно сохраняется даже для учётных записей с SSO. Когда поставщик идентификации становится недоступным или когда запись подрядчика в корпоративном каталоге удаляется в середине вовлечения, нам всё ещё нужен детерминированный, аудируемый путь обратно в учётную запись для верифицированного владельца. Канал восстановления ограничен по запросам, одноразовый и логируется отдельно от стандартного потока событий входа, чтобы команды безопасности могли обнаруживать аномальную активность восстановления без её потери в обычном шуме входа.
Общие учётные записи не поощряются на уровне продукта, а не блокируются полностью. Мы выводим предупреждение в админ-консоли, когда шаблоны использования предполагают, что одно место делится между несколькими людьми, потому что общие места ломают индивидуальную ответственность, искажают отчётность по прогрессу и усложняют любое будущее расследование инцидента. Организации, которым нужен кросс-командный доступ к панелям, должны использовать назначение ролей и SCIM-провизионированные роли учащихся, описанные в Безопасности данных, а не переиспользовать учётные данные.
Сопоставление аутентификации с соответствием
SecureCodingHub готовится к SOC 2 Type II и ещё не завершил аудит, поэтому мы не претендуем на сертификацию. Однако мы проектируем подсистему аутентификации против тех же семейств контролей, которые команда безопасности ожидала бы при оценке вендора для этого аудита. Ожидания SOC 2 CC6.1 вокруг логического доступа — уникальная идентификация каждого пользователя, многофакторная или эквивалентная step-up для чувствительных действий и отзыв при увольнении — адресованы через учётные записи на пользователя, magic-код или выпущенные IdP учётные данные как второй фактор и SCIM-управляемую деактивацию.
Элементы управления ISO 27001 Annex A.9, покрывающие политику контроля доступа, регистрацию пользователей и привилегированный доступ, адресованы через документированные определения ролей, регистрацию на уровне организации, ограниченную верифицированными доменами, где запрошено, и явное разделение ролей org_admin / learner внутри каждого тенанта. Для организаций, подпадающих под раздел 8 PCI DSS, релевантный элемент управления в том, что мы никогда не храним данные держателей карт и никогда не аутентифицируем держателей карт против платформы; SecureCodingHub — это среда обучения, а не среда платежей, поэтому поверхность, к которой применяется PCI, намеренно узкая.
Ничто из вышеперечисленного не должно читаться как замена Вашей собственной оценки. Пакеты доказательств, включая списки субпроцессоров, диаграммы потоков данных и текущая позиция аудита, доступны по запросу от security@securecodinghub.com.
Что меняется, когда SSO включён
Включение SSO — это не просто замена одного экрана входа другим — это меняет несколько runtime-поведений, которые команды безопасности должны понять до развёртывания. Как только Ваша организация подключена к поставщику идентификации, локальный путь с magic-кодом больше не предлагается пользователям, чей email соответствует Вашему верифицированному домену. Они перенаправляются на Ваш IdP вместо этого. Это правильное поведение по умолчанию, но это означает, что восстановление во время сбоя IdP смещается полностью к Вашей IT-команде, а не к поддержке SecureCodingHub. Мы рекомендуем задокументировать этот путь эскалации внутри до включения SSO для большой пользовательской базы.
Поведение блокировки также смещается: ограниченные по запросам неудачные попытки на пути локального magic-кода больше не применяются к тому же пользователю, как только SSO в силе, потому что вся валидация учётных данных происходит в IdP. Политика блокировки тогда управляется Вашей конфигурацией IdP, а не значениями по умолчанию SecureCodingHub. Записи аудит-лога, написанные мутациями, которые пользователь выполняет после входа, продолжают нести email пользователя и роль org_admin / learner; платформа в настоящее время не хранит метод аутентификации на стороне IdP (например, был ли удовлетворён MFA в IdP) в строке аудита, поэтому для этого уровня детализации Вы бы коррелировали против собственного потока логов центрального поставщика идентификации.