isLoggedIn()) { header('Location: index.php'); exit; } } catch (Exception $e) { die('Fehler beim Initialisieren: ' . $e->getMessage()); } I18n::init(); $error = ''; $success = ''; $show2fa = false; if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['totp_code'])) { // Zweiter Login-Schritt: 2FA-Code try { if ($auth->verifyTotpLogin(trim($_POST['totp_code']))) { header('Location: index.php'); exit; } $error = 'Code ungültig oder abgelaufen. Bitte erneut versuchen.'; $show2fa = $auth->isTotpPending(); } catch (Exception $e) { $error = 'Login-Fehler: ' . $e->getMessage(); } } elseif ($_SERVER['REQUEST_METHOD'] === 'POST') { try { $email = trim($_POST['email'] ?? ''); $password = $_POST['password'] ?? ''; if (empty($email) || empty($password)) { $error = __('login_error_empty'); } else { $result = $auth->login($email, $password); if ($result === true) { header('Location: index.php'); exit; } elseif ($result === 'totp_required') { $show2fa = true; } elseif ($result === 'rate_limited') { $error = __('login_error_rate'); } else { $error = __('login_error_creds'); } } } catch (Exception $e) { $error = 'Login-Fehler: ' . $e->getMessage(); } } // Direkter Aufruf mit ?2fa=1 (z.B. nach Redirect) und noch ausstehendem Login if (!$show2fa && isset($_GET['2fa']) && $auth->isTotpPending()) { $show2fa = true; } try { $db = Database::getInstance(); $appTitle = $db->getSetting('app_title', 'UniFi Voucher System'); $logoUrl = $db->getSetting('logo_url', ''); $m365ClientId = $db->getSetting('m365_client_id', ''); $m365ClientSecret = $db->getSetting('m365_client_secret', ''); $m365TenantId = $db->getSetting('m365_tenant_id', ''); $m365Enabled = !empty($m365ClientId) && !empty($m365ClientSecret) && !empty($m365TenantId); $publicAccess = $db->getSetting('public_access', 0); $smtpEnabled = $db->getSetting('smtp_enabled', '0') === '1'; $m365LoginUrl = ''; if ($m365Enabled) { $protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http'; $host = $_SERVER['HTTP_HOST']; $scriptPath = dirname($_SERVER['SCRIPT_NAME']); $scriptPath = $scriptPath === '/' ? '' : $scriptPath; $redirectUri = $protocol . '://' . $host . $scriptPath . '/m365_callback.php'; $params = [ 'client_id' => $m365ClientId, 'response_type' => 'code', 'redirect_uri' => $redirectUri, 'response_mode' => 'query', 'scope' => 'openid profile email User.Read', 'state' => bin2hex(random_bytes(16)) ]; $_SESSION['m365_state'] = $params['state']; $m365LoginUrl = "https://login.microsoftonline.com/$m365TenantId/oauth2/v2.0/authorize?" . http_build_query($params); } // Generisches OIDC (optional) $oidcEnabled = $db->getSetting('oidc_enabled', '0') === '1' && $db->getSetting('oidc_client_id', '') !== '' && $db->getSetting('oidc_auth_url', '') !== ''; $oidcName = $db->getSetting('oidc_name', 'SSO'); $oidcLoginUrl = ''; if ($oidcEnabled) { $protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http'; $scriptPath = dirname($_SERVER['SCRIPT_NAME']); $scriptPath = $scriptPath === '/' ? '' : $scriptPath; $oidcState = bin2hex(random_bytes(16)); $_SESSION['oidc_state'] = $oidcState; $oidcLoginUrl = rtrim($db->getSetting('oidc_auth_url', ''), '?') . '?' . http_build_query([ 'client_id' => $db->getSetting('oidc_client_id', ''), 'response_type' => 'code', 'redirect_uri' => $protocol . '://' . $_SERVER['HTTP_HOST'] . $scriptPath . '/oidc_callback.php', 'scope' => $db->getSetting('oidc_scopes', 'openid profile email'), 'state' => $oidcState, ]); } $showLocalLogin = isset($_GET['local']) && $_GET['local'] === '1'; } catch (Exception $e) { die('Datenbankfehler: ' . $e->getMessage()); } ?>
= __('login_subtitle') ?>