PRXCloud.
PrxID / Проекты / Техническая часть

Вход, который
понимает ваш проект.

Подключите вход через PrxID: сформируйте ссылку авторизации, настройте callback, обменяйте код на сервере и создайте сессию вашего сайта.

Поток входа

  1. Ваш backendСоздаёт случайный state, сохраняет его в серверном хранилище и связывает с cookie браузера.
  2. Браузер → PrxIDПользователь входит на стороне PrxID и подтверждает доступ приложению.
  3. PrxID → callbackБраузер возвращается на зарегистрированный URL с code и state.
  4. Ваш backend → /api/oauth/tokenПосле проверки state backend обменивает code, используя секретный ключ.
  5. Ваш сайтНаходит пользователя по usr_…, создаёт собственную сессию и открывает кабинет.

Это партнёрский протокол, а не полный OAuth/OIDC: endpoint с названием token сразу возвращает пользовательские данные. Не ожидайте access_token, refresh_token, ID token или отдельный userinfo.

Запрос авторизации

Публичная точка входа — GET /auth на базовом адресе из prxid_url. Формируйте ссылку стандартным URL-кодировщиком.

const url = new URL('/auth', prxidUrl);
url.search = new URLSearchParams({
  idpart_link: partnerId,
  redirect_uri: registeredCallback,
  state: serverGeneratedState,
  theme: 'white',
  scope: 'profile',
}).toString();
// API key в эту ссылку не добавляется.
redirectToProvider(url.href);
ПараметрСмысл
idpart_linkПубличный ID данного входа из карточки Cloud
redirect_uriТочное зарегистрированное значение callback
stateСлучайное одноразовое значение для защиты возврата
themewhite, glass, neon или plata
scopeprofile; email и phone — только при необходимости и согласии

PrxID добавляет profile автоматически. Контакты возвращаются только при запросе соответствующего scope и явном согласии. Минимальной интеграции достаточно profile; Cloud сейчас не сохраняет контакты.

Callback и state

GET /auth/prxid/callback?code=prx_code_…&state=…

Создайте state через криптографический генератор, например randomBytes(32). Сохраните его хеш, срок действия и привязку к случайной cookie браузера на сервере. Используйте короткий срок: в примере — десять минут.

  1. Проверьте метод запроса, наличие ровно одного code и одного state, формат и срок действия.
  2. Найдите попытку по защищённой cookie этого браузера. State сам по себе не заменяет такую привязку.
  3. Атомарно удалите попытку и сравните хеши constant-time сравнением.
  4. При любой ошибке завершите попытку. Не создавайте сессию и не обменивайте код.
  5. После успеха выполните серверный обмен и уберите code из адресной строки перенаправлением в кабинет.

PrxID выдаёт code на пять минут. Один code можно использовать только один раз. Повторный callback, истёкшая попытка и возврат в другом браузере должны завершаться отказом. Не сохраняйте полный code или ключ в логах и аналитике.

Обмен кода

Запрос идёт с backend на HTTPS-адрес из prxid_url. Не выполняйте обмен в браузере и не отключайте проверку TLS.

// Только backend. После проверки и удаления state.
const response = await fetch(new URL('/api/oauth/token', prxidUrl), {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  redirect: 'error',
  signal: AbortSignal.timeout(10000),
  body: JSON.stringify({
    api_key: serverOnlyApiKey,
    code: codeFromCallback,
    redirect_uri: registeredCallback,
  }),
});
if (!response.ok) throw new Error('PrxID не подтвердил вход');
const data = await response.json();
if (data.success !== true || typeof data.user?.id !== 'string') {
  throw new Error('Некорректный ответ PrxID');
}
// Найдите или создайте локального пользователя по data.user.id.
// Только теперь создайте защищённую серверную сессию своего сайта.

Минимальный успешный ответ:

