← Назад к заметкам

Заметки

Код статичного приложения можно посмотреть по URL обработчика

Почему в статичных приложениях Bitrix24 нельзя хранить токены, вебхуки и закрытую бизнес-логику.

Статичное приложение — это HTML и JavaScript, которые загружаются в браузер пользователя. Такой код нельзя считать закрытым, даже если приложение открывается внутри интерфейса Bitrix24.

Суть проблемы

Если приложение сделано как статичное, его исходный HTML и JavaScript попадают в браузер. Пользователь может посмотреть этот код через инструменты разработчика или открыть доступные файлы напрямую по URL.

Коротко

Статичное приложение удобно для простого интерфейса, виджетов и быстрых локальных доработок. Но всё, что лежит в его index.html, script.js и других frontend-файлах, нужно считать видимым.

Типовая ошибка выглядит так:

  • создаётся статичное приложение;
  • в JavaScript добавляется входящий вебхук или постоянный токен;
  • приложение работает в интерфейсе Bitrix24;
  • кто-то открывает DevTools и видит исходный код;
  • секретный URL или токен становится доступен вместе с кодом приложения.

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

Где встречается

Проблема чаще всего появляется в локальных приложениях и виджетах:

  • в статичных локальных приложениях на HTML/JS;
  • в обработчиках, подключённых через placement.bind;
  • в виджетах CRM-карточки;
  • в фоновых виджетах;
  • в приложениях, которые вызывают REST напрямую из браузера;
  • в тестовых приложениях, которые потом остались в работе.

Если обработчик — это обычный публично доступный HTML или JS-файл, его нельзя использовать как место для закрытой логики.

Что нельзя хранить в статике

Всё, что попало в frontend-код, нужно считать доступным для просмотра.

Токены и вебхуки

В статичном приложении нельзя хранить постоянные ключи доступа:

  • входящие вебхуки;
  • OAuth-токены;
  • секреты приложений;
  • пароли от внешних сервисов;
  • ключи API;
  • административные URL для служебных действий.

Даже если код не отображается на странице, он всё равно может быть виден в исходниках, во вкладке Network или в загруженных JavaScript-файлах.

// Так делать нельзя.

const WEBHOOK_URL = 'https://example.bitrix24.ru/rest/1/example_key/crm.deal.list.json';

BX24.callMethod(
    'crm.deal.list',
    {
        select: ['ID', 'TITLE'],
    },
    function (result) {
        console.log(result.data());
    }
);

Внутренняя логика

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

  • правила расчёта закрытых коэффициентов;
  • скрытые условия маршрутизации заявок;
  • списки внутренних исключений;
  • служебные ID пользователей, отделов или клиентов;
  • алгоритмы, которые должны выполняться только на сервере.

Если пользователь не должен видеть правило, оно не должно находиться в статичном JavaScript.

Как делать безопаснее

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

Статика только для интерфейса

В статичном приложении можно оставить:

  • разметку интерфейса;
  • отрисовку таблиц, кнопок и форм;
  • вызовы BX24.callMethod в рамках прав текущего пользователя;
  • валидацию формы для удобства пользователя;
  • код, который не содержит секретов.

Если приложение работает через JS SDK Bitrix24, оно действует в рамках прав пользователя, который открыл приложение. Это удобный вариант для простых интерфейсных задач.

Серверный обработчик для секретов

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

В таком варианте frontend отправляет на сервер только безопасные параметры, а сервер уже сам:

  • проверяет права;
  • использует закрытые токены;
  • обращается к REST или внешнему API;
  • выполняет бизнес-логику;
  • возвращает в приложение только нужный результат.
BX24.callMethod(
    'user.current',
    {},
    function (result) {
        if (result.error()) {
            console.error(result.error());

            return;
        }

        const user = result.data();

        fetch('https://example.com/local/app/ajax.php', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({
                user_id: user.ID,
                action: 'load_data',
            }),
        })
            .then(function (response) {
                return response.json();
            })
            .then(function (data) {
                console.log(data);
            });
    }
);

В этом примере секреты не лежат в JavaScript. Они должны храниться и использоваться только на серверной стороне.

Источники