Files

142 lines
3.8 KiB
PHP
Raw Permalink Normal View History

2026-01-01 15:40:32 -05:00
<?php
/**
* ApiKeyAuth - Handles API key authentication for external services
*/
require_once dirname(__DIR__) . '/models/ApiKeyModel.php';
require_once dirname(__DIR__) . '/models/UserModel.php';
class ApiKeyAuth {
private $apiKeyModel;
private $userModel;
private $conn;
public function __construct($conn) {
$this->conn = $conn;
$this->apiKeyModel = new ApiKeyModel($conn);
$this->userModel = new UserModel($conn);
}
/**
* Authenticate using API key from Authorization header
*
* @return array User data for system user
* @throws Exception if authentication fails
*/
public function authenticate() {
// Get Authorization header
$authHeader = $this->getAuthorizationHeader();
if (empty($authHeader)) {
$this->sendUnauthorized('Missing Authorization header');
exit;
}
// Check if it's a Bearer token
if (!preg_match('/^Bearer\s+(.+)$/i', $authHeader, $matches)) {
$this->sendUnauthorized('Invalid Authorization header format. Expected: Bearer <api_key>');
exit;
}
$apiKey = $matches[1];
// Validate API key
$keyData = $this->apiKeyModel->validateKey($apiKey);
if (!$keyData) {
$this->sendUnauthorized('Invalid or expired API key');
exit;
}
// Get system user (or the user who created the key)
$user = $this->userModel->getSystemUser();
if (!$user) {
$this->sendUnauthorized('System user not found');
exit;
}
// Add API key info to user data for logging
$user['api_key_id'] = $keyData['api_key_id'];
$user['api_key_name'] = $keyData['key_name'];
return $user;
}
/**
* Get Authorization header from various sources
*
* @return string|null Authorization header value
*/
private function getAuthorizationHeader() {
// Try different header formats
if (isset($_SERVER['HTTP_AUTHORIZATION'])) {
return $_SERVER['HTTP_AUTHORIZATION'];
}
if (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) {
return $_SERVER['REDIRECT_HTTP_AUTHORIZATION'];
}
// Check for Authorization in getallheaders if available
if (function_exists('getallheaders')) {
$headers = getallheaders();
if (isset($headers['Authorization'])) {
return $headers['Authorization'];
}
if (isset($headers['authorization'])) {
return $headers['authorization'];
}
}
return null;
}
/**
* Send 401 Unauthorized response
*
* @param string $message Error message
*/
private function sendUnauthorized($message) {
header('HTTP/1.1 401 Unauthorized');
header('Content-Type: application/json');
echo json_encode([
'success' => false,
'error' => 'Unauthorized',
'message' => $message
]);
}
/**
* Verify API key without throwing errors (for optional auth)
*
* @return array|null User data or null if not authenticated
*/
public function verifyOptional() {
$authHeader = $this->getAuthorizationHeader();
if (empty($authHeader)) {
return null;
}
if (!preg_match('/^Bearer\s+(.+)$/i', $authHeader, $matches)) {
return null;
}
$apiKey = $matches[1];
$keyData = $this->apiKeyModel->validateKey($apiKey);
if (!$keyData) {
return null;
}
$user = $this->userModel->getSystemUser();
if ($user) {
$user['api_key_id'] = $keyData['api_key_id'];
$user['api_key_name'] = $keyData['key_name'];
}
return $user;
}
}