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

3.9 KiB

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:

// 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:

// 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:

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:

// 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:

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:

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