# 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