Symfony 2 - API keys authentication add remember me

667 views Asked by At

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';
}

}
0

There are 0 answers