{
  "success": true,
  "user": {
    "id": "usr_ABCDEFGHIJKLMNOPQRSTUVWXYZ",
    "Ferif": "01",
    "email_verified": true,
    "number_verified": false
  }
}

Ferif и флаги подтверждения не содержат сами контакты. Email и phone появляются отдельно при разрешённых scopes. Имя и фамилия в текущем протоколе не передаются. Не считайте эти поля обязательными.

Локальная сессия вашего сайта

Используйте user.id как уникальный внешний ключ пользователя в пределах проекта. Повторный вход должен находить ту же запись. Создавайте новый случайный токен сессии после подтверждённого обмена; храните на сервере его хеш, пользователя и срок действия.

Cookie должна иметь HttpOnly, SameSite=Lax и Secure при HTTPS. Проверяйте сессию и права на каждом приватном API-запросе, а не только в интерфейсе. Выход удаляет серверную запись и cookie. Для действий, изменяющих данные, нужна защита от CSRF, например точная проверка Origin.

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

Готовый пример для вашего сайта

Пример использует Node.js 24+ и встроенный SQLite. Скачайте два файла в одну папку; внешние npm-зависимости не нужны. Модуль реализует state, одноразовый callback, серверный обмен, локальную базу пользователей, session API и выход.

node server.mjs

При первом запуске создаются time/prxid.json и time/users.db. В JSON заполните prxid_url из карточки входа, выданные idpart_link и api_key и точный redirect_uri. Пример слушает localhost:3000; для локального теста создайте вход с callback http://localhost:3000/auth/prxid/callback. Для туннеля зарегистрируйте его полный HTTPS callback и открывайте сайт через этот туннель.

{
  "prxid_url": "БАЗОВЫЙ_АДРЕС_ИЗ_CLOUD",
  "idpart_link": "ВЫДАННЫЙ_ID",
  "api_key": "СЕКРЕТНЫЙ_ТОКЕН",
  "redirect_uri": "http://localhost:3000/auth/prxid/callback",
  "theme": "white",
  "token_server_ip": ""
}

Если у вас уже есть интерфейс, кнопка входа обращается к вашему backend:

// Кнопка «Войти» на вашем сайте. Ключ остаётся на backend.
const response = await fetch('/api/auth/prxid/start', { method: 'POST' });
const data = await response.json();
if (!response.ok) throw new Error(data.message);
window.location.assign(data.url);

В существующем backend можно использовать createAuth и вызывать auth.handle(req, res) до обработки остальных маршрутов. Обязательно согласуйте пути и хранение сессий со своим приложением; не подключайте второй независимый механизм сессий незаметно для остального кода. Для другой технологии повторите протокол, а не переносите секрет в клиент.

Добавьте /time/ в .gitignore и обеспечьте сохранность базы при обновлении. Пример запускайте за HTTPS reverse proxy в production. Демо HTML служит стартовой точкой; внешний вид заменяется вашим интерфейсом.

Ошибки и проверка

HTTPЧто проверить
400Code, срок, повторное использование и точный callback
401Правильность и активность API-ключа
403Принадлежность ключа, кода и callback одной компании
429Лимит попыток; подождать перед новой попыткой
503 / сетьДоступность PrxID, DNS, HTTPS и баз данных

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

  1. Проверьте полный вход в обычном браузере и повторный вход того же пользователя.
  2. Проверьте неверный state, истёкшую попытку, повтор callback и другой браузер.
  3. Убедитесь, что секрет отсутствует в HTML, клиентских бандлах, URL и логах.
  4. Для двух входов одного проекта сравните user.id одного аккаунта — значения должны совпасть.
  5. Для входа другого проекта повторите тест — значение должно отличаться.
  6. Проверьте выход и отказ в доступе к защищённым маршрутам без действующей сессии вашего сайта.
Используйте user.id из успешного ответа как идентификатор пользователя вашего проекта. Для подключения достаточно выданных idpart_link, api_key, prxid_url и точного callback.
Назад к проектам