eplan/lib/eplan_token.lib.php
Eduard Wisch 593c93f377
All checks were successful
Deploy Eplan / deploy (push) Successful in 9s
feat: PWA-Token-Auth statt Dolibarr-REST-API-Key [deploy]
Das ElektroPlan-Backend spricht nicht mehr die Dolibarr-REST-API an
(API-Key-Flow kaputt, REST-Modul nicht zuverlässig), sondern einen
eigenen NOLOGIN-Endpoint im Eplan-Modul.

- ajax/pwa_api.php: NOLOGIN-Endpoint, Auth via X-Eplan-Token-Header
  gegen EPLAN_PWA_SECRET (hash_equals, timing-safe)
  Actions: ping, auftraege_listen, auftrag_details, kunden_suchen,
  dokument_upload (multipart POST)
- lib/eplan_token.lib.php: Lazy-init Token, Rotation, Verifikation
- admin/setup.php: Token-Feld (readonly, anklickbar zum Markieren),
  Endpoint-URL zum Kopieren, Button "Neuen Token erzeugen"
- de/en-Sprachdateien: EplanApiToken* Keys

Muster aus KB #354 (Bericht/Baustelle-PWA).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 11:02:27 +02:00

63 lines
1.7 KiB
PHP

<?php
/* Copyright (C) 2026 Eduard Wisch <data@data-it-solution.de>
* GPL v3+
*
* Token-Handling für die Eplan-PWA-Anbindung.
* Kein JWT — ein simpler Shared-Secret-Token reicht, weil nur der
* ElektroPlan-Backend-Container den Endpoint anspricht (Server-zu-Server
* über HTTPS). Kein User-Kontext, keine Rotation per Request.
*/
/**
* Lazy-init: Token aus llx_const laden, falls leer frisch erzeugen.
* @return string 64-Zeichen hex Token
*/
function eplanTokenHolen()
{
global $db, $conf;
$token = getDolGlobalString('EPLAN_PWA_SECRET');
if (!empty($token)) {
return $token;
}
$token = bin2hex(random_bytes(32));
dolibarr_set_const($db, 'EPLAN_PWA_SECRET', $token, 'chaine', 0, 'PWA-Token', $conf->entity);
return $token;
}
/**
* Neuen Token erzeugen (überschreibt den alten).
* @return string neuer Token
*/
function eplanTokenRotieren()
{
global $db, $conf;
$token = bin2hex(random_bytes(32));
dolibarr_set_const($db, 'EPLAN_PWA_SECRET', $token, 'chaine', 0, 'PWA-Token', $conf->entity);
return $token;
}
/**
* Vergleicht einen übergebenen Token mit dem gespeicherten (timing-safe).
* @param string $eingang Token aus dem Request
* @return bool
*/
function eplanTokenPruefen($eingang)
{
if (empty($eingang)) return false;
$gespeichert = getDolGlobalString('EPLAN_PWA_SECRET');
if (empty($gespeichert)) return false;
return hash_equals($gespeichert, (string) $eingang);
}
/**
* Token aus Request holen: bevorzugt Header X-Eplan-Token, sonst Query-Param `token`.
* @return string|null
*/
function eplanTokenAusRequest()
{
$header = $_SERVER['HTTP_X_EPLAN_TOKEN'] ?? '';
if (!empty($header)) return $header;
return $_GET['token'] ?? $_POST['token'] ?? null;
}