Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Session was used while the request was declared stateless #1219

Closed
a-lebailly opened this issue Apr 25, 2024 · 6 comments
Closed

Session was used while the request was declared stateless #1219

a-lebailly opened this issue Apr 25, 2024 · 6 comments

Comments

@a-lebailly
Copy link

a-lebailly commented Apr 25, 2024

I have a problem with Symfony 7.0.6 and LexikJWTAuthenticationBundle 2.20.3.

Introduction

My application is divided into 3 parts (/bundles) :

  • Front (everything related to classic users)
  • Admin (everything related to admin users)
  • Api (everything related to the API)

I use LexikJWTAuthenticationBundle for the API authentication.


Issue

I have a custom provider to authenticate API users.
When I try to access a public route in my API (for example /api/login), I don't get any error and the API returns a JWT token. If I try to access a private route in my API (a route that needs authentication) with an invalid JWT Token, I get this response :

{
    "code": 401,
    "message": "Invalid JWT Token"
}

Finally, when I try to access a private route in my API with a valid JWT Token, I get this error :

Session was used while the request was declared stateless.

Some issues on StackOverflow or here mention that this problem comes from calling getUser() from the Request when the firewall is stateless.

The stack trace doesn't mention any custom Listener where I call getUser(), but if I put a dd(...), my app stops on one of them (it's not important but I don't understand it either).

The catched exception is UnexpectedSessionUsageException who is throw in vendor/symfony/http-kernel/EventListener/AbstractSessionListener.php:224 :

if ($this->debug) {
  throw new UnexpectedSessionUsageException('Session was used while the request was declared stateless.');
}

I don't get that point... What is the relation between calling getUser() from the Request and the debug environment value ?

If I change my .env file to set APP_DEBUG=false, I no longer have the error.

Could this have anything to do with the Symfony Profiler ?


Files

Below, my security.yaml :

# config/packages/security.yaml
security:

  # ...

  providers:
    api_provider:
      id: App\Api\Provider\UserProvider

  # ...

  firewalls:
    api:
      pattern: ^/api
      stateless: true
      provider: api_provider
      jwt: ~

Below, my UserProvider :

<?php

declare(strict_types=1);

namespace App\Api\Provider;

use Exception;
use App\Core\Entity\User;
use App\Core\Repository\UserRepository;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;

use function is_subclass_of;

readonly class UserProvider implements UserProviderInterface
{
    public function __construct(private UserRepository $userRepository)
    {
    }

    public function refreshUser(UserInterface $user): UserInterface
    {
        throw new Exception('Cannot refresh user in a stateless application.');
    }

    public function supportsClass(string $class): bool
    {
        return User::class === $class || is_subclass_of($class, User::class);
    }

    public function loadUserByIdentifier(string $identifier): UserInterface
    {
        return $this->userRepository->findOneByUrai($identifier);
    }
}
@a-lebailly
Copy link
Author

The related StackTrace :

Symfony\Component\HttpKernel\Exception\UnexpectedSessionUsageException:
Session was used while the request was declared stateless.

  at vendor/symfony/http-kernel/EventListener/AbstractSessionListener.php:224
  at Symfony\Component\HttpKernel\EventListener\AbstractSessionListener->onKernelResponse()
     (vendor/symfony/event-dispatcher/Debug/WrappedListener.php:116)
  at Symfony\Component\EventDispatcher\Debug\WrappedListener->__invoke()
     (vendor/symfony/event-dispatcher/EventDispatcher.php:206)
  at Symfony\Component\EventDispatcher\EventDispatcher->callListeners()
     (vendor/symfony/event-dispatcher/EventDispatcher.php:56)
  at Symfony\Component\EventDispatcher\EventDispatcher->dispatch()
     (vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php:127)
  at Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher->dispatch()
     (vendor/symfony/http-kernel/HttpKernel.php:211)
  at Symfony\Component\HttpKernel\HttpKernel->filterResponse()
     (vendor/symfony/http-kernel/HttpKernel.php:199)
  at Symfony\Component\HttpKernel\HttpKernel->handleRaw()
     (vendor/symfony/http-kernel/HttpKernel.php:76)
  at Symfony\Component\HttpKernel\HttpKernel->handle()
     (vendor/symfony/http-kernel/Kernel.php:185)
  at Symfony\Component\HttpKernel\Kernel->handle()
     (vendor/symfony/runtime/Runner/Symfony/HttpKernelRunner.php:35)
  at Symfony\Component\Runtime\Runner\Symfony\HttpKernelRunner->run()
     (vendor/autoload_runtime.php:29)
  at require_once('/var/www/app/vendor/autoload_runtime.php')
     (public/index.php:7)              

@Seb33300
Copy link
Contributor

Seb33300 commented May 2, 2024

You should check in your project if you try to read the session somewhere ->getSession() (maybe in a listener?)

@Seb33300
Copy link
Contributor

Seb33300 commented May 2, 2024

Related to #1143

@a-lebailly
Copy link
Author

You should check in your project if you try to read the session somewhere ->getSession() (maybe in a listener?)
Related to #1143

Thank you for your reply. I hadn't seen this issue but I understood the same thing.
I know it's related to a custom Listener, but my application has a lot of Listener and I can't find which Listener is causing this problem, event with xDebug 🤯...
The Profiler, Logs or other development tools haven't shown me the full stack trace...

@a-lebailly
Copy link
Author

But yes, I can close this issue.
This bug does not come from the package, but from the design of the application.

If you call a custom listener that uses Session and this listener is called before an API Route that requires a JWT Token, it will throw the following exception :

Session was used while the request was declared stateless.

So, you have two options :

  1. Change the value of the stateless parameter to false in the security.yaml config file. But this option to false will save the JWT Token in the session (and it's not recommended for an API). Related to the Symfony Documentation
  2. Find the custom Listenerand configure it so that it is not called by routes requiring a JWT Token.

@Seb33300
Copy link
Contributor

Seb33300 commented May 3, 2024

On my side, I ended by hacking Symfony code to add the path in the log message so I can easily find what was triggering them.

And I found another bug in Symfony on logout that can trigger that session error, the PR is still under review here:
symfony/symfony#54742

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants