diff --git a/auth/nove_heslo.php b/auth/nove_heslo.php new file mode 100644 index 0000000..71131a2 --- /dev/null +++ b/auth/nove_heslo.php @@ -0,0 +1,279 @@ + 0, + 'path' => '/', + 'httponly' => true, + 'samesite' => 'Strict', + // 'secure' => true, +]); +session_start(); + +// Pokud je uživatel přihlášen, přesměrujeme ho +if (isset($_SESSION['uzivatel_id'])) { + header('Location: ' . AUTH_REDIRECT_PO_PRIHLASENI); + exit; +} + +// ------------------------------------------------------------ +// CSRF TOKEN +// ------------------------------------------------------------ + +if (empty($_SESSION['csrf_token'])) { + $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); +} +$csrf_token = $_SESSION['csrf_token']; + +// ------------------------------------------------------------ +// OVĚŘENÍ ODKAZU (parametry z URL) +// ------------------------------------------------------------ + +$token_ok = false; // true pokud je token platný +$zaznam_id = 0; // ID záznamu v auth_password_resets +$uzivatel_id = 0; // ID uživatele + +$id_z_url = $_GET['id'] ?? ''; +$token_z_url = $_GET['token'] ?? ''; + +if (!empty($id_z_url) && !empty($token_z_url)) { + + // Vyhledáme záznam podle ID + $stmt = $pdo->prepare(" + SELECT `id`, `uzivatel_id`, `token_hash`, `expiruje` + FROM `" . DB_TABULKA_RESET . "` + WHERE `id` = :id + LIMIT 1 + "); + $stmt->execute([':id' => (int) $id_z_url]); + $zaznam = $stmt->fetch(); + + if ($zaznam) { + + // Zkontrolujeme expiraci + if (time() < strtotime($zaznam['expiruje'])) { + + // Ověříme token (password_verify = konstantní čas, + // ochrana před timing útoky) + if (password_verify($token_z_url, $zaznam['token_hash'])) { + $token_ok = true; + $zaznam_id = $zaznam['id']; + $uzivatel_id = $zaznam['uzivatel_id']; + } + } + } +} + +// ------------------------------------------------------------ +// ZPRACOVÁNÍ FORMULÁŘE (nastavení nového hesla) +// ------------------------------------------------------------ + +$chyba = ''; +$uspech = false; + +if ($_SERVER['REQUEST_METHOD'] === 'POST' && $token_ok) { + + // -- Ověření CSRF tokenu ---------------------------------- + $csrf_z_formulare = $_POST['csrf_token'] ?? ''; + if (!hash_equals($csrf_token, $csrf_z_formulare)) { + $chyba = 'Neplatný požadavek. Zkuste stránku obnovit a zkusit znovu.'; + } + + if (empty($chyba)) { + + $heslo = $_POST['heslo'] ?? ''; + $heslo2 = $_POST['heslo2'] ?? ''; + + // Validace hesla + if (empty($heslo)) { + $chyba = 'Heslo nesmí být prázdné.'; + } elseif (mb_strlen($heslo) < HESLO_MIN_DELKA) { + $chyba = 'Heslo musí mít alespoň ' . HESLO_MIN_DELKA . ' znaků.'; + } elseif ($heslo !== $heslo2) { + $chyba = 'Hesla se neshodují.'; + } + } + + if (empty($chyba)) { + + try { + + // Zahashujeme nové heslo + $heslo_hash = password_hash($heslo, PASSWORD_DEFAULT); + + // Aktualizujeme heslo uživatele v DB + $stmt = $pdo->prepare(" + UPDATE `" . DB_TABULKA_UZIVATELE . "` + SET `heslo` = :heslo + WHERE `id` = :id + "); + $stmt->execute([ + ':heslo' => $heslo_hash, + ':id' => $uzivatel_id, + ]); + + // Smažeme použitý reset token – je jednorázový + $stmt2 = $pdo->prepare(" + DELETE FROM `" . DB_TABULKA_RESET . "` + WHERE `id` = :id + "); + $stmt2->execute([':id' => $zaznam_id]); + + // Smažeme všechny remember me tokeny tohoto uživatele – + // po změně hesla jsou všechna zařízení odhlášena + $stmt3 = $pdo->prepare(" + DELETE FROM `" . DB_TABULKA_TOKENY . "` + WHERE `uzivatel_id` = :uzivatel_id + "); + $stmt3->execute([':uzivatel_id' => $uzivatel_id]); + + $uspech = true; + + } catch (PDOException $e) { + error_log('Chyba při změně hesla: ' . $e->getMessage()); + $chyba = 'Při ukládání hesla došlo k chybě. Zkuste to prosím znovu.'; + } + } +} + +// ------------------------------------------------------------ +// HTML VÝSTUP +// ------------------------------------------------------------ +?> + + +
+ +Heslo bylo úspěšně změněno.
+Všechna zařízení byla odhlášena. Můžeš se nyní + přihlásit + novým heslem.
+ + + + +Tento odkaz pro obnovu hesla je neplatný nebo vypršel.
+Požádej o + + nový odkaz pro obnovu hesla.
+ + + + + + +Chyba:
+ + +Zadej nové heslo pro svůj účet.
+ + + + + + + + + + \ No newline at end of file