Files

43 lines
1.7 KiB
PHP

<?php
declare(strict_types=1);
final class ApiAuth
{
public static function bearerClaims(): array
{
$header = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
if (!preg_match('/^Bearer\s+([A-Za-z0-9_.-]+)$/i', $header, $matches)) {
api_json(['error' => 'unauthorized'], 401);
}
$claims = JwtToken::verify($matches[1]);
if ($claims === null) {
api_json(['error' => 'unauthorized'], 401);
}
try {
$db = Database::getInstance();
$stmt = $db->prepare('SELECT u.id, u.account_role, u.is_active FROM auth_sessions s JOIN users u ON u.id = s.user_id WHERE s.session_uuid = ? AND s.user_id = ? AND s.revoked_at IS NULL AND s.replaced_by IS NULL AND s.expires_at > UTC_TIMESTAMP() AND u.is_active = 1 LIMIT 1');
$userId = (int) $claims['sub'];
$sessionId = $claims['sid'];
$stmt->bind_param('si', $sessionId, $userId);
$stmt->execute();
$result = $stmt->get_result();
$user = $result->fetch_assoc();
$stmt->close();
if (!$user) {
api_json(['error' => 'unauthorized'], 401);
}
return ['user_id' => (int) $user['id'], 'role' => $user['account_role'], 'session_id' => $sessionId];
} catch (Throwable $exception) {
error_log('Bearer authorization check failed: ' . $exception->getMessage());
api_json(['error' => 'service_unavailable'], 503);
}
}
public static function requireRole(array $auth, array $allowedRoles): void
{
if (!in_array($auth['role'] ?? null, $allowedRoles, true)) {
api_json(['error' => 'forbidden'], 403);
}
}
}