67 lines
2.6 KiB
PHP
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;
|
|
}
|