Authentication
OAuth 2.0 + MFA implementation for enterprise security.
Stack
| Layer | Technology |
|---|---|
| Backend | FastAPI + SQLAlchemy 2.0 (async) |
| Auth | JWT (python-jose) + bcrypt (passlib) |
| MFA | TOTP (pyotp) + QR codes (qrcode) |
| Frontend | Next.js 14 + React Context |
Architecture
┌──────────────┐ POST /login ┌──────────────┐
│ Frontend │ ─────────────────► │ FastAPI │
│ Next.js 14 │ │ Backend │
└──────────────┘ └──────────────┘
│ │
│ 1. Credentials │ 2. Verify (bcrypt)
│ │
│ 3. JWT Token │ 3. Create JWT
│ ◄─────────────────────────────────│ (sub, role, mfa)
│ │
│ 4. MFA Required? │
│ ├─ No → Done │
│ └─ Yes → Show OTP input │
│ │
│ 5. POST /mfa/challenge │
│ ─────────────────────────────────►│
│ │ 5. Verify TOTP
│ 6. New JWT (mfa=true) │
│ ◄─────────────────────────────────│
Token Structure
{
"sub": "user@example.com",
"role": "analyst",
"mfa": true,
"exp": 1710000000
}API Endpoints
| Method | Endpoint | Purpose |
|---|---|---|
POST | /api/users/login | OAuth2 password grant |
GET | /api/users/me | Get current user |
POST | /api/users/mfa/setup | Generate TOTP secret + QR |
POST | /api/users/mfa/verify | Enable MFA |
POST | /api/users/mfa/challenge | Verify OTP during login |
Key Files
apps/api/
├── app/services/
│ ├── auth_service.py # JWT, password hashing
│ └── mfa_service.py # TOTP, QR generation
├── app/routers/
│ └── users.py # Auth endpoints
└── tests/
└── test_auth.py # 21 unit testsTest Coverage
21 tests • 100% pass rate
├── Password Hashing (6 tests)
├── JWT Tokens (5 tests)
├── MFA Service (5 tests)
└── Login Flows (5 tests)Run tests:
cd apps/api && pytest tests/ -vSecurity Features
- Passwords hashed with bcrypt (unique salts)
- JWT signed with HS256 (24h expiry)
- MFA via RFC 6238 TOTP (Google Authenticator compatible)
- Tokens invalidated on 401 (auto-logout)
- M-25-21 compliance: Analysts save drafts, reviewers commit