-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
Automagically flagging requests as stateless breaks valid session access #50715
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
Comments
You could make your solution compatible with that by running your listener between the RouterListener (priority 32) and the FirewallListener (priority 8) instead of using priority 1024. This way, you could check whether the route already added this attribute in the request. |
I second this. IMHO the exception should only be thrown if the code tries to access any authentication related session data (e.g. the token) and not otherwise. Or is the idea that there must never be a session if a firewall or route is declared stateless? |
When a request is declared as stateless, there must not be any usage of the session during the handling of that request. That's the whole point.
If a route declares the When a firewall is marked as stateless, it has 2 impacts:
So if you need a stateless firewall without making the request fully stateless (because you use the session for something else), the solution is to explicitly mark the request as not stateless before the firewall runs (see my previous comment) |
But that is the BC break. Being able to define a request (or route) as stateless is fine, but a stateless firewall should not automatically assume that all requests are stateless (only the authentication is). |
@stof Thanks for clearing that up. 👍 |
In my case, I get the warning
when someone call a route It renders the 404 not found page which use the session (for CSP nonce for instance). Some advice were to put Is there a way to configure different error page for different firewall ? |
If your error pages unconditionally access your session, none of your routes is stateless. 🤷🏻♂️ |
I've always thought that stateless firewall turns off session (you're not able to use session at all during that request). I have a flashback of the blog post that presented this as a performance feature (if stateless means there is no session then let's remove it) |
@javaDeveloperKid Marking a firewall as stateless means that the firewall itself will not use the session anymore. |
Hello, I just wanted to drop in and say that this broke my 5.4 -> 6.4 upgrade. Some of the tests started crashing because of the changed behavior and then another test started behaving weirdly when removing credentials for the next request (token stored in session). Anyway yeah, I'd like this behavior to be optional if possible. |
I'm getting the error when making a DELETE request to API platform. But it appears to actually do the delete (in the database). I do have the symfony/security-bundle installed, but it's really a pretty generic app, symfony new --webapp (Symfony 7), then installing api platform and the symfony tools for security (e.g. make:user). Any suggestions on how to debug this or configuring it differently? curl 'https://127.0.0.1:8012/api/reactions/66' -X 'DELETE' | jq {
"@id": "/api/errors/500",
"@type": "hydra:Error",
"title": "An error occurred",
"detail": "Session was used while the request was declared stateless.",
"status": 500,
"type": "/errors/500",
"trace": [
{
"file": "/home/tac/g/sites/pulse/vendor/symfony/event-dispatcher/Debug/WrappedListener.php",
"line": 116,
"function": "onKernelResponse",
"class": "Symfony\\Component\\HttpKernel\\EventListener\\AbstractSessionListener",
"type": "->"
},
{
"file": "/home/tac/g/sites/pulse/vendor/symfony/event-dispatcher/EventDispatcher.php",
"line": 206,
"function": "__invoke",
"class": "Symfony\\Component\\EventDispatcher\\Debug\\WrappedListener",
"type": "->"
},
{
"file": "/home/tac/g/sites/pulse/vendor/symfony/event-dispatcher/EventDispatcher.php",
"line": 56,
"function": "callListeners",
"class": "Symfony\\Component\\EventDispatcher\\EventDispatcher",
"type": "->"
},
{
"file": "/home/tac/g/sites/pulse/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php",
"line": 127,
"function": "dispatch",
"class": "Symfony\\Component\\EventDispatcher\\EventDispatcher",
"type": "->"
},
{
"file": "/home/tac/g/sites/pulse/vendor/symfony/http-kernel/HttpKernel.php",
"line": 211,
"function": "dispatch",
"class": "Symfony\\Component\\EventDispatcher\\Debug\\TraceableEventDispatcher",
"type": "->"
},
{
"file": "/home/tac/g/sites/pulse/vendor/symfony/http-kernel/HttpKernel.php",
"line": 199,
"function": "filterResponse",
"class": "Symfony\\Component\\HttpKernel\\HttpKernel",
"type": "->"
},
{
"file": "/home/tac/g/sites/pulse/vendor/symfony/http-kernel/HttpKernel.php",
"line": 76,
"function": "handleRaw",
"class": "Symfony\\Component\\HttpKernel\\HttpKernel",
"type": "->"
},
{
"file": "/home/tac/g/sites/pulse/vendor/symfony/http-kernel/Kernel.php",
"line": 185,
"function": "handle",
"class": "Symfony\\Component\\HttpKernel\\HttpKernel",
"type": "->"
},
{
"file": "/home/tac/g/sites/pulse/vendor/symfony/runtime/Runner/Symfony/HttpKernelRunner.php",
"line": 35,
"function": "handle",
"class": "Symfony\\Component\\HttpKernel\\Kernel",
"type": "->"
},
{
"file": "/home/tac/g/sites/pulse/vendor/autoload_runtime.php",
"line": 29,
"function": "run",
"class": "Symfony\\Component\\Runtime\\Runner\\Symfony\\HttpKernelRunner",
"type": "->"
},
{
"file": "/home/tac/g/sites/pulse/public/index.php",
"line": 5,
"function": "require_once"
}
],
"hydra:title": "An error occurred",
"hydra:description": "Session was used while the request was declared stateless."
} |
Yes - this is an annoyance. We're using Google's IAP for authentication which works by passing us signed headers, and so whilst the authentication is stateless, the pages being served are anything but (CSRF tokens, flash bags etc). On the plus side, at least I now know that I can fix it by marking a crap-ton of routes as stateless: false :) (Edit: Actually can just mark all of the routes in question as not stateless en-masse via our attributes.yaml, so it's an easy fix!) |
Got bit by #48044 again. Is there a chance a PR reverting this behavior would be accepted? AFAICT there wouldn’t be any BC break doing so. |
Let's discuss this on a PR indeed. |
IMHO it might be the reason why there was so many PR about "fixing" session access in stateless request. (And my misunderstanding about this feature) |
…he request when firewall is stateless and the attribute is not already set (MatTheCat) This PR was submitted for the 7.2 branch but it was merged into the 6.4 branch instead. Discussion ---------- [SecurityBundle] Revert adding `_stateless` attribute to the request when firewall is stateless and the attribute is not already set | Q | A | ------------- | --- | Branch? | 6.4 | Bug fix? | yes | New feature? | no | Deprecations? | no | Issues | Fix #50715 | License | MIT #40372 was about routes matching both stateful and stateless firewalls: you couldn’t easily configure them as stateless under a stateless firewall only. #48044 fixed it by linking these two attributes: a stateless firewall then implied a stateless request. While it can sound logical, this impacted many projects using the session while authenticating users in a stateless fashion. At last, #49997 allowed to override this behavior by explicitly configuring routes as *not* stateless. This kind of proved that #48044 was a mistake: you cannot tell a request must be stateless only because it matches a stateless firewall. As such, this PR reverts #48044 (and consequently #49997) so that configuring routes as stateless is the developers responsibility alone. It also reopens #40372, but I think this issue should be fixed in an opt-in way (with a new `firewall.stateless.with_routes` boolean configuration in the SecurityBundle e.g.). Commits ------- 47baed9 [SecurityBundle] Revert adding `_stateless` attribute to the request when firewall is stateless and the attribute is not already set
Symfony version(s) affected
6.3.0
Description
There are already several comments on #48044 that indicate that that change is a BC break.
The main problem is that flagging a firewall stateless has never meant that each request that passed that firewall is meant to be stateless. It was merely a way to tell Symfony not to persist the authentication token in the session. The application could still have valid reasons to access the session later on. @tucksaun mentioned CSRF checks and flash messages as examples.
My problem is that #48044 changes the semantics of the firewall attribute
stateless
. This might be a surprise for applications that suddenly raise exceptions on routes that worked perfectly fine with Symfony 6.2. However, this exception is not raised with production settings as far as I can tell, so it's "only" the local dev environment that breaks.I think that this behavior should've been opt-in, maybe with a deprecation layer.
How to reproduce
Declare a stateless firewall and access the session from a controller behind that firewall on a route with no explicit
stateless
setting.Possible Solution
Revert #48044 or make that functionality opt-in.
Additional Context
In my case, my firewall was declared stateless because Symfony was not supposed to manage the session of the application. This is part of a typical temporary authenticator I use when migrating legacy applications to Symfony: I can make Symfony aware of the authenticated user without migrating the login form. If I wouldn't declare the firewall stateless, Symfony would remember the authenticated token which would break the logout mechanism of the legacy app.
I "solved" this in my project by declaring an event listener:
But that only works because we don't make use of that
stateless
route flag at all at the moment.The text was updated successfully, but these errors were encountered: