src/EventSubscriber/InstallAccessSubscriber.php line 43

Open in your IDE?
  1. <?php
  2. namespace App\EventSubscriber;
  3. use App\Entity\User;
  4. use Psr\Log\LoggerInterface;
  5. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  6. use Symfony\Component\HttpKernel\Event\RequestEvent;
  7. use Symfony\Component\HttpKernel\KernelEvents;
  8. use Symfony\Component\Security\Http\Authenticator\Token\PostAuthenticationToken;
  9. /**
  10.  * Steuert den Zugang zu /install/action/{tgaHash}:
  11.  *
  12.  * - Jeder neue tgaHash (neuer QR-Code) löscht die bestehende qrcode-Session,
  13.  *   damit alte Sitzungen nicht wiederverwendet werden können.
  14.  * - Dashboard-Benutzer (onlyQrCodeUser = false) werden automatisch in die
  15.  *   qrcode-Firewall eingeloggt, ohne AppCode eingeben zu müssen.
  16.  * - onlyQrCodeUser muss sich immer mit dem AppCode am QR-Login anmelden.
  17.  */
  18. class InstallAccessSubscriber implements EventSubscriberInterface
  19. {
  20.     private const SESSION_KEY_QRCODE '_security_qrcode';
  21.     private const SESSION_KEY_DEFAULT '_security_default';
  22.     private const SESSION_KEY_INSTALL_HASH '_install_tgaHash';
  23.     private const INSTALL_ENTRY_ROUTE 'install_chose_action';
  24.     private LoggerInterface $logger;
  25.     public function __construct(LoggerInterface $logger)
  26.     {
  27.         $this->logger $logger;
  28.     }
  29.     public static function getSubscribedEvents(): array
  30.     {
  31.         // Nach RouterListener (32) aber vor Security-Firewall (8)
  32.         return [
  33.             KernelEvents::REQUEST => ['onKernelRequest'9],
  34.         ];
  35.     }
  36.     public function onKernelRequest(RequestEvent $event): void
  37.     {
  38.         if (!$event->isMainRequest()) {
  39.             return;
  40.         }
  41.         $request $event->getRequest();
  42.         if ($request->attributes->get('_route') !== self::INSTALL_ENTRY_ROUTE) {
  43.             return;
  44.         }
  45.         if (!$request->hasSession()) {
  46.             return;
  47.         }
  48.         $tgaHash = (string) $request->attributes->get('tgaHash''');
  49.         $session $request->getSession();
  50.         $hasQrcodeSession = (bool) $session->get(self::SESSION_KEY_QRCODE);
  51.         $storedHash = (string) $session->get(self::SESSION_KEY_INSTALL_HASH'');
  52.         // Gleicher tgaHash und gültige qrcode-Session → einfach durchlassen
  53.         // (auch wenn tgaHash leer ist, z.B. nach Logout ohne Hash-Kontext)
  54.         if ($hasQrcodeSession && $storedHash === $tgaHash) {
  55.             $this->logger->debug('InstallAccessSubscriber: same tgaHash, passing through.');
  56.             return;
  57.         }
  58.         // Neuer tgaHash oder abgelaufene Session → alles löschen
  59.         $session->remove(self::SESSION_KEY_QRCODE);
  60.         $session->remove(self::SESSION_KEY_INSTALL_HASH);
  61.         // Prüfen ob Dashboard-Session vorhanden
  62.         $defaultTokenSerialized $session->get(self::SESSION_KEY_DEFAULT);
  63.         if (!$defaultTokenSerialized) {
  64.             $this->logger->debug('InstallAccessSubscriber: no default session, redirecting to QR login.');
  65.             return;
  66.         }
  67.         try {
  68.             $defaultToken unserialize($defaultTokenSerialized);
  69.             if (!is_object($defaultToken) || !method_exists($defaultToken'getUser')) {
  70.                 return;
  71.             }
  72.             $user $defaultToken->getUser();
  73.             if (!$user instanceof User) {
  74.                 return;
  75.             }
  76.             if ($user->getOnlyQrCodeUser()) {
  77.                 $this->logger->debug('InstallAccessSubscriber: onlyQrCodeUser, must use QR login.');
  78.                 return;
  79.             }
  80.             // Dashboard-Benutzer automatisch in qrcode-Firewall einloggen
  81.             $qrcodeToken = new PostAuthenticationToken($user'qrcode'$user->getRoles());
  82.             $session->set(self::SESSION_KEY_QRCODEserialize($qrcodeToken));
  83.             $session->set(self::SESSION_KEY_INSTALL_HASH$tgaHash);
  84.             $this->logger->debug(sprintf(
  85.                 'InstallAccessSubscriber: auto-login user %d (%s) into qrcode firewall for tgaHash=%s',
  86.                 $user->getId(),
  87.                 $user->getEmail(),
  88.                 $tgaHash
  89.             ));
  90.         } catch (\Throwable $e) {
  91.             $this->logger->warning('InstallAccessSubscriber: failed to process token: '.$e->getMessage());
  92.         }
  93.     }
  94. }