Auth Workflow
PolePosition generated projects include a lightweight auth foundation by
default: token helpers, current-user dependency, and role checks. The optional
polepos add auth command adds a database-backed registration and token
workflow on top of that foundation.
Add Auth
polepos add auth
The command requires generated database wiring. Projects created with
polepos start --db none need an explicit database layer before using this
workflow.
Generated files:
src/<package>/auth/
model.py
password.py
repository.py
router.py
user_schemas.py
user_service.py
tests/integration/test_auth.py
tests/unit/test_auth_service.py
Updated files:
src/<package>/api/router.pysrc/<package>/db/models.pypyproject.toml.poleposition.toml
Added dependency:
pwdlib[argon2]>=0.2.0
Endpoints
The generated router is mounted under /api/v1/auth.
POST /api/v1/auth/register
POST /api/v1/auth/token
GET /api/v1/auth/me
Registration creates an auth_users row and stores a password hash. Token
login returns a JWT compatible with the generated get_current_user
dependency. /me validates the token and returns the authenticated user.
Migration Flow
After adding auth:
uv sync --extra dev
polepos db revision -m "add auth users table"
polepos db upgrade
polepos check
Review the generated migration before applying it to shared environments. Auth introduces a real table, so migration review is part of the workflow.
Generated Model
The generated User model starts intentionally small:
auth_users
id
email
hashed_password
roles
is_active
roles is a comma-separated string so the first scaffold stays simple. In a
real system you may replace it with normalized role tables, permissions,
external identity provider claims, tenant-scoped membership, or policy-based
authorization.
Security Scope
The generated auth workflow is a useful starting point, not a complete identity product. It does not include:
- refresh tokens
- password reset
- email verification
- account lockout
- MFA
- external identity provider integration
- tenant-aware roles or permissions
Add those deliberately based on the product and threat model.
Customization Boundaries
Safe places to customize:
- validation in
user_schemas.py - repository queries in
repository.py - registration and login policy in
user_service.py - response shapes and route names in
router.py - model fields and indexes in
model.py
After changing model fields, create a migration. After changing route or model wiring, run:
polepos check
polepos check validates generated auth files, tests, dependency, router
wiring, model import wiring, and database mode. If auth is intentionally
removed, detach it fully from .poleposition.toml, router wiring,
db/models.py, tests, and pyproject.toml.
Using Protected Routes
Generated projects expose get_current_user and require_roles through
api/deps.py.
from fastapi import APIRouter, Depends
from <package>.api.deps import get_current_user, require_roles
from <package>.auth.schemas import AuthenticatedUser
router = APIRouter()
@router.get("/me")
def read_me(
current_user: AuthenticatedUser = Depends(get_current_user),
) -> AuthenticatedUser:
return current_user
@router.get("/admin")
def read_admin(
current_user: AuthenticatedUser = Depends(require_roles("admin")),
) -> dict[str, str]:
return {"subject": current_user.subject}
Keep auth checks explicit at route boundaries. Avoid hiding authorization in global middleware unless the entire API has the same policy.