---
title: "Secure Symfony APIs with API Key Authentication"
description: "Secure your Symfony API using a shared secret."
canonicalUrl: "https://zuplo.com/use-cases/api-key-auth/php/symfony/secure-header"
framework: "Symfony"
language: "PHP"
authStrategy: "shared secret header"
pageType: use-case
---

# Secure Symfony APIs with API Key Authentication

Secure your Symfony API using a shared secret.

## How Zuplo Handles It

Put Zuplo in front of your Symfony backend to authenticate API keys and forward a shared secret header so your origin only accepts traffic from Zuplo.

## Symfony Backend Code

```php
// src/EventSubscriber/SharedSecretSubscriber.php

namespace App\EventSubscriber;

use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class SharedSecretSubscriber implements EventSubscriberInterface
{
    private string $expectedSecret;

    public function __construct(string $sharedSecret)
    {
        if (empty($sharedSecret)) {
            throw new \InvalidArgumentException('Server configuration error: Shared secret is not set.');
        }

        $this->expectedSecret = $sharedSecret;
    }

    public function onKernelRequest(RequestEvent $event): void
    {
        $request = $event->getRequest();

        if (!$request->headers->has('x-shared-secret')) {
            throw new HttpException(401, 'No secret provided');
        }

        $secret = $request->headers->get('x-shared-secret');

        if (!$this->timingSafeEquals($secret, $this->expectedSecret)) {
            throw new HttpException(401, 'Invalid secret');
        }
    }

    private function timingSafeEquals(string $secret, string $expectedSecret): bool
    {
        if (strlen($secret) !== strlen($expectedSecret)) {
            return false;
        }

        return hash_equals($secret, $expectedSecret);
    }

    public static function getSubscribedEvents(): array
    {
        return [
            KernelEvents::REQUEST => 'onKernelRequest',
        ];
    }
}
```

## Example Request

```bash
curl -X GET \
  'https://your-api.zuplo.dev/your-route' \
  -H 'Authorization: Bearer YOUR_API_KEY'
```

## Learn More

- [API Key Authentication on Zuplo](https://zuplo.com/docs/policies/api-key-auth-inbound)
- [JWT Authentication on Zuplo](https://zuplo.com/docs/policies/open-id-jwt-auth-inbound)
- [All use cases](https://zuplo.com/use-cases)
