Минимальный backend на FastAPI с собственной логикой аутентификации (JWT) и авторизации через роли/разрешения. Никаких встроенных auth подсистем фреймворка не используется.
- Python 3.11+
- FastAPI + Uvicorn (только HTTP-обвязка)
- SQLAlchemy 2.0 (ORM + модель БД)
- PyJWT + bcrypt (хеширование и выпуск токенов)
- SQLite по умолчанию, Postgres по
DATABASE_URL - uv для управления зависимостями (замена requirements.txt)
BCRYPT_MAX_PASSWORD_LENGTH=0— отключает ограничение bcrypt 72 байта (нужно из-за проверки passlib на старте)- bcrypt pinned 3.2.x (passlib 1.7.4 не дружит с 4.x)
- Установить uv, если нет:
curl -LsSf https://astral.sh/uv/install.sh | sh(добавьте~/.local/binв PATH). - Установить зависимости:
uv sync. - Запуск:
BCRYPT_MAX_PASSWORD_LENGTH=0 uv run uvicorn app.main:app --reload(порт 8000).
Переменные окружения:
DATABASE_URL— напримерpostgresql+psycopg2://user:pass@localhost:5432/auth(по умолчаниюsqlite:///./auth.db).JWT_SECRET_KEY— ключ для подписи токенов.ACCESS_TOKEN_EXPIRE_MINUTES— время жизни access token.
docker compose up --build
# приложение на http://localhost:8000, Postgres внутри сети dockerDockerfile использует uv внутри контейнера, psycopg2 собирается через libpq-dev. Env BCRYPT_MAX_PASSWORD_LENGTH=0 выставлен в контейнере.
На старте создаются таблицы и сиды:
- Пользователь:
admin@example.com/Admin1234 - Роли:
admin,viewer,editor - Разрешения:
(iam, manage),(objects, read),(objects, write)
- users — учетные записи (имя/фамилия/отчество, email, hash пароля, статус
active|deleted). - roles — именованные роли (например
admin,editor). - permissions — атомарные права:
resource+action+description(уникальны в паре resource/action). - user_roles — связь многие-ко-многим пользователей и ролей.
- role_permissions — связь ролей и разрешений.
- revoked_tokens — jti отозванных токенов (используется при logout).
- audit_logs — журнал решений ACL (кто, что запросил, разрешено/запрещено).
Каждый защищенный endpoint описывает пару resource, action и использует зависимость require_permission(resource, action).
Алгоритм:
- Токен из
Authorization: Bearer ...декодируется, валидируется, проверяется вrevoked_tokens. - Пользователь загружается и проверяется статус
active. - Запрос к
permissions → roles → usersпроверяет наличие разрешения. - В
audit_logsфиксируется запись и при отсутствии права возвращается403 Forbidden. Если токен отсутствует/невалиден —401 Unauthorized.
POST /auth/register— регистрация (тело: имя/фамилия/отчество?, email, пароль, повтор пароля). Возвращает пользователя.POST /auth/login— email + пароль → JWT (access_token,expires_in).POST /auth/logout— аннулирует текущий access token (добавляет jti вrevoked_tokens).GET /auth/me— профиль текущего пользователя.PATCH /auth/me— обновление ФИО/пароля (с повтором для подтверждения).DELETE /auth/me— мягкое удаление (status=deleted, повторный логин невозможен).
GET /admin/permissions— список прав.POST /admin/permissions— создание права.GET /admin/roles— список ролей с правами.POST /admin/roles— создание роли с перечнемpermission_ids.POST /admin/users/{user_id}/roles/{role_id}— назначить роль пользователю.
GET /objects/— список объектов (требует(objects, read)).GET /objects/{id}— детальный просмотр (требует(objects, read)).PUT /objects/{id}— обновление (требует(objects, write)).
- Логин админа
admin@example.com / Admin1234→ сохранитьaccess_token. - Создать нового пользователя через
/auth/register. - Назначить ему роль
viewerчерез/admin/users/{user_id}/roles/{role_id}. - С новым токеном пользователя вызвать
GET /objects/→ 200 OK. - Попробовать
PUT /objects/1→ 403 Forbidden. - Обновить роль на
editor→PUT /objects/1теперь 200 OK.
- Пароли хешируются вручную через
passlib, без фреймворк-менеджеров. - JWT генерируются/проверяются самостоятельно через PyJWT (нет OAuth2PasswordBearer и т.п.).
- Проверка доступа реализована отдельной зависимостью
require_permission, а не стандартными permissions фреймворка. - Бизнес-логика вынесена в сервисы (
app/services.py), доступ к БД через репозитории и Unit of Work (app/repositories.py,app/unit_of_work.py) — эндпоинты остаются тонкими.
- Вынести refresh токены и многофакторную аутентификацию.
- Добавить миграции Alembic и CI для линтеров/тестов.
- Поддержка политики на уровне записей (ABAC), кэширование прав, rate limiting.