M0: Skelett + Auth-Grundgerüst (Keycloak-OIDC + API-Token)
- Symfony 7.4 LTS, PHP 8.4, FrankenPHP, SQLite (3-Layer src/UI|Logic|Data) - Auth: manueller OidcClient (Authorization-Code) im UI-Layer, kein Security-Bundle/league; Session-Gate via SessionAuthSubscriber - API-Guard via statischem X-Api-Token (ApiTokenSubscriber); ExceptionSubscriber - UserEntity (Auto-Provision) + Init-Migration - Docker (php:8.4-frankenphp) + compose (essen.ljh31.de, traefik-net external) - SmokeTests (7) grün: Redirect-Fälle, API-Token, Auth-Render, Logout Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\UI\Http\Api;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
||||
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
|
||||
|
||||
/**
|
||||
* `X-Api-Token`-Guard für `/api/*`.
|
||||
*
|
||||
* Erwartet einen statischen Token aus der Umgebungsvariablen `API_TOKEN`
|
||||
* (siehe .env.dist). Bei Fehlerschlag → 401.
|
||||
*
|
||||
* Nur für stateless Consumer (z. B. Home Assistant). Für die Web-Session
|
||||
* ist die SessionAuthSubscriber zuständig.
|
||||
*/
|
||||
final class ApiTokenSubscriber implements EventSubscriberInterface
|
||||
{
|
||||
public function __construct(
|
||||
private readonly string $expectedToken,
|
||||
) {
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
RequestEvent::class => ['handle', 40],
|
||||
];
|
||||
}
|
||||
|
||||
public function handle(RequestEvent $event): void
|
||||
{
|
||||
if (true !== $event->isMainRequest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$request = $event->getRequest();
|
||||
if (!str_starts_with($request->getPathInfo(), '/api/')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$provided = (string) $request->headers->get('X-Api-Token', '');
|
||||
|
||||
if ($this->expectedToken === null
|
||||
|| $this->expectedToken === ''
|
||||
|| !hash_equals($this->expectedToken, $provided)) {
|
||||
throw new UnauthorizedHttpException('api', 'API-Token fehlt oder ist ungültig.');
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user