Files
auth-project/readme.md
2026-07-12 22:06:20 +03:00

9.8 KiB
Raw Blame History

Auth & Authorization Service

Backend-приложение на FastAPI + SQLAlchemy, реализующее собственную систему аутентификации и авторизации без использования готовых auth-механизмов фреймворка.

Стек

  • FastAPI — веб-фреймворк, роутинг, dependency injection
  • SQLAlchemy (ORM) — доступ к БД, sessionmaker, декларативные модели
  • python-jose (jwt) — создание и валидация JWT-токенов
  • bcrypt / passlib — хеширование паролей
  • Pydantic v2 — схемы валидации запросов/ответов
  • Alembic - Миграции бд

Аутентификация

Аутентификация построена на JWT-токенах (Bearer), без серверных сессий.

  1. Клиент отправляет POST /protected/token с email (как username) и password в формате OAuth2PasswordRequestForm (form-data).
  2. Сервер ищет пользователя по email, сверяет пароль через bcrypt (hash_check(plain, hashed)).
  3. Если пара email/пароль верна — выпускается JWT с payload {"sub": <user.id>}, подписанный секретным ключом (ENV.SECRET_STRING, алгоритм ENV.ALGORITHM).
  4. Клиент передаёт токен в заголовке Authorization: Bearer <token> в каждом последующем запросе.
  5. На защищённых эндпоинтах зависимость get_current_user:
    • декодирует токен (jwt.decode),
    • достаёт sub (id пользователя),
    • загружает пользователя из БД вместе с его правами,
    • при любой ошибке (невалидный/просроченный токен, юзер не найден) — 401 Unauthorized.

logout в чистой JWT-схеме требует либо короткого TTL токена + refresh-токена, либо чёрного списка отозванных токенов (таблица revoked_tokens). Также можно просто затирать токен на фронтенде при разлогине, как самый простой вариант.

Модель авторизации

Вместо классической схемы roles / business_elements / access_roles_rules (с раздельными read/create/update/delete × _all) выбрана более простая flat-модель прав доступа, которая проще для демонстрации, но покрывает те же принципы: пользователь получает набор строковых прав (permissions), и каждый эндпоинт объявляет, какие права требуются для его вызова.

Таблицы БД

users

поле тип описание
id int, PK идентификатор пользователя
name str(64) имя
last_name str(64) фамилия
middle_name str(64) отчество
email str(255) email, unique
status bool активен ли аккаунт (используется вместо is_active для мягкого удаления)
hashed_password str(255) bcrypt-хеш пароля

permissions

поле тип описание
id int, PK идентификатор права
permission str(64) код права: admin, can_view, can_create, can_edit, can_delete

user_permission (association table, many-to-many)

поле тип описание
user_id FK → users.id
permission_id FK → permissions.id

Один пользователь может иметь несколько прав одновременно (например, can_view + can_edit); право admin даёт полный доступ и разрешает выдавать/забирать любые права, включая admin, другим пользователям.

Правила проверки доступа

Каждый метод бизнес-логики (CrudActions) явно объявляет множество допустимых прав и проверяет его перед выполнением действия:

Действие Требуемое право
Просмотр пользователя (по email/id) can_view или admin
Создание пользователя can_create или admin
Изменение пользователя can_edit или admin
Удаление пользователя can_delete или admin

Дополнительно действует правило защиты от эскалации привилегий: пользователь без права admin не может назначить право admin ни себе, ни другому пользователю при создании/редактировании аккаунта.

Обработка ошибок доступа

  • 401 Unauthorized — если запрос не удаётся сопоставить с валидным залогиненным пользователем (нет токена, токен просрочен/невалиден, юзер из токена не существует).
  • 403 Forbidden — пользователь определён, но у него нет нужного права на запрошенное действие/ресурс (в т.ч. попытка эскалации прав, попытка занять чужой email).
  • 404 Not Found — запрошенный ресурс (пользователь, право) не существует.

API

Метод Путь Требуемое право Описание
POST /protected/token Логин, выдача JWT
POST /protected/logout Логин, выдача JWT
GET /protected/get_user_by_email can_view / admin Получить пользователя по email
GET /protected/get_user_by_id can_view / admin Получить пользователя по id
POST /protected/create_user can_create / admin Создать пользователя
PATCH /protected/update_user can_edit / admin Обновить свой профиль или (для admin/can_edit) чужой через target_id
DELETE /protected/delete_user can_delete / admin Удалить (деактивировать) пользователя

Тестовые данные

Для демонстрации системы в БД должны быть заведены минимум: Пароли d@d.d, d1@d.d, d2@d.d 12345678

  • 1 пользователь с правом admin (полный доступ)
  • 1 пользователь с правом can_view (только просмотр)
  • 1 пользователь без прав (для проверки 403)

Структура проекта

src/
  db/                # ActionsDB — доступ к БД (SQLAlchemy sessions, запросы)
  model/
    database_model/  # SQLAlchemy-модели (User, Permissions)
    user/             # Pydantic-схемы (UserOut, UserCreate, UserUpdate, PermissionIn/Out)
    env_read/         # Чтение env через pydantic settings
  service/
    crud_actions/     # CrudActions — бизнес-логика + проверки прав доступа
    JWT/               # JWT (кодирование/декодирование токена), Hash (bcrypt)
    auth/              # Создание и проверка jwt токена
  errors/              # централизованные HTTP-ошибки (401/403/404)
  web/                 # роутеры FastAPI (эндпоинты)
  migrations/          # миграции бд
  tests/               # тесты (Пусто, не создавались)

Запуск

poetry
make run

Переименовать env