Files
hyprcrd/relay/inc/auth.php
T

67 lines
2.6 KiB
PHP

<?php
// Auth helpers: rate limiting, sessions (UI), client API auth (header).
if (!defined('RELAY_BOOTSTRAPPED')) { http_response_code(404); exit; }
function isRateLimited(PDO $db, string $endpoint, int $max = 10): bool {
$ip = $_SERVER['REMOTE_ADDR'] ?? '';
$count = $db->prepare("SELECT COUNT(*) FROM rate_limits WHERE ip = :ip AND endpoint = :ep AND attempted_at > datetime('now', '-1 minutes')");
$count->execute(['ip' => $ip, 'ep' => $endpoint]);
if ((int)$count->fetchColumn() >= $max) return true;
$db->prepare("INSERT INTO rate_limits (ip, endpoint) VALUES (:ip, :ep)")->execute(['ip' => $ip, 'ep' => $endpoint]);
return false;
}
function makeSession(PDO $db, int $tenantId, int $hours = 24): string {
$token = bin2hex(random_bytes(32));
$db->prepare("INSERT INTO sessions (id, tenant_id, expires_at) VALUES (:t, :u, datetime('now', '+{$hours} hours'))")
->execute(['t' => $token, 'u' => $tenantId]);
return $token;
}
function getSessionTenant(PDO $db): ?array {
$token = $_COOKIE['relay_session'] ?? '';
if (!$token) return null;
$stmt = $db->prepare("SELECT t.* FROM sessions s JOIN tenants t ON t.id = s.tenant_id WHERE s.id = :tok AND s.expires_at > datetime('now')");
$stmt->execute(['tok' => $token]);
return $stmt->fetch() ?: null;
}
function destroySession(PDO $db): void {
$token = $_COOKIE['relay_session'] ?? '';
if ($token) {
$db->prepare('DELETE FROM sessions WHERE id = :t')->execute(['t' => $token]);
}
setcookie('relay_session', '', [
'expires' => time() - 3600,
'path' => '/',
'httponly' => true,
'samesite' => 'Strict',
'secure' => !empty($_SERVER['HTTPS']) || ($_SERVER['HTTP_X_FORWARDED_PROTO'] ?? '') === 'https',
]);
}
function setSessionCookie(string $token): void {
setcookie('relay_session', $token, [
'expires' => time() + 86400,
'path' => '/',
'httponly' => true,
'samesite' => 'Strict',
'secure' => !empty($_SERVER['HTTPS']) || ($_SERVER['HTTP_X_FORWARDED_PROTO'] ?? '') === 'https',
]);
}
/**
* Authenticate a tenant via the client API headers (X-Relay-User + X-Relay-Key).
* Returns the tenant row on success, null on failure.
*/
function authClient(PDO $db): ?array {
$username = $_SERVER['HTTP_X_RELAY_USER'] ?? '';
$key = $_SERVER['HTTP_X_RELAY_KEY'] ?? '';
if (!$username || !$key) return null;
$tenant = getTenantByUsername($db, $username);
if (!$tenant) return null;
if (!password_verify($key, $tenant['secret_hash'])) return null;
return $tenant;
}