Files
stechuhr3/backend/ID_HASHING.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

165 lines
3.9 KiB
Markdown

# ID-Hashing System
## Übersicht
Das TimeClock Backend verwendet ein automatisches ID-Hashing-System, das alle numerischen IDs in API-Responses verschlüsselt und eingehende Hash-IDs automatisch entschlüsselt.
## Warum ID-Hashing?
- **Sicherheit**: Verhindert, dass Angreifer die Anzahl der Datensätze erraten können
- **Obfuscation**: Versteckt die interne Datenbankstruktur
- **Schutz vor ID-Enumeration**: Verhindert systematisches Durchlaufen von Ressourcen
## Funktionsweise
### Automatisches Hashing (Backend → Frontend)
Alle numerischen ID-Felder in API-Responses werden automatisch in Hashes konvertiert:
```javascript
// Datenbank-Daten:
{
id: 123,
user_id: 456,
full_name: "Max Mustermann"
}
// API-Response:
{
id: "xY9kL2mP3qR5.aB7cD8eF9gH0",
user_id: "tU6vW7xY8zZ9.iJ1kL2mN3oP4",
full_name: "Max Mustermann"
}
```
### Automatisches Enthashen (Frontend → Backend)
Alle Hash-IDs in eingehenden Requests werden automatisch zurück in numerische IDs konvertiert:
```javascript
// Frontend sendet:
{
user_id: "xY9kL2mP3qR5.aB7cD8eF9gH0"
}
// Backend erhält:
{
user_id: 123
}
```
## Implementierung
### Backend
Das System besteht aus drei Komponenten:
1. **`utils/hashId.js`**: Utility-Klasse für Encoding/Decoding
2. **`middleware/hashResponse.js`**: Middleware für ausgehende Responses
3. **`middleware/unhashRequest.js`**: Middleware für eingehende Requests
### Konfiguration
In der `.env`-Datei:
```env
HASH_ID_SECRET=your-hash-id-secret-change-in-production
```
⚠️ **Wichtig**: Das Secret sollte in Produktion geändert werden und geheim bleiben!
### Erkannte ID-Felder
Folgende Feldnamen werden automatisch als IDs erkannt und gehashed:
- `id`, `_id`
- `user_id`, `userId`
- `auth_info_id`, `authInfoId`
- `auth_token_id`, `authTokenId`
- `worklog_id`, `worklogId`
- `vacation_id`, `vacationId`
- `sick_id`, `sickId`
- `holiday_id`, `holidayId`
- `state_id`, `stateId`
- `sick_type_id`, `sickTypeId`
- `weekly_worktime_id`, `weeklyWorktimeId`
## Frontend-Integration
Das Frontend muss keine Änderungen vornehmen - es arbeitet einfach mit den empfangenen Hash-IDs:
```javascript
// GET /api/auth/me
const response = await fetch('/api/auth/me')
const data = await response.json()
console.log(data.user.id) // "xY9kL2mP3qR5.aB7cD8eF9gH0"
// POST /api/some-endpoint
await fetch('/api/some-endpoint', {
method: 'POST',
body: JSON.stringify({
user_id: data.user.id // Hash wird automatisch entschlüsselt
})
})
```
## Manuelle Verwendung
Falls manuelles Encoding/Decoding nötig ist:
```javascript
const hashId = require('./utils/hashId');
// Einzelne ID hashen
const hash = hashId.encode(123); // "xY9kL2mP3qR5.aB7cD8eF9gH0"
// Hash dekodieren
const id = hashId.decode(hash); // 123
// Objekt hashen
const obj = { id: 123, name: "Test" };
const hashed = hashId.encodeObject(obj); // { id: "xY9...", name: "Test" }
// Array hashen
const array = [{ id: 1 }, { id: 2 }];
const hashedArray = hashId.encodeArray(array);
```
## Sicherheitshinweise
1. **Secret ändern**: Ändern Sie `HASH_ID_SECRET` in der Produktion
2. **Secret sicher aufbewahren**: Das Secret sollte niemals im Code oder in der Versionskontrolle erscheinen
3. **Keine zusätzliche Sicherheit**: ID-Hashing ersetzt keine echte Autorisierung - prüfen Sie immer die Zugriffsrechte!
## Hash-Format
Das Hash-Format: `{encrypted_id}.{hash_prefix}`
- **encrypted_id**: AES-256-CBC verschlüsselte ID
- **hash_prefix**: HMAC-SHA256 Hash (erste 12 Zeichen) zur Verifizierung
- **Encoding**: base64url (URL-sicher)
Beispiel: `xY9kL2mP3qR5.aB7cD8eF9gH0`
## Fehlerbehandlung
Ungültige Hash-IDs werden zu `null` dekodiert. Services/Controller sollten dies behandeln:
```javascript
const userId = req.params.id; // Könnte null sein wenn Hash ungültig
if (!userId) {
return res.status(400).json({ error: 'Ungültige ID' });
}
```
## Performance
- **Encoding**: ~0.1ms pro ID
- **Decoding**: ~0.2ms pro ID
- **Overhead**: Minimal, da deterministisch und ohne Datenbank-Zugriff