Skip to content

Custom Plugin Implementation

Create a custom plugin to implement specific business logic:

<?php

namespace App\Security\Firewall\Plugins;

use Kanopi\Firewall\Plugins\AbstractPluginBase;
use Symfony\Component\HttpFoundation\Request;

class ApiKeyValidator extends AbstractPluginBase
{
    private array $validApiKeys;

    public function __construct(array $metadata = [], array $config = [])
    {
        parent::__construct($metadata, $config);

        // Load API keys from configuration or database
        $this->validApiKeys = $metadata['api_keys'] ?? [];
    }

    public function getName(): string
    {
        return 'API Key Validator';
    }

    public function getDescription(): string
    {
        return 'Validates API keys for authenticated endpoints';
    }

    public function evaluate(Request $request): bool
    {
        // Only check API endpoints
        if (!str_starts_with($request->getPathInfo(), '/api/')) {
            return false;
        }

        // Check for API key in header or query
        $apiKey = $request->headers->get('X-API-Key') 
                  ?? $request->query->get('api_key');

        if (!$apiKey) {
            $this->logger?->warning('Missing API key', [
                'ip' => $request->getClientIp(),
                'path' => $request->getPathInfo(),
            ]);
            return true; // Block request
        }

        if (!in_array($apiKey, $this->validApiKeys, true)) {
            $this->logger?->warning('Invalid API key', [
                'ip' => $request->getClientIp(),
                'api_key' => substr($apiKey, 0, 8) . '...',
            ]);
            return true; // Block request
        }

        return false; // Allow request
    }

    public function getStatusCode(): int
    {
        return 401; // Unauthorized
    }
}

Register the custom plugin in your configuration:

plugins:
  - plugin: "App\\Security\\Firewall\\Plugins\\ApiKeyValidator"
    response: block
    weight: -150   # Run before rate limiting
    enable: true
    metadata:
      api_keys:
        - "sk_live_abcd1234567890"
        - "sk_live_efgh0987654321"