| 
<?phpnamespace App;
 
 use Firebase\JWT\JWT;
 use Firebase\JWT\Key;
 
 class Authenticator
 {
 public array $config;
 
 public function __construct(array $config)
 {
 $this->config = $config;
 }
 
 public function authenticate(): bool
 {
 if (empty($this->config['auth_enabled'])) {
 return true;
 }
 
 switch ($this->config['auth_method']) {
 case 'apikey':
 $headers = $this->getHeaders();
 $key = $headers['X-API-Key'] ?? ($_GET['api_key'] ?? null);
 return in_array($key, $this->config['api_keys'], true);
 
 case 'basic':
 if (!isset($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'])) {
 $this->requireBasicAuth();
 return false;
 }
 $user = $_SERVER['PHP_AUTH_USER'];
 $pass = $_SERVER['PHP_AUTH_PW'];
 return isset($this->config['basic_users'][$user])
 && $this->config['basic_users'][$user] === $pass;
 
 case 'jwt':
 $headers = $this->getHeaders();
 $authHeader = $headers['Authorization'] ?? '';
 if (preg_match('/Bearer\s(\S+)/', $authHeader, $matches)) {
 $jwt = $matches[1];
 return $this->validateJwt($jwt);
 }
 return false;
 
 case 'oauth':
 // Placeholder for OAuth token validation
 $headers = $this->getHeaders();
 $authHeader = $headers['Authorization'] ?? '';
 if (preg_match('/Bearer\s(\S+)/', $authHeader, $matches)) {
 $token = $matches[1];
 // TODO: Validate $token with OAuth provider
 return false;
 }
 return false;
 
 default:
 return false;
 }
 }
 
 public function requireAuth()
 {
 if (!$this->authenticate()) {
 http_response_code(401);
 header('Content-Type: application/json');
 echo json_encode(['error' => 'Unauthorized']);
 exit;
 }
 }
 
 public function createJwt(array $payload, int $expireSeconds = 3600): string
 {
 $now = time();
 $payload = array_merge([
 'iat' => $now,
 'exp' => $now + $expireSeconds,
 'iss' => $this->config['jwt_issuer'] ?? '',
 'aud' => $this->config['jwt_audience'] ?? '',
 ], $payload);
 
 return JWT::encode($payload, $this->config['jwt_secret'], 'HS256');
 }
 
 public function validateJwt(string $jwt): bool
 {
 try {
 $decoded = JWT::decode($jwt, new Key($this->config['jwt_secret'], 'HS256'));
 // Optionally: Validate iss/aud/exp
 return true;
 } catch (\Exception $e) {
 return false;
 }
 }
 
 private function getHeaders(): array
 {
 if (function_exists('getallheaders')) {
 return getallheaders();
 }
 // Fallback
 $headers = [];
 foreach ($_SERVER as $name => $value) {
 if (str_starts_with($name, 'HTTP_')) {
 $header = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))));
 $headers[$header] = $value;
 }
 }
 return $headers;
 }
 
 private function requireBasicAuth()
 {
 header('WWW-Authenticate: Basic realm="API"');
 http_response_code(401);
 echo json_encode(['error' => 'Unauthorized']);
 exit;
 }
 }
 |