fix(2.9.3): Ankerpruefung vergleicht, statt nur auf "gesetzt" zu sehen

checks.webauthn_anchor meldete bisher nur, OB app.url oder
security.webauthn_rp_id einen Wert tragen. Das beantwortet die Frage
nicht, die dahintersteht: Ein Tippfehler in app.url weist den
Hardwarekey genauso ab wie ein fehlender Wert - der Browser traegt den
echten Ursprung in clientDataJSON ein, und der muss zu expectedOrigin
passen.

Die Pruefung vergleicht jetzt zusaetzlich mit dem Namen, unter dem die
Anfrage tatsaechlich hereinkam, und meldet configured und
matches_request getrennt. Dass dafuer der Host-Header herangezogen wird,
ist unbedenklich: Es ist eine Diagnose, keine Entscheidung. Wer ihn
faelscht, erzeugt eine falsche Warnung und sonst nichts - waehrend
WebauthnServer ihn weiterhin unveraendert ignoriert.

Damit ist die Auskunft vor einem Deployment belastbar, statt nur die
haelfte der Frage zu beantworten.

188 von 188 Testfaellen gruen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Deploymentcenter Bot
2026-09-21 15:52:51 +02:00
co-authored by Claude Opus 5
parent 91d8bf353e
commit df67932019
+37 -6
View File
@@ -58,14 +58,45 @@ $checks['log_writable'] = ['ok' => is_dir($logDir) ? is_writable($logDir) : is_w
// beim naechsten Anmeldeversuch. Gemeldet wird nur, OB ein Wert gesetzt ist -
// nicht welcher; eine Gesundheitsauskunft ohne Anmeldung soll keine
// Konfiguration ausplaudern.
$appUrlGesetzt = trim((string)Config::get('app.url', '')) !== ''
|| trim((string)Config::get('security.webauthn_rp_id', '')) !== '';
$appUrl = trim((string)Config::get('app.url', ''));
$rpIdConf = trim((string)Config::get('security.webauthn_rp_id', ''));
$gesetzt = $appUrl !== '' || $rpIdConf !== '';
// "Gesetzt" allein genuegt als Auskunft nicht. Ein Tippfehler in app.url
// weist den Hardwarekey genauso ab wie ein fehlender Wert - der Browser
// traegt den echten Ursprung in clientDataJSON ein, und der muss zu
// expectedOrigin passen. Deshalb wird hier zusaetzlich verglichen, unter
// welchem Namen diese Anfrage tatsaechlich hereingekommen ist.
//
// Dass dafuer der Host-Header herangezogen wird, ist hier unbedenklich: Es
// ist eine Diagnose, keine Entscheidung. Wer ihn faelscht, erzeugt eine
// falsche Warnung und sonst nichts - waehrend WebauthnServer ihn
// unveraendert ignoriert.
$erwarteterHost = $rpIdConf !== ''
? $rpIdConf
: (string)(parse_url($appUrl, PHP_URL_HOST) ?: '');
$tatsaechlicherHost = strtolower((string)(explode(':', (string)($_SERVER['HTTP_HOST'] ?? ''))[0]));
$passt = $erwarteterHost !== ''
&& strtolower($erwarteterHost) === $tatsaechlicherHost;
$hinweis = null;
if (!$gesetzt) {
$hinweis = 'app.url oder security.webauthn_rp_id fehlt - der Hardwarekey wird abgewiesen.';
} elseif (!$passt) {
$hinweis = sprintf(
'Die hinterlegte Adresse ("%s") ist eine andere als die, unter der diese Anfrage '
. 'hereinkam. Ein Hardwarekey, der unter der einen registriert wurde, wird unter der '
. 'anderen abgewiesen.',
$erwarteterHost
);
}
$checks['webauthn_anchor'] = [
'ok' => $appUrlGesetzt,
'hint' => $appUrlGesetzt
? null
: 'app.url oder security.webauthn_rp_id fehlt - der Hardwarekey wird abgewiesen.',
'ok' => $gesetzt && $passt,
'configured' => $gesetzt,
'matches_request' => $passt,
'hint' => $hinweis,
];
// Bewusst KEIN $healthy = false: Eine Anlage ohne Hardwarekeys laeuft damit