PDF-accessibility-saas/auth.php

198 lines
5.3 KiB
PHP

<?php
/**
* API Authentication Module
*
* Provides simple API key authentication for REST API endpoints
* Supports multiple authentication methods:
* - Authorization: Bearer <token>
* - X-API-Key: <key>
* - Query parameter: ?api_key=<key> (dev only)
*/
/**
* Check if request is authenticated
*
* @return bool True if authenticated, false otherwise
*/
function authenticate() {
// Development mode: allow localhost without auth
if (isDevelopmentMode()) {
return true;
}
$api_key = extractApiKey();
if (!$api_key) {
return false;
}
// Validate against configured keys
$valid_keys = getValidApiKeys();
return in_array($api_key, $valid_keys, true);
}
/**
* Check if running in development mode (localhost)
*
* @return bool True if development mode
*/
function isDevelopmentMode() {
// DEV_MODE env var explicitly bypasses auth (set in Apache/env config)
$dev_mode = getenv('DEV_MODE');
return ($dev_mode === 'true' || $dev_mode === '1');
}
/**
* Extract API key from request
*
* Checks multiple sources in order of security:
* 1. Authorization: Bearer header
* 2. X-API-Key header
* 3. Query parameter (least secure, for dev only)
*
* @return string|null API key or null if not found
*/
function extractApiKey() {
// Check Authorization: Bearer header
if (isset($_SERVER['HTTP_AUTHORIZATION'])) {
if (preg_match('/Bearer\s+(.*)$/i', $_SERVER['HTTP_AUTHORIZATION'], $matches)) {
return trim($matches[1]);
}
}
// Check X-API-Key header
if (isset($_SERVER['HTTP_X_API_KEY'])) {
return trim($_SERVER['HTTP_X_API_KEY']);
}
// Check query parameter (least secure - dev only)
if (isDevelopmentMode() && isset($_GET['api_key'])) {
return trim($_GET['api_key']);
}
return null;
}
/**
* Get list of valid API keys
*
* Loads keys from:
* 1. Environment variable API_KEY
* 2. .api_keys file (one key per line)
* 3. Default dev key (for development only)
*
* @return array List of valid API keys
*/
function getValidApiKeys() {
$keys = [];
// Load from environment variable
$env_key = getenv('API_KEY');
if ($env_key) {
$keys[] = $env_key;
}
// Load from .api_keys file
$config_file = __DIR__ . '/.api_keys';
if (file_exists($config_file)) {
$file_keys = file($config_file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
if ($file_keys) {
// Filter out comments and empty lines
$file_keys = array_filter($file_keys, function($line) {
$line = trim($line);
return $line && substr($line, 0, 1) !== '#';
});
$keys = array_merge($keys, array_values($file_keys));
}
}
// Fallback to dev key only in development mode
if (empty($keys) && isDevelopmentMode()) {
error_log("WARNING: Using default dev API key. Configure proper API keys for production!");
$keys[] = 'dev_key_12345';
}
return array_unique($keys);
}
/**
* Send error response and exit
*
* @param string $message Error message
* @param int $status_code HTTP status code
*/
function sendUnauthorizedResponse($message = "Unauthorized", $status_code = 401) {
http_response_code($status_code);
header('Content-Type: application/json');
header('WWW-Authenticate: Bearer realm="API"');
echo json_encode([
'success' => false,
'error' => $message,
'status' => $status_code
]);
exit;
}
/**
* Require authentication or send error
*
* Call this at the beginning of protected endpoints
*/
function requireAuth() {
if (!authenticate()) {
sendUnauthorizedResponse("Valid API key required");
}
}
/**
* Generate a new random API key
*
* @return string 64-character hex API key
*/
function generateApiKey() {
return bin2hex(random_bytes(32));
}
// Example usage (for testing):
if (basename(__FILE__) == basename($_SERVER['SCRIPT_FILENAME'])) {
header('Content-Type: text/plain');
echo "PDF Accessibility Checker - Authentication Module\n";
echo "=================================================\n\n";
if (isset($_GET['generate'])) {
echo "New API Key:\n";
echo generateApiKey() . "\n\n";
echo "Add this to your .api_keys file or API_KEY environment variable.\n";
} else if (isset($_GET['test'])) {
echo "Testing authentication...\n\n";
$api_key = extractApiKey();
if ($api_key) {
echo "API Key found: " . substr($api_key, 0, 8) . "...\n";
if (authenticate()) {
echo "✅ Authentication successful!\n";
} else {
echo "❌ Authentication failed - invalid key\n";
}
} else {
echo "❌ No API key provided\n";
echo "\nTry:\n";
echo " - Add header: X-API-Key: <your-key>\n";
echo " - Or query param: ?api_key=<your-key>&test=1\n";
}
echo "\nValid keys configured: " . count(getValidApiKeys()) . "\n";
} else {
echo "Available actions:\n";
echo " ?generate - Generate new API key\n";
echo " ?test - Test authentication\n";
echo "\nExample:\n";
echo " php auth.php?generate\n";
echo " curl -H 'X-API-Key: your-key' http://localhost:8000/auth.php?test\n";
}
}
?>