# Секретный API-ключ в приложении Expo: что защищать

> Публичный ключ Supabase, серверный секрет, переменные Expo: разбираем, что можно класть в iPhone-приложение, и проверяем доступ двумя аккаунтами.

Оригинальная страница: [Секретный API-ключ в приложении Expo: что защищать](https://devoria.fr/ru/blog/sekretnyj-api-klyuch-expo-prilozhenie)
Автор: [Mehdi Azizi](https://devoria.fr/ru/mehdi-azizi)
Опубликовано: 2026-09-29
Последняя правка контента: 2026-10-09


## Переменная окружения не всегда секрет

В приложении Expo переменная с префиксом `EXPO_PUBLIC_` предназначена для кода приложения. Серверного секрета в ней быть не должно. Expo объясняет, что эти значения встраиваются в скомпилированный JavaScript и пользователи приложения могут их прочитать. Так что перенести ключ в файл `.env` недостаточно, чтобы его защитить. [Источник: переменные окружения Expo](https://docs.expo.dev/guides/environment-variables/).

Прежде чем просить ИИ «подключить API», разложи по полочкам, что ты ему доверяешь: адрес сервиса, ключ, который задуман публичным, или ключ, дающий право на привилегированные действия. От этого зависит, где должен выполняться код.

Таблица ниже это схема для проектирования, а не аудит твоего приложения.

| Элемент                                        | Где хранить                                          | Что проверить                                                                                          |
| ---------------------------------------------- | ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| Публичный адрес бэкенда                        | Конфигурация приложения                              | Он указывает на нужное окружение.                                                                      |
| Ключ Supabase publishable или старый ключ anon | В приложении, если права доступа настроены правильно | Правила доступа к данным реально не пускают в аккаунт другого пользователя.                            |
| Ключ Supabase secret или service_role          | Только на сервере                                    | Его нет ни в мобильном бандле, ни в логах, доступных клиенту.                                          |
| Секретный ключ ИИ-провайдера                   | Только на сервере                                    | Приложение обращается к твоему серверу, а тот проверяет пользователя и лимиты до запроса к провайдеру. |

Supabase разделяет ключи для клиентов и секретные ключи для доверенных окружений. Публичный ключ идентифицирует проект, но не заменяет права доступа к данным. [Источник: API-ключи Supabase](https://supabase.com/docs/guides/getting-started/api-keys).

## Пример: вымышленное приложение-дневник чтения

Представим приложение, в котором Лея и Сами записывают свои книги и личные заметки. Этот пример нужен, чтобы подготовить тесты. Он не описывает результаты, полученные на приложении Devoria.

Обычный сценарий выглядит нормально: Лея входит и видит свои заметки. Но главный вопрос пока без ответа: отклонит ли сервер запрос Леи к заметке Сами?

Фильтр в интерфейсе вроде «показывать заметки вошедшего пользователя» улучшает отображение. Но авторизация должна применяться и на уровне данных. В Supabase правила Row Level Security позволяют ограничить доступные строки в зависимости от сессии. Supabase рекомендует включать их для таблиц, открытых через API, и объясняет политики чтения и записи. [Источник: Row Level Security](https://supabase.com/docs/guides/database/postgres/row-level-security).

В своём тестовом проекте привяжи каждую заметку к владельцу и отдельно определи, кто может её читать, создавать, изменять и удалять. Файлы тоже проверь: защищённая строка в базе ещё не доказывает, что картинка приватна.

## Сценарий проверки с двумя тестовыми аккаунтами

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

1. **Прочитать свою заметку.** Аккаунт A находит заметку A.
2. **Прочитать заметку B из аккаунта A.** Запрос не раскрывает её приватное содержимое.
3. **Изменить заметку B из аккаунта A.** Сервер отказывает, заметка B не меняется.
4. **Создать запись от имени B из аккаунта A.** Сервер отклоняет такую привязку.
5. **Прочитать без сессии.** Никакой приватный контент не возвращается.
6. **Открыть приватный файл B из аккаунта A.** Файл недоступен.

Записывай фактический результат, проверенную версию и ошибку, если она была. «Правила включены» это не результат теста. [Чек-лист проверки из раздела ресурсов](https://devoria.fr/ru/resources) можно взять за основу, чтобы сохранять эти доказательства.

## Платные запросы через твой сервер

Для функции, которая делает краткое содержание книги через [ИИ-API](https://devoria.fr/ru/blog/guideline-5-1-2-third-party-ai-att-data-sharing), цепочка может быть такой: приложение → твой сервер → провайдер → твой сервер → приложение. Секретный ключ остаётся на сервере. Но одной этой архитектуры мало: доступ к серверу тоже нужно контролировать.

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

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

## Что можно попросить у ИИ-ассистента для кода

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

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

Читай ответ вместе с соответствующим кодом. Ассистент может заметить несоответствие, но его ответ не заменяет запуск тестов. В гайде [как создать приложение с Claude Code](https://devoria.fr/ru/blog/sozdat-prilozhenie-claude-code-tutorial-iphone) объясняется, как разбить эту работу на части.

## Прежде чем развивать приложение дальше

Ты должен уметь просто объяснить три вещи: какие значения публичны, какие операции идут через сервер и какие тесты показывают, что один аккаунт не видит данные другого. Если хоть что-то из этого неясно, разберись до того, как добавлять новые функции.

Страница [создать приложение для iPhone](https://devoria.fr/ru/expertise/create-iphone-app) показывает место этого этапа во всём проекте. Чтобы двигаться по порядку, в [iOS Kit](https://devoria.fr/ru/kits/ios) есть путь из четырёх этапов и стартовый код, где уже есть аккаунты и ИИ. Если не понимаешь, с какого этапа продолжить, [бесплатная диагностика](https://devoria.fr/ru/diagnostic) расставит твой проект по порядку и пришлёт мой чек-лист против отказов Apple.

## Частые вопросы

### Где хранить секретный API-ключ в приложении Expo?

На своём сервере, никогда не в приложении. Ключ Supabase secret или service_role, как и секретный ключ ИИ-провайдера, должен оставаться только на сервере. Приложение обращается к твоему серверу, а тот проверяет пользователя и лимиты, прежде чем вызвать провайдера. Убедись, что ни одного из этих ключей нет ни в мобильном бандле, ни в логах, доступных клиенту.

### Защищает ли файл .env мой API-ключ в Expo?

Сам по себе нет. Переменная с префиксом `EXPO_PUBLIC_` предназначена для кода приложения, и серверного секрета в ней быть не должно. Expo объясняет, что эти значения встраиваются в скомпилированный JavaScript и пользователи приложения могут их прочитать. Так что перенести ключ в файл `.env` недостаточно, чтобы его защитить.

### Чем публичный API-ключ отличается от секретного?

Публичный ключ задуман для поставки внутри приложения: он идентифицирует проект, но не заменяет права доступа к данным. Секретный ключ даёт право на привилегированные действия и предназначен только для доверенных окружений. В Supabase ключ publishable или старый ключ anon может оставаться в приложении, если права доступа настроены правильно. Ключи secret и service_role остаются на сервере.

### Как вызывать ИИ-API из приложения Expo, не раскрывая ключ?

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

### Как проверить, что каждый пользователь видит только свои данные?

Подготовь два тестовых аккаунта под своим контролем, в каждом по узнаваемой заметке. Из аккаунта A попробуй прочитать, изменить и создать запись от имени аккаунта B, а затем открыть приватный файл B. Сделай и проверки без сессии: каждый запрос должен быть отклонён или ничего не раскрывать. Записывай фактический результат, потому что «правила включены» это не результат теста.

### Как попросить ИИ проверить ключи в моём приложении?

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


## Твой проект

[iOS Kit](https://devoria.fr/ru/kits/ios): Создай приложение для iPhone с Claude Code: стартовый код моих приложений, skills для проверки его работы и наборы Apple Review Kit, App Store Screenshots Kit и ASO Kit. 129,99 €.
