symfony/symfony — pull request #11993 by fabpot (2014-09-23 08:36:54+00:00)
Title: [Security] make it possible to override the default success/failure handler

| Q | A
| ------------- | ---
| Bug fix? | no
| New feature? | yes
| BC breaks? | no
| Deprecations? | no
| Tests pass? | yes
| Fixed tickets | #5432, #9272, #10417
| License | MIT
| Doc PR | not yet

Overriding the default success/failure handler of the security firewalls is possible via the `success_handler` and `failure_handler` setting but this approach is not flexible as it does not allow you to get the options/provider key.

To sum up the problem:

* Overriding the default success/failure handler is possible via a service;
* When not overridden, the default success/failure handler gets options and the provider key;
* Those options and the provider key are injected by the factory as they are dynamic (they depend on the firewall and the provider key), so getting those options/provider key is not possible for a custom service that is only configured via the container configuration;
* Extending the default handler does not help as the injection mechanism is only triggered when no custom provider is set;
* Wrapping the default handler is not possible as the service id is dynamic.

... and of course we need to keep BC and make it work for people extending the default handler but also for people just using the interface.

Instead of the current PR, I propose this slightly different approach. It's not perfect, but given the above constraint, I think this is an acceptable trade-of.

So, several use cases:

* Using the default handler (no change);
* Using a custom handler that implements `AuthenticationSuccessHandlerInterface` directly and does not need any options (no change);
* Using a custom handler that needs the options/provider key (that's the new use case this PR supports).

If your custom handler needs the options/provider key, your service must have `security.authentication.success_handler`/`security.authentication.failure_handler` as a parent. Yours handler
does not need to extend the default handler `DefaultAuthentication*Handler`, but doing so helps with the default options. To make it work properly, your custom handler class **must** define a `setProviderKey()` and a `setOptions()` methods. As you can see, this is purely a convention, but with proper documentation, I think it's enough to cover all use cases.