115 lines
3.4 KiB
PHP
115 lines
3.4 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Middleware;
|
|
|
|
use Closure;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Log;
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
|
|
class ApiKeyAuthenticationMiddleware
|
|
{
|
|
/**
|
|
* Handle an incoming request.
|
|
*
|
|
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
|
|
*/
|
|
public function handle(Request $request, Closure $next): Response
|
|
{
|
|
// Check if API key authentication is enabled
|
|
if (!config('api_security.enable_api_key_auth', true)) {
|
|
return $next($request);
|
|
}
|
|
|
|
// Get API key from request
|
|
$apiKey = $this->extractApiKey($request);
|
|
|
|
if (!$apiKey) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'API key is required for external system access.',
|
|
'error' => 'API_KEY_REQUIRED'
|
|
], 401);
|
|
}
|
|
|
|
// Validate API key
|
|
if (!$this->isValidApiKey($apiKey)) {
|
|
// Log invalid API key attempt
|
|
if (config('api_security.log_api_key_usage', true)) {
|
|
Log::warning('Invalid API key attempt', [
|
|
'ip' => $request->ip(),
|
|
'user_agent' => $request->header('User-Agent'),
|
|
'endpoint' => $request->fullUrl(),
|
|
'method' => $request->method(),
|
|
'api_key_prefix' => substr($apiKey, 0, 8) . '...',
|
|
]);
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Invalid API key provided.',
|
|
'error' => 'API_KEY_INVALID'
|
|
], 401);
|
|
}
|
|
|
|
// Log successful API key usage
|
|
if (config('api_security.log_api_key_usage', true)) {
|
|
Log::info('API key authenticated', [
|
|
'ip' => $request->ip(),
|
|
'user_agent' => $request->header('User-Agent'),
|
|
'endpoint' => $request->fullUrl(),
|
|
'method' => $request->method(),
|
|
'api_key_prefix' => substr($apiKey, 0, 8) . '...',
|
|
]);
|
|
}
|
|
|
|
// Add API key info to request for downstream use
|
|
$request->merge(['_api_key' => $apiKey]);
|
|
|
|
return $next($request);
|
|
}
|
|
|
|
/**
|
|
* Extract API key from request headers
|
|
*/
|
|
private function extractApiKey(Request $request): ?string
|
|
{
|
|
// Check multiple header formats
|
|
$apiKeyHeaders = config('api_security.api_key_headers', [
|
|
'X-API-Key',
|
|
'API-Key',
|
|
'Authorization'
|
|
]);
|
|
|
|
foreach ($apiKeyHeaders as $header) {
|
|
$value = $request->header($header);
|
|
|
|
if ($value) {
|
|
// Handle Bearer token format
|
|
if ($header === 'Authorization' && preg_match('/Bearer\s+(.*)$/i', $value, $matches)) {
|
|
return $matches[1];
|
|
}
|
|
|
|
// Direct API key
|
|
return $value;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Validate API key against configured valid keys
|
|
*/
|
|
private function isValidApiKey(string $apiKey): bool
|
|
{
|
|
$validApiKeys = config('api_security.valid_api_keys', []);
|
|
|
|
if (empty($validApiKeys)) {
|
|
return false;
|
|
}
|
|
|
|
return in_array($apiKey, $validApiKeys);
|
|
}
|
|
}
|