Перейти к содержанию
FoxAuth

Возможности

В комплекте всё. Большая часть выключена.

FoxAuth — это один сервер без редакций. Authorization Code с PKCE и OpenID Connect работают с первого запуска, а почти всё остальное ждёт за именованным флагом. На практике ваша поверхность атаки — это ровно те возможности, которые вы сами запросили. На каждой карточке указано, включена ли возможность сразу или ждёт своего флага.

Каждый флаг ниже ведёт на свою запись в справочнике настроек: он генерируется из кода и называет значение по умолчанию и последствия.

Протокол

Любой тип гранта, который может запросить клиент OAuth 2.1.

Гранты и эндпоинты. Authorization Code с PKCE и OpenID Connect включены всегда; большая часть остального ждёт флага.

Authorization Code с PKCE

PKCE обязателен для каждого клиента, публичного или конфиденциального, как того требует OAuth 2.1. Redirect URI сравниваются точно.

RFC 7636

OpenID Connect Core 1.0

ID-токены, эндпоинт UserInfo и discovery — со стандартным набором claims и попарными (pairwise) идентификаторами субъекта.

OIDC Core 1.0

Идентификация издателя

Каждый ответ авторизации содержит iss, поэтому клиента нельзя обманом заставить принять код другого издателя.

RFC 9207

Resource Indicators

Ограничьте аудиторию токена параметром resource и проверяйте её на сервере ресурсов. Включено по умолчанию.

resourceIndicators.enabledRFC 8707

Грант Client Credentials

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

clientCredentials.enabled

Грант Refresh Token

Долгие сессии с ротацией и обнаружением повторного использования. Предъявите токен повторно — и отзывается всё выданное разрешение. Включено по умолчанию: этот тип гранта доступен, пока offline_access входит в поддерживаемые scope.

scopes

Device Authorization Grant

Вход на телевизоре или в CLI: пользователь вводит код на другом устройстве.

deviceFlow.enabledRFC 8628

CIBA

Аутентификация по обратному каналу, инициированная клиентом: клиент запрашивает, пользователь подтверждает по отдельному каналу.

ciba.enabledCIBA Core 1.0

Pushed Authorization Requests

Клиент сначала отправляет запрос напрямую серверу, а через браузер передаёт только request_uri.

par.enabledRFC 9126

Объекты запроса

Подписанные параметры request и request_uri: целостность самого запроса авторизации защищена.

requestObjects.enabled

JARM

Ответы авторизации, защищённые JWT: подписанные и, при необходимости, зашифрованные.

responseMode.jwt.enabledJARM

Rich Authorization Requests

Детальные authorization_details вместо строки scope — для платежей и похожих сценариев.

richAuthorizationRequests.enabledRFC 9396

Интроспекция токенов

Серверы ресурсов спрашивают у издателя, активен ли ещё токен и что он содержит.

introspection.enabledRFC 7662

Ответы интроспекции в виде JWT

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

jwtIntrospection.enabledRFC 9701

Отзыв токенов

Клиент отзывает токен доступа или refresh-токен, который ему больше не нужен.

revocation.enabledRFC 7009

Подписанные ответы UserInfo

UserInfo возвращается в виде подписанного JWT вместо обычного JSON.

jwtUserinfo.enabled

Параметр claims

Выбор claims в каждом запросе, включая обязательные (essential) claims и запрос acr.

claimsParameter.enabled

Выход по инициативе RP

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

rpInitiatedLogout.enabled

Backchannel logout

Уведомление всех клиентов сессии о её завершении — напрямую, от сервера к серверу.

backchannelLogout.enabled

Безопасность

Привязка к отправителю и защита, которая уже включена.

Профили банковского уровня — это флаги, а не редакции. Всё остальное в этом списке включено с первого запуска.

DPoP

Токены доступа и refresh-токены, привязанные к отправителю, включая серверные nonce: одного украденного токена недостаточно.

dpop.enabledRFC 9449

Аутентификация клиента по mTLS

Клиентские сертификаты для аутентификации и токены доступа, привязанные к сертификату.

mTLS.enabledRFC 8705

Поведение профилей FAPI

Более строгие проверки, которых требуют профили Financial-grade API, — одним переключателем.

fapi.enabled

Шифрование токенов и ответов

Зашифрованные ID-токены, ответы UserInfo и JARM на зарегистрированных ключах клиента.

encryption.enabled

Второй фактор TOTP

Одноразовые пароли на основе времени в каждом бакете; для консоли администратора их можно сделать обязательными.

RFC 6238

Попарные идентификаторы субъекта

Свой sub для каждого сектора, с солью из базы данных, поэтому две доверяющие стороны не могут сопоставить пользователя.

Троттлинг перебора паролей при входе

