- Introduced a new section for the Jinkendo Foundation, detailing design principles for the product family. - Updated README files to include references to the new design principles documentation. - Enhanced the overall documentation structure to improve navigation and accessibility of design resources. - Ensured consistency across documentation related to the Jinkendo Foundation and its principles.
13 KiB
Auth & Session – Designprinzipien (Extraktion)
Status: Analyse / Arbeitspapier
Stand: 2026-07-04
Geltungsbereich: Authentifizierung, Session-Management, rollenbasierte API-Zugriffe — kein Mandanten-/SSO-System, keine Zahlungs-Auth
Serie: Designprinzipien für Produktfamilie · Dokument 5 von n
Vorgänger: REGISTRY_PLUGIN_DESIGN_PRINCIPLES.md
Kernkomponenten:
| Bereich | Pfade |
|---|---|
| Auth-Kern | backend/auth.py |
| Auth-Endpoints | backend/routers/auth.py |
| Profile | backend/routers/profiles.py |
| Frontend | frontend/src/context/AuthContext.jsx, ProfileContext.jsx, utils/api.js |
| DB | profiles, sessions |
| Architektur-Regeln | .claude/rules/ARCHITECTURE.md, CLAUDE.md § Auth |
| Vision (nicht implementiert) | CENTRAL_SUBSCRIPTION_SYSTEM.md (SSO/JWT) |
Modul
Auth & Session
Server-seitige, token-basierte Authentifizierung mit FastAPI-Dependencies — Identität und Rolle, getrennt von Feature-Entitlements und fachlicher Logik.
Fachliche Verantwortung
Das Modul übernimmt:
- Identität — Wer ist eingeloggt? (
profiles+ Passwort/bcrypt) - Session — Opaque Token in
sessions, Ablaufzeit, Logout - API-Gate —
require_auth,require_admin,require_auth_flexible - Passwort-Lifecycle — Hash, Verify, Reset, Registrierung, E-Mail-Verifizierung
- Rollen —
profiles.role:user|admin(grobbinsenartig)
Es übernimmt nicht:
- Feature-Limits / Tier (→ Feature & Entitlement System, gleiche
auth.py-Datei aber logisch getrennt) - Mandanten-Isolation / Org-Workspaces
- OAuth/SSO/JWT (nur Vision)
- Authorization auf Datensatzebene (Row-Level Security)
Was Mitai ist vs. nicht ist
| Mitai | Produktfamilien-Muster |
|---|---|
| 1 Login = 1 Profil (E-Mail) | ✅ Account-Modell |
| Historisch Multi-Profil auf einer Instanz | ⚠️ Legacy (/profiles, X-Profile-Id) |
| Self-hosted Einzelinstanz | ✅ Kein Multi-Tenant-SaaS |
| Session-Token in DB | ✅ Server-side Session Store |
| Zentrale Jinkendo-Auth (Vision) | ❌ nicht gebaut |
Administrierte vs. code-definierte Konfiguration
| Konfiguration | Speicherort | Administrierbar? |
|---|---|---|
| Nutzer-Stammdaten, Rolle | profiles |
Admin (User-Verwaltung) / Self-Service |
| Session-Laufzeit | profiles.session_days (Default 30) |
Profil/Admin |
| Passwort-Hash | profiles.pin_hash |
Nutzer (change pin) |
| E-Mail-Verifizierung | email_verified, Token-Felder |
System |
| Trial-Ende | trial_ends_at |
System bei Registrierung |
| SMTP | Env (SMTP_*, APP_URL) |
Deploy |
| Rate Limits Login/Register | Code (5/min, 3/hour) |
Code |
Hardcodiert: bcrypt, Token-Länge (secrets.token_urlsafe(32)), Rollen-Enum (user/admin), Header-Name X-Auth-Token.
Session- und Auth-Flow
Login (email + password)
→ verify_pin (bcrypt | legacy SHA256)
→ optional bcrypt upgrade
→ INSERT sessions (token, profile_id, expires_at)
→ Client: localStorage bodytrack_token
Request
→ Header X-Auth-Token (api.js / AuthContext)
→ get_session(token) JOIN profiles
→ require_auth → session dict (profile_id, role, …)
Logout
→ DELETE sessions WHERE token=…
→ Client: localStorage clear
Sonderfall: require_auth_flexible — Token via Header oder Query ssetoken (SSE, <img>, Downloads).
Rollen
| Rolle | Mechanismus | Typische Rechte |
|---|---|---|
| user | profiles.role = 'user' |
Eigene Daten, Features nach Tier |
| admin | require_admin |
Admin-Shell, Prompts, User, System |
Kein feingranulares RBAC (keine Permission-Matrix). Admin ist Binär-Schalter.
Designprinzipien
1. FastAPI-Dependencies als Auth-Gate
| Prinzip | Jeder geschützte Endpoint nutzt session: dict = Depends(require_auth) als separaten Parameter — nie in Header() eingebettet. |
| Begründung | Verhindert ungeschützte Endpoints durch falsche Parameter-Signatur. |
| Quelle | CLAUDE.md § Kritische Regeln; auth.py |
| Tragfähigkeit | hoch |
| Einschränkung | Nicht linter-erzwungen; Legacy-Endpoints existieren. |
2. Server-side opaque Sessions
| Prinzip | Token ist zufällig, in DB gespeichert; Validierung über sessions + Ablauf — kein JWT mit Client-Claims. |
| Begründung | Revocation (Logout), kein Trust in Client-Payload; einfaches Modell für Self-Hosted. |
| Quelle | sessions Tabelle; make_token(), get_session() |
| Tragfähigkeit | hoch (Single-App, Self-Hosted) |
| Einschränkung | Skalierung multi-node braucht shared session store; SSO-Familie braucht anderes Modell. |
3. profile_id aus Session, nicht aus Client
| Prinzip | Autoritative Identität für neue Endpoints: session['profile_id'] — Client darf Profil nicht wählen. |
| Begründung | Verhindert IDOR (Zugriff auf fremde Profile). |
| Quelle | routers/goals.py, routers/prompts.py; Architektur-Intent in CLAUDE.md |
| Tragfähigkeit | hoch |
| Einschränkung | Legacy get_pid(x_profile_id) akzeptiert X-Profile-Id ohne Session-Abgleich — siehe Nicht übernehmen. |
4. bcrypt mit Legacy-Migration
| Prinzip | Passwörter mit bcrypt; SHA256-Legacy beim Login erkannt und transparent auf bcrypt upgraded. |
| Begründung | Kein Big-Bang-Migration; sichere Hashes ohne Nutzer-Zwangs-Reset. |
| Quelle | verify_pin(), Login in routers/auth.py |
| Tragfähigkeit | hoch |
| Einschränkung | Upgrade nur bei erfolgreichem Login. |
5. Rate Limiting auf Auth-Endpoints
| Prinzip | Login, Register, Forgot-Password, Resend-Verification mit slowapi-Limits (IP-basiert). |
| Begründung | Brute-Force- und Abuse-Schutz. |
| Quelle | routers/auth.py (5/minute, 3/hour); main.py Limiter |
| Tragfähigkeit | hoch |
| Einschränkung | IP-only; kein account-based lockout. |
6. Keine E-Mail-Enumeration bei sensiblen Flows
| Prinzip | Forgot-Password und Resend-Verification liefern generische Erfolgsmeldung, auch wenn E-Mail unbekannt. |
| Begründung | Privacy; erschwert Account-Scraping. |
| Quelle | password_reset_request, resend_verification |
| Tragfähigkeit | hoch |
| Einschränkung | Register sagt „E-Mail bereits registriert“ (Enumeration möglich). |
7. E-Mail-Verifizierung vor voller Nutzung
| Prinzip | Self-Register setzt email_verified=FALSE; Verify-Endpoint aktiviert + Auto-Login-Session. |
| Begründung | Valide Kontaktadresse; Spam-Reduktion. |
| Quelle | register, verify_email in routers/auth.py |
| Tragfähigkeit | hoch |
| Einschränkung | Nicht überall im Backend erzwungen (Login ohne verified check?). |
8. Flexible Auth für technische Clients
| Prinzip | require_auth_flexible: gleiche Session-Validierung via Header oder ?ssetoken= für SSE/Bilder. |
| Begründung | Browser-APIs ohne Custom Headers. |
| Quelle | auth.py; Prompt SSE /execute-stream |
| Tragfähigkeit | mittel–hoch |
| Einschränkung | Token in URL kann in Logs/Referrer leaken — kurze Sessions / HTTPS Pflicht. |
9. Zentraler API-Client mit Token-Injektion
| Prinzip | Frontend: api.js injiziert X-Auth-Token automatisch — kein scattered fetch ohne Auth. |
| Begründung | Konsistenz; eine Stelle für Token-Handling. |
| Quelle | utils/api.js → hdrs(); getToken() aus AuthContext |
| Tragfähigkeit | hoch |
| Einschränkung | Einzelne Komponenten umgehen noch api.js (SettingsPage, EmailSettings). |
10. Auth getrennt von Authorization (Features)
| Prinzip | require_auth = identifiziert; check_feature_access = berechtigt für Aktion — nacheinander im Router. |
| Begründung | Klare Schichten; Auth-Modul nicht mit Tier-Logik vermischen (auch wenn Datei auth.py beides enthält). |
| Quelle | FEATURE_ENTITLEMENT_DESIGN_PRINCIPLES.md; Router-Muster |
| Tragfähigkeit | hoch |
| Einschränkung | Legacy Profil-Flags ai_enabled, export_enabled parallel zum Feature-System. |
11. Admin-Gate im Frontend und Backend
| Prinzip | Backend: require_admin; Frontend: RequireAdmin + isAdmin aus Session-Rolle. |
| Begründung | UX-Navigation + API-Sicherheit (Frontend allein reicht nicht). |
| Quelle | RequireAdmin.jsx; require_admin() |
| Tragfähigkeit | hoch |
| Einschränkung | Einzelne Routen (Workflow-Editor) ohne Frontend-Admin-Gate. |
12. Session-Kontext im Frontend
| Prinzip | AuthProvider hält { token, profile_id, role, profile }; App setzt setProfileId(session.profile_id) für API. |
| Begründung | Single React-Tree für Login-State; Re-Validate via /auth/me beim Start. |
| Quelle | AuthContext.jsx; App.jsx |
| Tragfähigkeit | hoch |
| Einschränkung | ProfileContext lädt alle Profile — Multi-Profil-UX Rest; Session-Profil ist Kanon. |
Nicht übernehmen
-
get_pid(X-Profile-Id)ohne Session-Bindung — Client kann fremdeprofile_idsenden; IDOR-Risiko. Kanon: immersession['profile_id']oder explizite Admin-Impersonation mit Audit. -
Profile-CRUD nur mit
require_auth—/profileslistet alle Nutzer für jeden Authentifizierten (Kommentar „admin“, keinrequire_admin). Für Familien-Architektur: strikte Admin-Gates. -
Dual-System Profil-Flags vs. Features —
ai_enabled,export_enabled,ai_limit_dayin Session-Query neben v9c Feature-Registry. -
localStorage-Key-Inkonsistenz —
bodytrack_tokenvs.mitai-jinkendo_active_profile(historischer App-Name). -
Direktes
fetchohneapi.js— umgeht Token-/Error-Konvention. -
Reset-Token in
sessions-Tabelle —reset_{token}mischt Session-Typen in einer Tabelle; OK für MVP, für Familie: getrennte Token-Typen/Tabellen. -
Kein JWT/SSO trotz Produktfamilien-Vision —
CENTRAL_SUBSCRIPTION_SYSTEM.mdbeschreibtauth.jinkendo.de— Mitai-Implementierung ist nicht das Zielbild für Cross-App-SSO. -
Multi-Profil-Haushalt ohne klares Modell — Legacy Multi-Profile auf einer Instanz vs. 1 Account = 1 Profil; für neue Apps Modell explizit wählen.
-
Role als einziges RBAC — reicht für Admin/User, nicht für feingranulare Permissions.
-
Session-Query mit veralteten Profil-Spalten —
get_sessionSELECT enthält Legacy-Felder statt nur Identität + Rolle. -
Fehlende erzwungene E-Mail-Verified-Prüfung — Registrierung setzt Flag, Login prüft es nicht offensichtlich.
-
Debug-Print in Auth-Modul —
print("[AUTH.PY] Module loaded…")in Produktionscode.
Abgrenzung zu anderen Serien-Dokumenten
| Thema | Dokument |
|---|---|
| Tier, Limits, Quotas | FEATURE_ENTITLEMENT_DESIGN_PRINCIPLES.md |
| Zentrale SSO/Abo-Vision | CENTRAL_SUBSCRIPTION_SYSTEM.md |
| API-First / Router | ARCHITECTURE.md §1 |
Modul-Inventar (Ist-Stand)
backend/
├── auth.py # Session, require_*, Feature-Access (v9c)
└── routers/
├── auth.py # login, logout, register, verify, reset
└── profiles.py # CRUD, get_pid (Legacy)
frontend/src/
├── context/AuthContext.jsx
├── context/ProfileContext.jsx
├── layouts/RequireAdmin.jsx
└── utils/api.js # Token-Injektion
DB:
├── profiles # Identität, Rolle, Hash, Tier, Trial
└── sessions # token → profile_id, expires_at
Endpoints (Auswahl):
| Endpoint | Auth |
|---|---|
POST /api/auth/login |
Public + Rate limit |
POST /api/auth/logout |
Token optional |
GET /api/auth/me |
require_auth |
POST /api/auth/register |
Public + Rate limit |
GET /api/auth/verify/{token} |
Public |
Verwandte Dokumentation
- Feature-Entitlements: FEATURE_ENTITLEMENT_DESIGN_PRINCIPLES.md
- Architektur-Regeln Auth:
CLAUDE.md,.claude/rules/ARCHITECTURE.md - GUI Admin-Guard:
docs/issues/GUI_IA_ADMIN_NAV_2026-04-05.md - SSO-Vision: CENTRAL_SUBSCRIPTION_SYSTEM.md
Geplante Folgedokumente (Serie)
| # | Modul | Status |
|---|---|---|
| 1 | Prompt Engine | ✅ |
| 2 | Data Layer | ✅ |
| 3 | Feature & Entitlement | ✅ |
| 4 | Registry-/Plugin-Muster | ✅ |
| 5 | Auth & Session | ✅ dieses Dokument |
| 6 | Universal Import | ✅ UNIVERSAL_IMPORT_DESIGN_PRINCIPLES.md |
| 7 | Dashboard Widgets | ✅ |
| 8 | Navigation / IA | ✅ NAVIGATION_IA_DESIGN_PRINCIPLES.md |
| 9 | Migration & Deploy | ✅ |