fix: leave access denials on stateless firewalls to the plain 401/403

This commit is contained in:
fromme committed 2026-10-08 11:46:59 +02:00
1 parent 1b4384e3f3
commit 754360605c
2 files changed
+23 -4

No files matched your search

+9 -3
View File
@@ -63,13 +63,19 @@ class AccessDeniedListener implements EventSubscriberInterface
return;
}
/** @var Session $session */
$session = $request->getSession();
$this->authLogger->warning('Access denied', [
'uri' => $request->getRequestUri(),
]);
// API clients (/api, /mcp, webhooks) get the plain 401/403. A flash would start a
// session nobody reads and send a cookie, and a redirect would answer with HTML.
if (true === $this->security->getFirewallConfig($request)?->isStateless()) {
return;
}
/** @var Session $session */
$session = $request->getSession();
if (null === $this->security->getUser()) {
$session->getFlashBag()->add('info', 'Bitte melde dich an.');
@@ -11,6 +11,7 @@ use App\Security\DefaultRouteResolver;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Bundle\SecurityBundle\Security\FirewallConfig;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\Session;
@@ -83,6 +84,17 @@ class AccessDeniedListenerTest extends TestCase
self::assertSame([], $this->session($request)->getFlashBag()->all());
}
public function testStatelessFirewallsGetThePlainResponseWithoutStartingASession(): void
{
foreach ([null, new User('[email protected]')] as $user) {
$request = $this->request('/mcp');
$event = $this->dispatch($request, $user, stateless: true);
self::assertFalse($event->hasResponse());
self::assertFalse($this->session($request)->isStarted());
}
}
/**
* @param array<string, string> $server
*/
@@ -102,10 +114,11 @@ class AccessDeniedListenerTest extends TestCase
return $session;
}
private function dispatch(Request $request, ?UserInterface $user): ExceptionEvent
private function dispatch(Request $request, ?UserInterface $user, bool $stateless = false): ExceptionEvent
{
$security = $this->createStub(Security::class);
$security->method('getUser')->willReturn($user);
$security->method('getFirewallConfig')->willReturn(new FirewallConfig($stateless ? 'mcp' : 'main', 'security.user_checker', stateless: $stateless));
$resolver = $this->createStub(DefaultRouteResolver::class);
$resolver->method('resolveUrl')->willReturn('/admin/dashboard');