Сохраняемые счётчики неудачных попыток для каждой учётной записи с нарастающими блокировками. Отказ из-за троттлинга выглядит точно так же, как неверный пароль.

Ограничение частоты запросов по origin

Свои лимиты для каждого класса маршрутов, включено по умолчанию; число доверенных прокси-хопов настраивается.

rateLimit.enabled

CORS, закрытый данными

Origin получает доступ к ответам, только если его указал проект, которому принадлежит вызывающий клиент. Никакая настройка с wildcard его не открывает.

cors.enabled

Заголовки безопасности

HSTS, Permissions-Policy, защита от встраивания во фреймы и от подмены типа содержимого — в каждом ответе.

Контроль доступа по scope

Проверка scope для каждого клиента — на эндпоинте авторизации и ещё раз на эндпоинте токенов.

Журнал аудита администрирования: исполнитель, действие, объект и время каждого изменения.
Журнал аудита. Записи делаются до изменения, а хранилище не позволяет ни обновлять, ни удалять их, поэтому запись нельзя изменить задним числом.

Администрирование

Один API управления, три входа.

Консоль, HTTP API и инструменты MCP обращаются к одним и тем же маршрутам, поэтому проверки и запись аудита не могут разойтись.

Консоль администратора

Проекты, OAuth-клиенты, администраторы и их группы, бакеты пользователей, конечные пользователи, внешние провайдеры, подключения SCIM, настройки, SMTP и ключи подписи. У каждого экрана есть свой адрес. Изменение, которое может закрыть людям вход или сломать приложения, сначала сообщает, кого оно затронет и сколько их, и применяется только после вашего подтверждения.

Журнал аудита только на дозапись

Каждое действие администратора, меняющее состояние, фиксирует исполнителя, действие, объект и время. Запись делается до изменения, а у хранилища нет способа обновить или удалить её.

Активные пользователи бакета за месяц

Каждый бакет считает людей, которым выдал токены, — по одному разу за месяц и за день по UTC, отдельно для локального входа, входа через внешнего провайдера, продления и поставки из каталога. Закрытый месяц больше не меняется, а история переживает и самих людей, и бакет. Страница Usage показывает каждый бакет рядом с группой-владельцем, поэтому экземпляр, который вы держите для других команд или клиентов, может сказать, кто сколько использовал.

Администрирование через MCP

126 инструментов MCP: ИИ-агент вызывает их по POST /mcp, защищённому ресурсу OAuth 2.1, а операции с серьёзными последствиями требуют подтверждения вторым вызовом.

mcp.enabledRFC 9728

Авторизация для ваших собственных MCP-серверов

Объявите сторонний MCP-сервер защищённым ресурсом проекта, и этот сервер будет выпускать токены, аудитория которых — ровно этот ресурс, без изменений в коде и без перезапуска. В бакете с собственным адресом объявлению ничего не нужно от самого ресурса — он может быть внутренним, работать на localhost или ещё не быть развёрнутым, — а другой тенант может объявить тот же URL, никак не затронув ваш. По умолчанию токены самодостаточны, поэтому ресурс проверяет их по опубликованным ключам своего бакета, не имея собственных учётных данных.

RFC 8707

Документы идентификации клиента

client_id — это HTTPS-URL JSON-документа с описанием клиента; документ загружается и проверяется по требованию и никогда не сохраняется. Именно этот механизм спецификация авторизации MCP называет первым для клиента, с которым у сервера нет предварительных отношений.

clientIdMetadataDocument.enabled

Динамическая регистрация клиентов

Клиенты регистрируются сами в рамках политики регистрации. Спецификация MCP объявила этот механизм устаревшим в пользу документов идентификации клиента.

registration.enabledRFC 7591

Управление регистрацией

Чтение, изменение и удаление регистрации с помощью её registration access token.

registrationManagement.enabledRFC 7592

Клиенты в базе данных

Клиенты хранятся в собственном хранилище сервера и создаются через консоль, API, динамическую регистрацию или скрипт настройки. Статического файла с клиентами нет.

Владение через группы

Проекты и бакеты пользователей принадлежат группе. Доступ даёт только членство в ней, и оно проверяется заново при каждом запросе. Бакет переходит к другой группе вместе с проектами, которые им пользуются.

Бакет по пути или по хосту

Каждый бакет пользователей — отдельный издатель со своими метаданными и ключами подписи, доступный по пути на сервере или по собственному имени хоста: одно из двух, но не оба сразу. Имя хоста позволяет браузеру изолировать cookie входа этого бакета по origin и публикует одно расположение метаданных вместо двух; цена — DNS-запись и сертификат, которые вы предоставляете сами. Смена адреса — отдельная операция: она показывает, какие клиенты сломаются, ещё до того, как их сломать.

