I have a server sided API developed with Symfony2 and now I try to authenticate.
Therefore I use this firewall and apikey authenticator
firewalls:
login:
pattern: ^/login$
security: false
secured_area:
pattern: ^/
stateless: true
simple_preauth:
authenticator: apikey_authenticator
Api Key Authenticator
namespace Rental\APIBundle\Security;
use Symfony\Component\Security\Core\Authentication\SimplePreAuthenticatorInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
class ApiKeyAuthenticator implements SimplePreAuthenticatorInterface {
protected $userProvider;
public function __construct(ApiKeyUserProvider $userProvider)
{
$this->userProvider = $userProvider;
}
public function createToken(Request $request, $providerKey)
{
//$apiKey = $request->query->get('apikey');
// use test value
$apiKey = "234234234";
if (!$apiKey) {
throw new BadCredentialsException('No API key found');
}
return new PreAuthenticatedToken(
'anon.',
$apiKey,
$providerKey
);
}
public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey)
{
$apiKey = $token->getCredentials();
$username = $this->userProvider->getUsernameForApiKey($apiKey);
if (!$username) {
throw new AuthenticationException(
sprintf('API Key "%s" does not exist.', $apiKey)
);
}
$user = $this->userProvider->loadUserByUsername($username);
return new PreAuthenticatedToken(
$user,
$apiKey,
$providerKey,
$user->getRoles()
);
}
public function supportsToken(TokenInterface $token, $providerKey)
{
return $token instanceof PreAuthenticatedToken && $token->getProviderKey() === $providerKey;
}
}
Up to this point, no problem. Now this class uses methods of the following class
namespace Rental\APIBundle\Security;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\User;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
class ApiKeyUserProvider implements UserProviderInterface {
public function getUsernameForApiKey($apiKey)
{
// Look up the username based on the token in the database
// use test value
$username = "Alex";
return $username;
}
public function loadUserByUsername($username)
{
// return User by Username
}
public function refreshUser(UserInterface $user)
{
// code
}
public function supportsClass($class)
{
return 'Symfony\Component\Security\Core\User\User' === $class;
}
}
My Problems in detail are:
loadUserByUsername needs to find the User entity by searching the Username. But from this Class I do not have access to database. I found examples using a static method User::find() but there is not such a method and the Entity - the model of MVC- does also not have access to database. How do I get the User out of the database ?1. You should use Dependency Injection for it and inject entity manager in your provider.
your_api_key_user_provider:
class: Rental\APIBundle\Security\ApiKeyUserProvider
arguments: ["@doctrine.orm.entity_manager"]
apikey_authenticator:
class: Rental\APIBundle\Security\ApiKeyAuthenticator
arguments: [""@your_api_key_user_provider"]
After that add it in provider:
use Doctrine\ORM\EntityManager;
class ApiKeyUserProvider implements UserProviderInterface {
protected $em;
public function __construct(EntityManager $em){
$this->em = $entityManager;
}
//... Now you have access to database
}
2. Ajax can send cookies and php can work with these requests like with normal and use sessions. Make sure if your request is sending cookies(see Why is jquery's .ajax() method not sending my session cookie?)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With