Before Symfony 2.8 SimplePreAuthenticatorInterface
was in the following namespace Symfony\Component\Security\Core\Authentication\SimplePreAuthenticatorInterface
It have been deprecated in 2.8 and changed in 3.0 to Symfony\Component\Security\Http\Authentication\SimplePreAuthenticatorInterface
now I'm writing a bundle which must work either in symfony 2.7 and symfony 3.0 it is an api authenticator bundle for a private use.
I would like to write a factory for it which checks interface existance
example from FosUserBundle
if (interface_exists('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface')) {
$tokenStorage = $this->get('security.token_storage');
} else {
$tokenStorage = $this->get('security.context');
}
but my class which implements this interface is a service in DI and symfony firewall directly uses this.
My question is how could I make this abstraction in a manner of best practise and logical.
AccessTokenAuthenticator Class :
<?php
namespace MyCompany\SBundle\Security;
// this usage for before symfony 2.8
use Symfony\Component\Security\Core\Authentication\SimplePreAuthenticatorInterface;
/**
* Class AccessTokenAuthenticator
*/
class AccessTokenAuthenticator implements SimplePreAuthenticatorInterface
{
services.yml
# Authentication
mycompany_security.security.accesstoken_authenticator:
class: MyCompany\SBundle\Security\AccessTokenAuthenticator
arguments: ["@mycompany_security.security.accesstoken_userprovider"]
Firewall Configuration :
secure_area:
pattern: ^/
stateless: true
simple_preauth:
authenticator: mycompany_security.security.accesstoken_authenticator
My exact problem is even if I define two classes which are identical each other but the implementation namespace different even how could I give this to firewall ? How this can be abstracted from firewall ?
Any help would be appreciated.
OK I find the answer,
When I focus the service container and security.yml firewall configurations. I just forget, my firewall configuration can be different from symfony2 and symfony3 application.
In that manner I can would define a BaseAccessTokenAuthenticator
and AccessTokenAuthenticator
for either PreSymfony28 and Symfony30 and then I will put all the logic inside BaseAccessTokenAuthenticator
and AccessTokenAuthenticator would be multiple and there would be 2 different service. One for symfony2.7 firewall configuration one for symfony3.0.
Base Class :
<?php
namespace MyCompany\SBundle\Security;
/**
* Abstract Class BaseAccessTokenAuthenticator
*/
abstract class BaseAccessTokenAuthenticator
{
public function createToken(Request $request, $providerKey)
{
// Implementation
}
public function authenticateToken(
TokenInterface $token,
UserProviderInterface $userProvider,
$providerKey
) {
// Implementation.
}
public function supportsToken(TokenInterface $token, $providerKey)
{
// Implementation.
}
}
Symfony 3.0 class :
<?php
namespace MyCompany\SBundle\Security;
use Symfony\Component\Security\Http\Authentication\SimplePreAuthenticatorInterface;
/**
* Class AccessTokenAuthenticatorSf30
*/
class AccessTokenAuthenticatorSf30 extends BaseAccessTokenAuthenticator implements SimplePreAuthenticatorInterface
{
}
Pre Symfony 2.8 class :
<?php
namespace MyCompany\SBundle\Security;
use Symfony\Component\Security\Core\Authentication\SimplePreAuthenticatorInterface;
/**
* Class AccessTokenAuthenticatorPreSf28
*/
class AccessTokenAuthenticatorPreSf28 extends BaseAccessTokenAuthenticator implements SimplePreAuthenticatorInterface
{
}
Services :
# Authentication
mycompany.security.accesstoken_authenticator_pre_sf28:
class: MyCompany\SBundle\Security\AccessTokenAuthenticatorPreSf28
arguments: ["@mycompany.security.accesstoken_userprovider"]
# Authentication
mycompany.security.accesstoken_authenticator_sf30:
class: MyCompany\SBundle\Security\AccessTokenAuthenticatorSf30
arguments: ["@mycompany.security.accesstoken_userprovider"]
wide application firewall for symfony =< 2.8 :
simple_preauth:
authenticator: mycompany.security.accesstoken_authenticator_sf28
wide application firewall for symfony >= 2.8 :
simple_preauth:
authenticator: mycompany.security.accesstoken_authenticator_sf30
This is probably non-PSR compliant but will work (probably).
File AccessTokenAuthenticator.php
if (interface_exists('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface')) {
class AccessTokenAuthenticator implements \Symfony\Component\Security\Core\Authentication\SimplePreAuthenticatorInterface { }
} else {
class AccessTokenAuthenticator implements \Symfony\Component\Security\Http\Authentication\SimplePreAuthenticatorInterface { }
}
Autoloading should still pick it up.