Удаление бакета можно отменить

Удаление сразу отключает бакет, а уничтожает его через 30 дней. До этого срока в нём ничего не уничтожается, и восстановление возвращает бакет со всеми сессиями и refresh-токенами, которые продолжают действовать.

Самообслуживание конечных пользователей

Подтверждение email и сброс пароля в каждом бакете — с лимитами попыток, паузами между ними и одноразовыми ссылками.

Управление конечными пользователями

Пригласите человека, чтобы он сам задал себе пароль, отметьте адрес как подтверждённый или завершите вход человека в одно приложение, не трогая остальные. До 100 человек можно разом деактивировать, активировать, удалить или завершить их сессии, и у каждого будет своя запись в журнале аудита.

Вход через Google, Microsoft, Apple или GitHub

Подключите провайдера по имени, и консоль покажет, что сделать на его стороне и какой именно адрес callback зарегистрировать; вы вводите только выданные им значения. Любого другого провайдера OIDC можно настроить вручную. Настройка делается для каждого бакета пользователей, поэтому у каждого тенанта своё приложение. Пробный вход показывает, что сделает настоящий вход, ещё до того, как на провайдера кто-то положится, а callback отклоняет ответ, если его прислал не тот издатель, у которого начался вход. Администраторы тоже могут входить в консоль через провайдера вашей организации.

federation.enabled

Поставка пользователей по SCIM 2.0

Microsoft Entra ID, Okta или любой каталог с SCIM 2.0 создаёт, изменяет и удаляет пользователей и группы бакета. Удаление сразу многих людей можно не применять, а задержать до проверки. Заменённый секрет или статический токен продолжает работать, пока каталог не перейдёт на новый.

scim.enabledRFC 7644

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

Каждый бакет с собственным адресом подписывает своими ключами, опубликованными по его собственному jwks_uri, поэтому токен одного тенанта никогда не пройдёт проверку на сервере ресурсов другого. Группа — владелец бакета ротирует их одним действием: новый ключ публикуется до того, как им можно подписывать, а выведенный из оборота остаётся опубликованным, пока не истекут его токены. Скомпрометированный ключ можно сразу отозвать, и ничто подписанное им больше не пройдёт проверку. Набор ключей экземпляра при этом остаётся за суперадминистратором.

Панель настроек консоли администратора с флагами типов грантов и их текущими значениями.
Настройки — по панели на каждую область. Флаг здесь — тот же ключ, что описан в Справочнике; перед сохранением изменения проверяются в составе всей конфигурации.

Расширяемость

Меняйте поведение без форка.

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

31 точка переопределения

Поиск учётной записи, политика взаимодействия, ротация refresh-токенов, разрешение ресурсов, попарные идентификаторы, обработка RAR и многое другое — всё подменяется в момент вызова.

Подключаемое хранилище

Каждая сохраняемая модель проходит через единый интерфейс адаптера. В комплекте реализации: PostgreSQL, MongoDB и хранилище в памяти; какую использовать, определяет одна строка подключения.

Монтируемое приложение Elysia

Импортируйте приложение и смонтируйте его в своём сервисе на Bun. Шага инициализации нет — сервер запускается при импорте.

Встроенный интерфейс входа и согласия

Экраны на React и Ant Design, которые можно оформить под себя или заменить через политику взаимодействия.

Эксплуатация

То, что нужно, когда что-то пошло не так.

Разверните, наблюдайте и выясняйте, почему запрос завершился ошибкой.

Готовый образ контейнера

ghcr.io/redfox-soft/oauth-server-ts с тегом для каждого релиза и latest, а также Compose-файл, который подготавливает схему.

Хранилище ошибок сервера

Внутренние сбои записываются и доступны для просмотра в консоли. Обычные отказы клиентам — это корректное поведение, и туда они не попадают.

errorStore.enabled

Отправка в Sentry по желанию

Отправка отчётов полностью вынесена из обработки запроса: сбой попадает в неё только после того, как классифицирован как дефект, поэтому ответы не меняются.

sentry.enabled

Понятные настройки

Для каждой настройки уровня сервера описаны тип, значение по умолчанию и последствия, а редактируется она в консоли.

Машиночитаемый справочник

Справочники эндпоинтов, настроек, Admin API, инструментов MCP и переменных окружения генерируются из самого кода.

Дальше

Сравните с тем, что используете сейчас.

Мы ведём фактическое датированное сравнение с серверами, с которыми FoxAuth обычно сопоставляют.

Уже используете другое решение? Мы ведём датированные сравнения с Auth0, authentik, Keycloak, Ory Hydra и Zitadel, и в каждом указано, какие страницы мы прочитали и когда.