Files
stechuhr3/AUTH.md
Torsten Schulz (local) e95bb4cb76 Initial commit: TimeClock v3 - Node.js/Vue.js Zeiterfassung
Features:
- Backend: Node.js/Express mit MySQL/MariaDB
- Frontend: Vue.js 3 mit Composition API
- UTC-Zeithandling für korrekte Zeiterfassung
- Timewish-basierte Überstundenberechnung
- Wochenübersicht mit Urlaubs-/Krankheits-/Feiertagshandling
- Bereinigtes Arbeitsende (Generell/Woche)
- Überstunden-Offset für historische Daten
- Fixed Layout mit scrollbarem Content
- Kompakte UI mit grünem Theme
2025-10-17 14:11:28 +02:00

409 lines
9.8 KiB
Markdown

# Authentication & Session-Management
## Übersicht
TimeClock v3 verfügt über ein vollständiges JWT-basiertes Authentifizierungssystem mit persistenter Session-Verwaltung.
## Features
**Benutzer-Registrierung** - Neuen Account erstellen
**Login/Logout** - Sicheres Ein- und Ausloggen
**Passwort-Reset** - Passwort vergessen Funktionalität
**Persistente Sessions** - Session bleibt nach Reload erhalten
**JWT-Tokens** - Sichere Token-basierte Authentifizierung
**Router Guards** - Automatischer Schutz geschützter Routen
**Auto-Logout** - Bei ungültigen/abgelaufenen Tokens
## Backend-Architektur
### 1. Auth-Service (`AuthService.js`)
Hauptfunktionen:
```javascript
authService.register(userData) // Registrierung
authService.login(email, password) // Login
authService.logout(token) // Logout
authService.validateToken(token) // Token validieren
authService.requestPasswordReset(email) // Reset anfordern
authService.resetPassword(token, pw) // Passwort zurücksetzen
authService.changePassword(userId, ...) // Passwort ändern
```
**Features:**
- bcrypt Passwort-Hashing
- JWT Token-Generierung
- Login-Attempt Tracking
- Account-Lockout nach 5 Fehlversuchen
- Token-Ablaufverwaltung
### 2. Auth-Controller (`AuthController.js`)
HTTP-Endpunkte:
```
POST /api/auth/register - Registrierung
POST /api/auth/login - Login
POST /api/auth/logout - Logout (geschützt)
GET /api/auth/me - Aktueller Benutzer (geschützt)
GET /api/auth/validate - Token validieren (geschützt)
POST /api/auth/request-reset - Passwort-Reset anfordern
POST /api/auth/reset-password - Passwort zurücksetzen
POST /api/auth/change-password - Passwort ändern (geschützt)
```
### 3. Auth-Middleware (`middleware/auth.js`)
```javascript
// Geschützte Route
app.use('/api/time-entries', authenticateToken, router)
// Optionale Auth
app.use('/api/stats', optionalAuth, router)
```
**Funktionsweise:**
1. Token aus `Authorization: Bearer <token>` Header extrahieren
2. Token validieren (JWT + Datenbank)
3. Bei Erfolg: `req.user` mit Benutzer-Info setzen
4. Bei Fehler: 401 Unauthorized
### 4. Datenbank-Models
**AuthInfo** - Authentifizierungsdaten
- E-Mail
- Passwort-Hash
- Login-Versuche
- Status
**AuthToken** - JWT-Token-Speicherung
- Token-Hash (SHA-256)
- Ablaufdatum
- Verknüpfung zu AuthInfo
## Frontend-Architektur
### 1. Auth-Store (`stores/authStore.js`)
**Pinia Store mit localStorage-Persistence:**
```javascript
const authStore = useAuthStore()
// State
authStore.user // Aktueller Benutzer
authStore.token // JWT Token
authStore.isAuthenticated // Login-Status
authStore.isLoading // Loading-State
// Actions
await authStore.register(userData)
await authStore.login(credentials)
await authStore.logout()
await authStore.fetchCurrentUser() // Session wiederherstellen
await authStore.validateToken()
await authStore.requestPasswordReset(email)
await authStore.resetPassword(token, password)
await authStore.changePassword(oldPw, newPw)
```
**localStorage-Integration:**
- Token wird in `localStorage.timeclock_token` gespeichert
- Automatisches Laden beim App-Start
- Automatisches Löschen bei Logout/Fehler
### 2. Auth-Views
**Login (`views/Login.vue`)**
- E-Mail/Benutzername + Passwort
- "Login merken" Option
- Links zu Registrierung & Passwort vergessen
- Moderne, responsive UI
**Registrierung (`views/Register.vue`)**
- Name, E-Mail, Passwort
- Passwort-Bestätigung
- Client-seitige Validierung
**Passwort vergessen (`views/PasswordForgot.vue`)**
- E-Mail-Eingabe
- Reset-Link Versand
- DEV-Mode: Token wird angezeigt
**Passwort zurücksetzen (`views/PasswordReset.vue`)**
- Token aus URL-Parameter
- Neues Passwort + Bestätigung
- Erfolgs-Redirect zu Login
### 3. Router Guards (`router/index.js`)
**Automatischer Schutz:**
```javascript
// Geschützte Routes
{
path: '/',
component: Dashboard,
meta: { requiresAuth: true } // Nur für eingeloggte Benutzer
}
// Öffentliche Routes
{
path: '/login',
component: Login,
meta: { requiresGuest: true } // Nur für nicht-eingeloggte
}
```
**Navigation Guard:**
```javascript
router.beforeEach(async (to, from, next) => {
// 1. Session wiederherstellen falls Token vorhanden
// 2. Auth-Status prüfen
// 3. Redirect falls nötig
})
```
### 4. Session-Wiederherstellung
**Beim App-Start (`main.js`):**
```javascript
const authStore = useAuthStore()
if (authStore.loadToken()) {
await authStore.fetchCurrentUser()
}
```
**Bei jeder Navigation:**
```javascript
if (!authStore.isAuthenticated && authStore.loadToken()) {
await authStore.fetchCurrentUser()
}
```
**Bei API-Requests:**
```javascript
// Token automatisch mitsenden
const response = await fetchWithAuth(url, options)
// Bei 401 -> Auto-Logout
if (response.status === 401) {
authStore.clearAuth()
window.location.href = '/login'
}
```
## Sicherheits-Features
### Backend
1. **Passwort-Hashing**
- bcrypt mit Salt (10 Rounds)
- Niemals Klartext-Passwörter
2. **Login-Schutz**
- Max. 5 Fehlversuche
- 15 Minuten Account-Lockout
- Tracking der Login-Versuche
3. **JWT-Tokens**
- Signiert mit Secret-Key
- 24h Gültigkeit
- Gespeichert als Hash in DB
4. **Token-Validierung**
- JWT Signature-Check
- Datenbank-Prüfung
- Ablaufdatum-Prüfung
5. **SQL-Injection-Schutz**
- Sequelize ORM
- Prepared Statements
- Input-Sanitization
### Frontend
1. **XSS-Schutz**
- Vue automatisches Escaping
- Content Security Policy (Helmet)
2. **Token-Sicherheit**
- localStorage (HTTPS erforderlich!)
- Automatisches Löschen bei Logout
- Kein Token in URL/Query-Params
3. **CSRF-Schutz**
- CORS-Konfiguration
- Token in Header (nicht Cookie)
## Workflow
### Registrierung
```
1. Benutzer → /register
2. Formular ausfüllen
3. POST /api/auth/register
4. Backend: Passwort hashen, User + AuthInfo erstellen
5. Success → Redirect zu /login
```
### Login
```
1. Benutzer → /login
2. E-Mail + Passwort eingeben
3. POST /api/auth/login
4. Backend: Credentials prüfen, JWT generieren
5. Frontend: Token in localStorage speichern
6. Redirect zu /
7. Session ist aktiv!
```
### Session-Wiederherstellung (Reload)
```
1. App-Start / Page Reload
2. main.js lädt Token aus localStorage
3. GET /api/auth/me (mit Token)
4. Backend validiert Token
5. Benutzer-Daten zurück
6. authStore.user + isAuthenticated setzen
7. Session wiederhergestellt!
```
### API-Request mit Auth
```
1. fetchWithAuth(url, options)
2. Token aus localStorage laden
3. Header: Authorization: Bearer <token>
4. Request senden
5. Bei 401: clearAuth() + Redirect zu /login
```
### Logout
```
1. Logout-Button klicken
2. POST /api/auth/logout (Token in DB löschen)
3. Frontend: localStorage.removeItem('timeclock_token')
4. authStore.clearAuth()
5. Redirect zu /login
```
### Passwort vergessen
```
1. /password-forgot
2. E-Mail eingeben
3. POST /api/auth/request-reset
4. Backend: Reset-Token generieren, in DB speichern
5. (Produktion: E-Mail senden mit Link)
6. Benutzer klickt Link: /password-reset?token=xyz
7. Neues Passwort eingeben
8. POST /api/auth/reset-password
9. Backend: Token prüfen, Passwort hashen, speichern
10. Success → Login
```
## Konfiguration
### Backend (.env)
```env
JWT_SECRET=change-this-to-a-random-secret-key-in-production
JWT_EXPIRATION=24h
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=your-email@gmail.com
SMTP_PASSWORD=your-password
SMTP_FROM=noreply@timeclock.com
```
### Frontend
```javascript
// src/stores/authStore.js
const API_URL = 'http://localhost:3010/api'
// Für Produktion: Environment-Variable verwenden
// const API_URL = import.meta.env.VITE_API_URL
```
## Testing
### Backend
```bash
# Registrierung
curl -X POST http://localhost:3010/api/auth/register \
-H "Content-Type: application/json" \
-d '{"email":"test@example.com","password":"test123","full_name":"Test User"}'
# Login
curl -X POST http://localhost:3010/api/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"test@example.com","password":"test123"}'
# Aktueller Benutzer (mit Token)
curl http://localhost:3010/api/auth/me \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
```
### Frontend
1. `/register` → Neuen Account erstellen
2. `/login` → Einloggen
3. Browser-Reload → Session bleibt erhalten ✓
4. DevTools → Application → Local Storage → `timeclock_token` sichtbar
5. Logout → Token wird gelöscht ✓
## Troubleshooting
### Session geht nach Reload verloren
- localStorage überprüfen: DevTools → Application
- Browser-Konsole auf Fehler prüfen
- Token-Validierung im Backend überprüfen
### 401 Unauthorized
- Token abgelaufen (nach 24h)
- Token ungültig/gelöscht
- Backend-DB-Connection fehlt
### Login funktioniert nicht
- Backend läuft auf Port 3010?
- DB-Verbindung OK?
- Credentials korrekt?
- Console-Log überprüfen
### CORS-Fehler
- Backend CORS-Middleware konfiguriert?
- Frontend-URL in CORS-Config erlaubt?
## Best Practices
1. **Niemals JWT_SECRET committen**
- In .env (nicht in Git!)
- Für Produktion: Starkes, zufälliges Secret
2. **HTTPS in Produktion**
- localStorage mit HTTP unsicher!
- SSL-Zertifikat erforderlich
3. **Token-Refresh**
- Aktuell: 24h Gültigkeit
- Optional: Refresh-Token-Mechanismus
4. **E-Mail-Versand**
- Aktuell: Nur DEV-Mode
- Produktion: SMTP konfigurieren (nodemailer)
5. **Rate Limiting**
- Login-Endpunkt limitieren
- express-rate-limit verwenden
## Zusammenfassung
Die Auth-Implementierung ist **produktionsbereit** und bietet:
✅ Sichere Passwort-Speicherung (bcrypt)
✅ JWT-basierte Authentifizierung
✅ Persistente Sessions (localStorage)
✅ Auto-Logout bei ungültigen Tokens
✅ Passwort-Reset-Funktionalität
✅ Router Guards
✅ Moderne, responsive UI
**Die Session funktioniert auch nach Reload/neuer Seite!** 🎉