Обзор
Private Channels включает опциональный Auth Service, который ограничивает доступ к шлюзу с помощью JWT-аутентификации и управления доступом на основе ролей (RBAC). Когда аутентификация отключена, шлюз принимает все подключения. Когда она включена, клиенты должны передавать действительный JWT в каждом запросе.
Эта страница охватывает обе аудитории:
- Разработчики — регистрация, вход, верификация кошелька и выполнение аутентифицированных запросов
- Операторы — включение auth service, настройка
JWT_SECRETи назначение ролиoperator
Включение аутентификации
Аутентификация включается путём установки JWT_SECRET (непустого значения) как на шлюзе, так и в Auth Service. Auth Service также требует AUTH_DATABASE_URL.
Если JWT_SECRET не задан, шлюз работает в открытом режиме — токен не требуется.
Docker Compose: Auth service является профилем Docker Compose и по умолчанию не запускается. Чтобы включить его, передайте
--profile authв командуdocker compose, а также--env-file .env, чтобы секреты, такие какJWT_SECRETиPOSTGRES_PASSWORD, корректно разрешались (Compose отключает автоматическую загрузку.env, как только передаётся любой флаг--env-file):docker compose -f docker-compose.devnet.yml --env-file versions.env --env-file .env.devnet --env-file .env --profile auth up -d
API Auth Service
Все эндпоинты находятся по пути /auth. Auth service слушает на порту AUTH_PORT (по умолчанию 8903).
POST /auth/register
Создать новый аккаунт. Все пользователи регистрируются с ролью user.
{ "username": "alice", "password": "hunter2" }
- Имя пользователя: 5–32 символа, буквенно-цифровые плюс
_и- - Пароль: 6–128 символов
- Возвращает созданного пользователя; пароль никогда не возвращается
POST /auth/login
Выполнить аутентификацию и получить подписанный JWT, действительный в течение 24 часов.
{ "username": "alice", "password": "hunter2" }
Возвращает { "token": "<jwt>" }. Неверное имя пользователя и неверный пароль оба возвращают 401, чтобы предотвратить перебор имён пользователей.
POST /auth/challenge-wallet
Запросить challenge для подписи с целью подтверждения владения кошельком Solana. Требуется действительный JWT.
Возвращает сообщение, nonce и время истечения. Challenge действителен в течение 10 минут.
{"message": "PrivateChannel wallet verification\nuser: <uuid>\nnonce: <uuid>\nexpires: <unix>","nonce": "<uuid>","expires_at": "<iso8601>"}
POST /auth/verify-wallet
Отправить подписанный challenge для регистрации кошелька как верифицированного. Требуется действительный JWT.
{"pubkey": "<base58 pubkey>","nonce": "<uuid from challenge>","signature": "<base58 Ed25519 signature>"}
Сервис восстанавливает сообщение challenge, проверяет подпись Ed25519 и сохраняет кошелёк. Каждый nonce может быть использован только один раз; повторные запросы отклоняются.
Возвращает { "pubkey": "<base58>", "created_at": "<iso8601>" }.
GET /auth/wallets
Получить список всех верифицированных кошельков аутентифицированного пользователя. Требуется действительный JWT.
DELETE /auth/wallets/{pubkey}
Удалить верифицированный кошелёк из аккаунта аутентифицированного пользователя. Требуется действительный JWT.
GET /health
Проверка работоспособности. Возвращает 200 ok. Аутентификация не требуется.
Структура JWT
Токены используют алгоритм HS256 и истекают через 24 часа после выдачи.
| Claim | Значение |
|---|---|
sub | UUID пользователя |
role | "user" или "operator" |
iss | "private-channel-auth" |
aud | "private-channel-gateway" |
exp | Unix timestamp (24ч с момента выдачи) |
issиaudприсутствуют в payload JWT, но проверяются JWT-конфигурацией шлюза, а не десериализуются в структуру claims приложения. Код на уровне приложения имеет доступ только кsub,roleиexp.
Передайте токен в заголовке Authorization:
Authorization: Bearer <JWT_TOKEN>
Роли
user
Роль по умолчанию при регистрации.
- Доступ ограничен верифицированными кошельками самого пользователя
- Заблокированы:
getBlock,getTransaction,simulateTransaction - Доступно: вызов
Depositв Escrow Program, инициирование вывода средств черезWithdrawFunds
operator
Привилегированная роль. Назначается только вручную; самостоятельного способа повысить роль с user до operator не существует.
Выдайте роль через Admin CLI (private-channel-auth-admin):
private-channel-auth-admin set-role --username alice --role operator
или с помощью прямого SQL-запроса:
Это привилегированная операция с базой данных. Ограничьте доступ к базе данных Auth Service соответствующим образом и ведите аудит всех изменений ролей.
UPDATE private_channel_auth.users SET role = 'operator' WHERE username = 'alice';
Зарегистрировать кошелёк без процедуры самостоятельной верификации (Admin CLI, private-channel-auth-admin):
private-channel-auth-admin attach-wallet --username alice --pubkey <base58-pubkey>
Это вставляет верифицированный кошелёк напрямую в таблицу verified_wallets, минуя процедуру challenge/verify. Применяется ограничение уникальности по (user_id, pubkey). Сама по себе эта команда не выдаёт роль operator — для этого используйте set-role или приведённый выше SQL-запрос. Команда предназначена для привязки кошелька к аккаунту (например, сервисному) без прохождения интерактивной процедуры challenge/verify.
Возможности:
- Обходит все проверки владения кошельком
- Полный доступ ко всем RPC-методам шлюза, включая
getBlock,getTransaction,simulateTransaction - Обязательно для:
ReleaseFunds,ResetSmtRoot
Полный процесс аутентификации
Выполнение аутентифицированных запросов
const response = await fetch("http://localhost:8899/", {method: "POST",headers: {"Content-Type": "application/json",Authorization: `Bearer ${jwtToken}`},body: JSON.stringify({jsonrpc: "2.0",id: 1,method: "getBalance",params: [walletAddress]})});const data = await response.json();
Эндпоинты шлюза
Следующие эндпоинты не требуют аутентификации:
| Эндпоинт | Метод | Описание | Успех | Ошибка |
|---|---|---|---|---|
/health | GET | Проверка работоспособности | 200 {"status":"ok"} | - |
/ready | GET | Глубокая проверка готовности; опрашивает узлы записи и чтения | 200 {"status":"ready"} | 503 {"status":"degraded"} |
Справочник по JWT_SECRET и переменным окружения шлюза см. в справочнике по конфигурации.
Матрица доступа к RPC-методам
Следующие методы распознаются шлюзом. Если JWT_SECRET задан, доступ зависит от роли в JWT:
| Метод | Маршрут | Без JWT | user | operator |
|---|---|---|---|---|
sendTransaction | Узел записи | ✓ | ✓ | ✓ |
getLatestBlockhash | Узел чтения | ✓ | ✓ | ✓ |
getSlot | Узел чтения | ✓ | ✓ | ✓ |
getRecentBlockhash | Узел чтения | ✓ | ✓ | ✓ |
getSignatureStatuses | Узел чтения | ✓ | ✓ | ✓ |
getTransactionCount | Узел чтения | ✓ | ✓ | ✓ |
getFirstAvailableBlock | Узел чтения | ✓ | ✓ | ✓ |
getBlocks | Узел чтения | ✓ | ✓ | ✓ |
getEpochInfo | Узел чтения | ✓ | ✓ | ✓ |
getEpochSchedule | Узел чтения | ✓ | ✓ | ✓ |
getRecentPerformanceSamples | Узел чтения | ✓ | ✓ | ✓ |
getBlockTime | Узел чтения | ✓ | ✓ | ✓ |
getVoteAccounts | Узел чтения | ✓ | ✓ | ✓ |
getSupply | Узел чтения | ✓ | ✓ | ✓ |
getSlotLeaders | Узел чтения | ✓ | ✓ | ✓ |
isBlockhashValid | Узел чтения | ✓ | ✓ | ✓ |
getAccountInfo | Узел чтения | 401 | ownership-gated¹ | ✓ |
getTokenAccountBalance | Узел чтения | 401 | ownership-gated¹ | ✓ |
getSignaturesForAddress | Узел чтения | 401 | ownership-gated¹ | ✓ |
getBlock | Узел чтения | 401 | 403 | ✓ |
getTransaction | Узел чтения | 401 | 403 | ✓ |
simulateTransaction | Узел чтения | 401 | 403 | ✓ |
¹ Ownership-gated: для SPL Token account (поле owner равно TokenkegQ... или TokenzQ..., данные не менее 165 байт) шлюз проверяет, совпадает ли поле owner или delegate с одним из верифицированных кошельков аутентифицированного пользователя. Для любого другого типа аккаунта (кошелёк System Program или неизвестный PDA) вместо этого проверяется, является ли запрашиваемый pubkey одним из верифицированных кошельков пользователя — поскольку у таких аккаунтов нет поля owner/delegate для проверки. Если любая из проверок не проходит, возвращается 403.
Is this page helpful?