Как сделать так, чтобы пользователь вошёл в приложение, получил ровно свои права и никогда не увидел чужие данные.
Понять: регистрация, вход, сессия, JWT.
Спроектировать: роли и конкретные права.
Защитить: backend, RLS, service key.
Слайд 1/9. Карта темы: пользователь, сессия, роли и права.
0
Зачем вообще нужна авторизация
Потому что почти любое полезное приложение хранит что-то личное: профиль, документы, заказы, деньги, историю действий, настройки.
Без авторизацииПриложение не понимает, кто делает запрос. Значит, либо доступ открыт всем, либо вы вынуждены городить опасные костыли.
С авторизациейСистема знает пользователя, может определить его роль, проверить права и вернуть только разрешённые данные.
Не путай два слова. Аутентификация отвечает на вопрос «кто ты?». Авторизация отвечает на вопрос «что тебе можно?».
Пример. Павел вошёл как обычный пользователь. Сервер понимает его ID, но это ещё не значит, что Павел может открыть панель администратора. Для этого нужна отдельная проверка прав.
1
Регистрация, вход и сессия
Три разных этапа, которые новичок часто смешивает в одно слово «авторизация».
Слайд 2/9. Регистрация создаёт аккаунт, вход подтверждает личность и даёт начало сессии.
1
Регистрация Создаём пользователя: email, Telegram ID, OAuth-профиль или другой идентификатор.
2
Подтверждение При необходимости подтверждаем почту, номер или внешний аккаунт.
3
Вход Пользователь доказывает, что он владелец аккаунта.
4
Сессия Приложение получает способ узнавать пользователя в следующих запросах.
Email + парольПросто объяснить. Нужны безопасное хранение паролей, восстановление доступа и защита от перебора.
Magic linkПользователь получает ссылку на почту. Меньше проблем с паролями, но критична безопасность почты.
OAuthВход через Google, GitHub и другие провайдеры. Удобно, но появляется зависимость от внешнего провайдера.
Telegram loginХорошо подходит для mini-app и ботов. Сервер обязан проверять подпись/данные Telegram, а не верить фронту.
Важно. Кнопка «Войти» на фронтенде ничего не защищает сама по себе. Защищает проверка на сервере.
2
Сессии, токены и JWT
После входа серверу нужно узнавать пользователя в каждом следующем запросе.
Слайд 3/9. Access token короткий, refresh token продлевает доступ, сессия объединяет всё в один жизненный цикл.
Access tokenКороткоживущий токен для обычных API-запросов. Если его украдут, окно риска ограничено сроком жизни.
Refresh tokenНужен, чтобы получить новый access token без повторного ввода пароля. Обычно живёт дольше и требует особенно аккуратного хранения.
JWTЧасто используется как подписанный токен. Подпись позволяет серверу проверить, что токен не подменили.
JWT обычно не шифрует содержимое. Не клади внутрь пароли, service key, банковские секреты и другие данные, которые нельзя показывать пользователю.
Что сервер обычно проверяет в JWT
Подпись, срок действия, issuer/audience при необходимости, ID пользователя и иногда дополнительные claims. Роль можно хранить в токене, но для критичных прав сервер всё равно должен доверять своей серверной логике и актуальному источнику данных.
Почему logout бывает не таким простым
Если токен самодостаточный и ещё не истёк, простой logout на фронтенде удалит его только с устройства. Для повышенной безопасности используют короткие access tokens, отзыв refresh token, серверные сессии или deny-list для отдельных сценариев.
3
Роли: удобная группировка прав
Роль не должна быть украшением архитектуры. Она нужна только тогда, когда реально упрощает правила доступа.
Слайд 4/9. Минимальная ролевая модель для MVP: admin, manager, user.
Роль
Что видит
Что делает
Что нельзя
User
Свой профиль, свои заказы, свои документы
Менять разрешённые поля своих объектов
Чужие данные и админские действия
Manager
Рабочие объекты своей зоны ответственности
Обрабатывать заявки, менять статусы, работать с контентом
Системные настройки и критичные права
Admin
Расширенный объём данных
Пользователи, системные настройки, аудит
Даже админские действия желательно логировать и ограничивать
Для MVP лучше три понятные роли, чем двенадцать «на будущее». Чем больше ролей, тем сложнее тестирование, аудит и поддержка.
4
Права доступа: что конкретно разрешено
Роль отвечает «кто ты в системе», право отвечает «какое действие тебе разрешено».
Слайд 5/9. Чтение, изменение и удаление должны проверяться отдельно.
ReadМожет ли пользователь получить объект или список объектов?
WriteМожет ли создавать или изменять? Какие поля?
DeleteКто может удалить? Нужен ли soft-delete, подтверждение или аудит?
Принцип наименьших привилегий: по умолчанию запрещено всё, что явно не разрешено.
Пример. Manager может поменять статус заказа, но не должен менять `user_id`, сумму выплаты или роль владельца. «Право на редактирование» лучше раскладывать на конкретные поля и операции.
5
Проверки на сервере (backend)
Если доступ проверяется только в интерфейсе, это не безопасность. Это просто скрытая кнопка.
Слайд 6/9. Безопасный запрос проходит цепочку валидации, проверки пользователя, роли и владельца.
Определить пользователя Из проверенной сервером сессии или токена.
3
Проверить роль и право Есть ли у этого пользователя право на действие?
4
Проверить владельца Принадлежит ли объект пользователю или его разрешённой зоне?
5
Выполнить действие Только после всех проверок.
Классическая уязвимость. Фронт отправляет `user_id=123`, а сервер верит этому полю. Пользователь меняет 123 на 124 и получает чужие данные. Правильный сервер берёт user ID из проверенной сессии, а не из пользовательского ввода.
# Псевдокод
user = require_authenticated_user(request)
order = db.orders.get(order_id)
if order.user_id != user.id and user.role != "admin":
return 403
return order
6
RLS: второй слой защиты прямо в базе
RLS, Row Level Security, ограничивает доступ не ко всей таблице, а к конкретным строкам.
Слайд 7/9. Разные пользователи получают разные строки из одной таблицы.
Пример. В таблице `orders` хранятся заказы всех клиентов. Обычный пользователь должен видеть только те строки, где `user_id` совпадает с его ID.
-- Включаем RLS
alter table public.orders enable row level security;
-- Пользователь читает только свои строки
create policy "read own orders"
on public.orders
for select
using (user_id = auth.uid());
Backend-проверкаЗащищает бизнес-логику API и позволяет делать сложные правила.
RLS-политикаСтрахует на уровне БД и снижает риск, что ошибка в API откроет чужие строки.
Лучший практический подход: критичный доступ проверяется и в backend, и на уровне базы, если архитектура это позволяет.
7
Supabase и служебный ключ (service key)
Главное правило: ключ с административными полномочиями не должен попадать в браузер, мобильное приложение или публичный репозиторий.
Слайд 8/9. Публичный ключ и service role key имеют принципиально разные уровни доверия.
Publishable / anon keyПредназначен для клиентского использования в рамках правил Supabase. Безопасность данных должна обеспечиваться RLS и Auth.
Служебный ключ с расширенными правами (service role / secret key)Только для доверенного backend. Может обходить RLS или иметь очень широкие полномочия, поэтому утечка критична.
Нельзя: вставлять service key в React/Vue/Next client bundle, HTML, мобильное приложение, публичный GitHub или отправлять его пользователю.
Можно: хранить секрет в env/secret manager на сервере, использовать внутри server-side endpoint, Edge Function или другого доверенного backend-кода.
Что проверить в Supabase перед запуском
RLS включён на пользовательских таблицах, политики реально проверены двумя разными аккаунтами, service key отсутствует в клиентском bundle, публичные таблицы осознанно публичны, admin-функции работают только с доверенного backend.
8
Реальные примеры архитектуры
Самый простой способ понять безопасность: посмотреть, как она работает на конкретных действиях.
Пример 1. Личный кабинет
Пользователь A запрашивает `/orders/55`. Сервер получает его ID из сессии, находит заказ и проверяет `order.user_id == current_user.id`. Если нет, возвращает 403.
Пример 2. Менеджер региона
Manager видит заказы только своего региона. Проверка идёт по роли + `region_id`, а RLS дополнительно фильтрует строки.
Пример 3. Telegram Mini App
Фронт передаёт init data на backend. Backend проверяет подпись Telegram, находит/создаёт профиль, затем выдаёт серверную сессию или токен.
Пример 4. Admin-действие
Админ меняет роль пользователя. Backend проверяет admin permission, логирует кто, когда и кому поменял роль, и не принимает роль «на веру» из фронта.
Полезная привычка. Для каждого endpoint задавай четыре вопроса: кто вызывает, какой объект трогает, имеет ли право, как доказано владение объектом.
9
Частые ошибки новичков
Большинство проблем не требуют «хакера». Достаточно открыть DevTools и поменять запрос.
1. Секреты на фронтендеСлужебные ключи и приватные API-токены попадают в bundle.
2. Нет проверки владельцаAPI проверяет, что пользователь вошёл, но не проверяет, чей объект он запрашивает.
3. Роль берётся из запросаКлиент отправляет `role=admin`, сервер принимает это значение.
4. RLS отключёнЛюбая ошибка API превращается в доступ ко всей таблице.
5. Нет негативных тестовТестируют только «всё работает», но не «чужой пользователь получает отказ».
6. Интерфейс считают защитойСпрятали кнопку, но endpoint остался доступен.
Слайд 9/9. Финальная проверка: права, сервер, RLS, секреты и тесты.
Что должен держать в голове человек, а что должен делать ИИ
Ты отвечаешь заКто кому должен иметь доступ, какие данные чувствительные, где проходит бизнес-граница, какой риск неприемлем.
ИИ должен делатьПредлагать схему, писать политики и код, искать уязвимости, генерировать тесты, объяснять ошибки, но не принимать за тебя бизнес-решение о правах.
10
6 готовых промптов для ИИ
Вставляй описание своего проекта вместо квадратных скобок. Лучше давать ИИ реальную структуру таблиц, endpoints и роли.
Промпт 1/6
Спроектировать пользователей и доступ
Можно выделить текст вручную
Промпт 2/6
Собрать роли и права
Можно выделить текст вручную
Промпт 3/6
Спроектировать авторизацию
Можно выделить текст вручную
Промпт 4/6
Провести аудит безопасности
Можно выделить текст вручную
Промпт 5/6
Внедрить вход Supabase (Auth) + правила доступа RLS
Можно выделить текст вручную
Промпт 6/6
Составить план тестирования
Можно выделить текст вручную
11
Чек-лист из 20 пунктов
Не «я примерно понимаю», а конкретно: проверено или нет.
Прогресс проверки0 / 20
0-9: архитектура пока опасная. Перед production нужно закрыть базовые дыры.
10-16: основа есть, но нужен аудит слабых мест и негативные тесты.
17-20: хороший базовый уровень для MVP, если реальные тесты подтверждают правила доступа.
12
Практическое задание
Сделай на своём реальном проекте. Результат должен быть проверяемым.
Шаг 1. Выпиши всех типов пользователей и оставь минимальный набор ролей.
Шаг 2. Для каждой роли заполни таблицу: читать / создавать / менять / удалять / запрещено.
Шаг 3. Возьми один реальный endpoint и добавь серверную проверку пользователя, роли и владельца.
Шаг 4. Если используешь Supabase, включи RLS на одной пользовательской таблице и напиши политику «видит только своё».
Шаг 5. Создай двух обычных пользователей A и B. Попробуй из аккаунта A получить данные B. Ожидаемый результат: отказ.
Шаг 6. Проверь, что service key и другие секреты отсутствуют во фронтенде, исходном HTML, JS bundle и публичном репозитории.
Готовый критерий завершения: ты можешь показать тест, где пользователь A пытается забрать данные B и получает 401/403 или пустой результат согласно вашей модели доступа.
Финальная мысль
Авторизация - это не экран входа. Это цепочка доверия от пользователя до сервера и базы данных.
Хорошая система доступа отвечает на четыре вопроса без двусмысленности: кто ты, что тебе можно, над какими данными, где это проверяется.
Перед переходом дальше: Даже если технология сейчас не нужна, ты уже получил главное понимание. Зафиксируй «НЕ НУЖНО сейчас» и спокойно переходи к следующему гайду. Кнопка «Дальше» означает следующий учебный урок, а не обязанность внедрить каждую технологию.
🧠 WIKI ЭТОГО ГАЙДА
Непонятные слова простыми словами
Не зубри определения. Вернись сюда, если встретил термин и забыл, что он означает.
АутентификацияПроверка: кто именно вошёл в систему.
АвторизацияПроверка: что этому пользователю разрешено делать.
СессияПериод, когда система помнит, что пользователь уже вошёл.
TokenВременный цифровой пропуск, подтверждающий вход или право доступа.
РольГруппа прав, например пользователь, менеджер или администратор.
PermissionОдно конкретное разрешение, например читать заказ или менять пользователя.
RLSПравила на уровне базы данных, которые ограничивают, какие строки может видеть конкретный пользователь.