Внешний и внутренний API для клиентской платформы
Задача
У платформы два разных клиента: стороннее приложение и интерфейс сайта. Приложению нужны вход по учётной записи, профиль, сотрудники компании, материалы и данные о продуктах. Личному кабинету нужны операции с компанией, правами доступа и заказами. Общая база пользователей и данных не означает одинаковые правила доступа: публичный поиск, чтение своих данных и изменение состава компании требуют разных проверок.
Нужно было дать обоим клиентам стабильный API, сохранив бизнес-ограничения серверной части. По одному лишь факту входа пользователь не должен получать возможность управлять чужой компанией, скачать закрытый материал или подтвердить операцию с произвольным заказом.
Роль и объём
Разработал REST-контур в WordPress: отдельные пространства маршрутов для внешнего клиента и сайта, контроллеры по предметным областям, обработчики операций, схемы параметров и общие функции проверки доступа и формирования ответов. Внешняя часть обслуживает стороннее приложение; внутренняя — интерфейс сайта, личный кабинет и сценарии входа. Контур связан с пользовательскими ролями, данными компаний, хранилищем материалов и сервисами других разделов платформы.
Ограничения
- Не все внешние методы требуют входа: регистрация, восстановление доступа и часть справочной информации должны работать до авторизации. Правила задаются для каждого маршрута и ресурса отдельно.
- Роль «владелец компании» сама по себе недостаточна для изменения её данных: нужно сверять пользователя с владельцем конкретной компании. При удалении сотрудника дополнительно проверяется его принадлежность этой компании.
- Вход для приложения и запросы из браузера используют разные механизмы. Приложение получает токен, а интерфейс сайта передаёт nonce вместе с запросами от текущей сессии WordPress.
- Операции, обращающиеся к другим сервисам платформы, должны различать ожидаемый бизнес-отказ и технический сбой, не раскрывая клиенту внутренние сообщения зависимой системы.
- Повторные и параллельные запросы к чувствительным операциям нельзя трактовать как независимые действия над одним заказом.
Архитектура
Стороннее приложение Сайт / личный кабинет
│ │
▼ ▼
Внешние маршруты REST Внутренние маршруты REST
├── Вход и обновление токена ├── Сессия WordPress + nonce
├── Профиль и сотрудники компании ├── Компания и зоны доступа
├── Материалы и сведения о продуктах ├── Операции с заказами
└── Публичные справочные методы └── Сценарий единого входа
│ │
└───────────┬───────────────┘
▼
Контроллеры и обработчики
├── Схемы и очистка параметров
├── Проверка роли и владельца компании
├── Проверка доступа к ресурсу
├── Лимиты и блокировка для отдельных операций
└── Коды ошибок и диагностика
│
▼
WordPress / данные компаний
├── Пользователи и роли
├── Материалы и история доступа
└── Сервисы других разделов платформы
Разделение на внешние и внутренние маршруты показывает, какой клиент вызывает метод, но само по себе не служит защитой. Доступ определяется проверкой на конкретном маршруте и, где нужно, повторной проверкой бизнес-объекта в обработчике.
Реализация
Для приложения предусмотрены получение и обновление токена. При входе проверяются состояние учётной записи и возможность работы пользователя в приложении; ответ собирает профиль, компанию и доступные зоны. Методы изменения данных компании и управления сотрудниками требуют соответствующей роли. Владелец сверяется с записью компании, а сотрудник перед удалением — с её идентификатором. Это закрывает сценарий, когда корректный пользователь пытается передать идентификатор или адрес чужого сотрудника.
На уровне маршрутов описаны обязательные параметры, типы, допустимые значения и ограничения длины. Обработчики дополнительно очищают и проверяют данные там, где требуется бизнес-контекст. Для материалов действует проверка самого ресурса: открытый файл можно получить без входа, закрытый выдаётся после проверки прав пользователя. Поиск продукта выполняется на сервере через параметризованный SQL-запрос.
Для запросов сайта используется авторизация текущей сессии WordPress; браузер передаёт REST nonce. Внутренние операции также ограничены ролью и типом компании. Например, в сценарии подтверждения выдачи заказа запросы ограничены по частоте, перед обработкой заказа устанавливается кратковременная блокировка через объектный кэш, а сервис учёта повторно проверяет состав заказа и переданный адрес. При постоянном объектном кэше блокировка атомарна; без него она защищает только запросы внутри одного процесса. После успешного действия кэш поиска сбрасывается. Так интерфейс не может считать отправленный из браузера список позиций окончательным источником истины.
Отдельный сценарий единого входа построен на временном state, PKCE и nonce. state связан с короткоживущей записью и cookie с HttpOnly; при обратном вызове эта связка сверяется и однократно расходуется. Адрес возврата ограничен текущим доменом, а для публичных точек входа действует лимит запросов. Сессия WordPress создаётся после проверки ответа провайдера и связи внешней учётной записи с существующим пользователем.
Ошибки и диагностика
API возвращает клиенту признак успеха, код и данные или сообщение об ошибке. В операции выдачи заказа известные бизнес-состояния — уже обработан, несовпадение позиций, занятая операция, превышен лимит — имеют отдельные коды. Неожиданные ошибки зависимого сервиса журналируются на сервере, а клиент получает общее сообщение без внутреннего текста ошибки. Ошибка отправки уведомления также попадает в лог и не меняет результат уже совершённой операции.
Для единого входа предусмотрен отдельный журнал событий. Записи связываются коротким идентификатором потока, полученным из хеша state: по нему можно сопоставить начало входа, отказ и итог без записи самого state. Состав полей ограничен разрешённым списком; коды авторизации, проверочные значения PKCE, токены и секреты в журнал не передаются. Это даёт опору для разбора инцидента входа без публикации учётных данных в диагностике.
Результат
Стороннее приложение и сайт работают с одними бизнес-данными через разные наборы REST-маршрутов. Проверки выполняются на нескольких уровнях: формат запроса, полномочия пользователя, связь с компанией и доступ к конкретному ресурсу. Для отдельных чувствительных операций предусмотрены ограничения частоты, блокировка обработки и явные ошибки; для единого входа — проверяемый сценарий авторизации и диагностика без записи секретов.
Стек
PHP · WordPress REST API · JavaScript · JWT · OAuth 2.0 / OIDC · PKCE · MySQL · Multisite
Есть похожая задача?
Расскажите о текущей системе и нужных изменениях — обсудим следующий шаг.
Следующий кейс: Платёжный шлюз для заказов и счетов B2B-магазина