I am new to Symfony 2 and I need to code customized login via link with hash. I have created user provider and user authenticator using this tutorial - symfony 2 - api key auth.
The login itself works just fine but I am struggling with "remember me" function. You can see the relevant part of the code in the config excerpt in "SECURITY.yml" which results in error message - "RuntimeException: You must configure at least one remember-me aware listener (such as form-login) for each firewall that has remember-me enabled."
security.yml
security:
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
providers:
employee:
id: employee_provider
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
access:
pattern: ^/access$
security: false
main:
pattern: ^/
simple_preauth:
authenticator: employee_authenticator
logout:
path: logout_page
target: forgotten_password_page
invalidate_session: true
remember_me:
key: "%secret%"
lifetime: 3600 # 365 days in seconds
path: /
domain: ~ # Defaults to the current domain from $_SERVER
always_remember_me: true
remember_me_parameter: _remember_me
access_control:
- { path: ^/admin, roles: [ROLE_MASTER] }
EmployeeAuthenticator
class EmployeeAuthenticator implements SimplePreAuthenticatorInterface, AuthenticationSuccessHandlerInterface, AuthenticationFailureHandlerInterface {
protected $router;
protected $httpUtils;
protected $loginCheckUrl;
public function __construct(Router $router, HttpUtils $httpUtils, $loginCheckUrl) {
$this->router = $router;
$this->httpUtils = $httpUtils;
$this->loginCheckUrl = $loginCheckUrl;
}
private function isLoginUrl($request) {
echo rawurldecode($request->getPathInfo());
die();
}
public function createToken(Request $request, $providerKey) {
$this->isLoginUrl($request);
if (!$this->httpUtils->checkRequestPath($request, $this->loginCheckUrl)) {
throw new AuthenticationException("Wrong login page");
}
$apiKey = $request->query->get('apikey');
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();
$employee = $token->getUser();
if ($employee instanceof Employee) {
return new PreAuthenticatedToken(
$employee, $apiKey, $providerKey, $employee->getRoles()
);
}
$employee = $userProvider->loadUserByUsername($apiKey);
if (!$employee) {
throw new AuthenticationException(
sprintf('API Key "%s" does not exist.', $apiKey)
);
}
return new PreAuthenticatedToken(
$employee, $apiKey, $providerKey, $employee->getRoles()
);
}
public function supportsToken(TokenInterface $token, $providerKey) {
return $token instanceof PreAuthenticatedToken && $token->getProviderKey() === $providerKey;
}
public function onAuthenticationFailure(Request $request, AuthenticationException $exception) {
$request->getSession()->getFlashBag()->add('notice', $exception->getMessage());
return new RedirectResponse($this->router->generate('forgotten_password_page'));
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token) {
return new RedirectResponse($this->router->generate('homepage'));
}
}
EmployeeProvider
class EmployeeProvider implements UserProviderInterface {
private $repo;
public function __construct(ObjectManager $em) {
$this->repo = $em->getRepository("MyWebBundle:Employee");
}
public function loadUserByUsername($hash) {
$employee = $this->repo->loadUserByHash($hash);
if ($employee) {
return $employee;
}
throw new UsernameNotFoundException(
sprintf('ApiKey is not exists "%s" does not exist.', $hash)
);
}
public function refreshUser(UserInterface $employee) {
if (!$employee instanceof Employee) {
throw new UnsupportedUserException(
sprintf('Instances of "%s" are not supported.', get_class($employee))
);
}
return $this->repo->findOneById($employee->getId());
}
public function supportsClass($class) {
return $class === 'My\WebBundle\Entity\Employee';
}
}