-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
Avoid migration on stateless firewalls #27452
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
Avoid migration on stateless firewalls #27452
Conversation
third option: inject a no-op session strategy in listeners belonging to stateless firewalls |
your first approach requires every listener to set the firewall name as a request attribute before calling the session strategy (which is very easy to miss as it is not part of the explicit API of the session strategy). So IMO, that's not a good approach |
I like the noop-idea, It does not even need to be a new no-op class. A second session migration strategy for stateless firewalls would solve that, which gets a The respective listeners must then get the "stateless migration strategy" injected (instead of https://github.com/weaverryan/symfony/blob/4d5bc448ee2c192c9f4ef964e3006a63a707029e/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml#L178) |
No op is a great idea - I’ll update |
I've just updated to use a noop approach. I think this is solid. Unless anyone sees a major issue, I'll extend this to all of the other listeners & add some tests. For |
Why do we need a noop strategy at all if you can simply not inject a strategy for the same behavior? |
Good question - it’s just a technical work around. The listener service is created in the factory, but the factory doesn’t know whether or not it will live in a stateless firewall. So, it can’t be smart enough (unless I’m missing an idea - very possible) to know if it should or should not inject the session strategy. To work around that, we simply always inject a session strategy, but then in SecurityExtension, we change that session strategy to be a noop for stateless firewalls. It’s a tricky dance. |
@@ -89,6 +89,8 @@ public function load(array $configs, ContainerBuilder $container) | |||
$this->createAuthorization($config, $container); | |||
$this->createRoleHierarchy($config, $container); | |||
|
|||
$container->setParameter('security.authentication.stateless_firewalls', $this->statelessFirewalls); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not needed anymore now :)
This is ready for review. I was very careful, but as I don't believe there are tests on the "factory" classes that build the auth listeners, I appreciate close review. I added a test for |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there is a failure on deps=low, a composer.json needs a tweak somewhere
cheers :)
/** | ||
* Call this method if your authentication token is stored to a session. | ||
* | ||
* @param SessionAuthenticationStrategyInterface $sessionStrategy |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can be removed
/** | ||
* Call this method if your authentication token is stored to a session. | ||
* | ||
* @param SessionAuthenticationStrategyInterface $sessionStrategy |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need for this one :)
/** | ||
* Call this method if your authentication token is stored to a session. | ||
* | ||
* @param SessionAuthenticationStrategyInterface $sessionStrategy |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to be removed
/** | ||
* Call this method if your authentication token is stored to a session. | ||
* | ||
* @param SessionAuthenticationStrategyInterface $sessionStrategy |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
boo
/** | ||
* Call this method if your authentication token is stored to a session. | ||
* | ||
* @param SessionAuthenticationStrategyInterface $sessionStrategy |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:P
Ok, CI is happy! To summarize: the only downside to this PR is on a technical level: the fact that I'm using setter injection everywhere to avoid trying to add this dependency to the constructor (when every class already has optional deps). I've made the setters final, so, if we want to change this in the future, we could decide to do that with less trouble. |
LGTM. I'd just suggest moving the |
Done!
|
@@ -18,7 +18,7 @@ | |||
"require": { | |||
"php": ">=5.3.9", | |||
"ext-xml": "*", | |||
"symfony/security": "^2.8.41|^3.4.11", | |||
"symfony/security": "^2.8.42|^3.4.12", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I bumped both versions - pretty sure that's correct :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would just make the setSessionAuthenticationStrategy()
internal to not introduce any new public api in a patch and just fix our own listeners until this reaches master. 👍 anyways
We could do this, but technically speaking, if anyone uses the components, then they would need to use these methods to migrate the session. So, I'm not sure that we can |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
with minor comment
/** | ||
* Call this method if your authentication token is stored to a session. | ||
* | ||
* @final since version 2.8 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"since version 2.8" should be removed. I don't think we are doing that anywhere else.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do when we want to hint that the @final
has been added after the method has been introduced. i.e. when it's deprecated to extend from it.
Which is not the case here, so yes, this has to be removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
see 5c2b2bb
fe79801
to
cca73bb
Compare
Thank you @weaverryan. |
This PR was squashed before being merged into the 2.8 branch (closes #27452). Discussion ---------- Avoid migration on stateless firewalls | Q | A | ------------- | --- | Branch? | 2.8 | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | Related to #27395 | License | MIT | Doc PR | symfony/symfony-docs#9860 This is a proof-of-concept. Once we agree / are happy, I need to add this to all of the other authentication mechanisms that recently got the session migration code & add tests. Basically, this avoids migrating the session if the firewall is stateless. There were 2 options to do this: A) Make the `SessionAuthenticationStrategy` aware of all stateless firewalls. **This is the current approach** or B) Make each individual authentication listener aware whether or not *its* firewall is stateless. Commits ------- cca73bb Avoid migration on stateless firewalls
…PasswordJsonAuthenticationListener (weaverryan) This PR was squashed before being merged into the 3.4 branch (closes #27556). Discussion ---------- Avoiding session migration for stateless firewall UsernamePasswordJsonAuthenticationListener | Q | A | ------------- | --- | Branch? | 3.4 | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | Related to #27395 | License | MIT | Doc PR | symfony/symfony-docs#9860 This is the sister PR to #27452, which covered all the other authentication listeners. Commits ------- c06f322 Avoiding session migration for stateless firewall UsernamePasswordJsonAuthenticationListener
…gration (weaverryan) This PR was squashed before being merged into the 2.8 branch (closes #27581). Discussion ---------- Fix bad method call with guard authentication + session migration | Q | A | ------------- | --- | Branch? | 2.8 | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no (but there needs to be on master) | Tests pass? | yes | Fixed tickets | #27577 | License | MIT | Doc PR | n/a I messed up #27452 :/. Guard is the one class where the session migration is not on the listener, it's on the handler. The tricky part is that there is only ONE handler (unlike listeners where there is 1 listener per firewall). That means that implementing a session migration strategy that avoids stateless firewalls was a bit more tricky: I could only think to inject a map into `GuardAuthenticationHandler`. On the bright side, this also fixes session migration (not happening) when people call the `authenticateUserAndHandleSuccess()` method directly. On master, we'll need to add a deprecation to make the 3rd argument of `authenticateWithToken()` required - it's optional now for BC. We may also need to re-order the constructor args. I DID test this in a real 2.8 project, to make sure that things were properly wired up. Apologies for not doing that for the other PR. Cheers! Commits ------- 2c0ac93 Fix bad method call with guard authentication + session migration
This is a proof-of-concept. Once we agree / are happy, I need to add this to all of the other authentication mechanisms that recently got the session migration code & add tests.
Basically, this avoids migrating the session if the firewall is stateless. There were 2 options to do this:
A) Make the
SessionAuthenticationStrategy
aware of all stateless firewalls. This is the current approachor
B) Make each individual authentication listener aware whether or not its firewall is stateless.