Pierstoval
4/20/2017 - 5:39 PM

FormLoginAuthenticator.php

<?php

namespace UserBundle\Security;

final class UsernamePasswordCredentials
{
    /**
     * @var string
     */
    private $usernameOrEmail;

    /**
     * @var string
     */
    private $password;

    /**
     * @param string $usernameOrEmail
     * @param string $password
     */
    public function __construct($usernameOrEmail, $password)
    {
        $this->usernameOrEmail = $usernameOrEmail;
        $this->password = $password;
    }

    /**
     * @return string
     */
    public function getUsernameOrEmail()
    {
        return $this->usernameOrEmail;
    }

    /**
     * @return string
     */
    public function getPassword()
    {
        return $this->password;
    }
}
<?php

namespace UserBundle\Security;

use FOS\UserBundle\Doctrine\UserManager;
use FOS\UserBundle\Security\UserProvider;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Guard\Authenticator\AbstractFormLoginAuthenticator;
use Symfony\Component\Security\Http\Util\TargetPathTrait;
use UserBundle\Entity\User;

final class FormLoginAuthenticator extends AbstractFormLoginAuthenticator
{
    use TargetPathTrait;

    const USERNAME_OR_EMAIL_FORM_FIELD = '_username_or_email';
    const PASSWORD_FORM_FIELD = '_password';
    const SECURITY_REFERER_PARAMETER = '_security_referer';

    const PROVIDER_KEY = 'main'; // Firewall name

    const LOGIN_ROUTE = 'fos_user_security_login';

    const NO_REFERER_ROUTES = [
        self::LOGIN_ROUTE,
        'fos_user_security_check',
        'fos_user_security_register',
        'fos_user_security_logout',
        'fos_user_registration_register',
        'fos_user_registration_check_email',
        'fos_user_registration_confirm',
        'fos_user_registration_confirmed',
        'fos_user_resetting_request',
        'fos_user_resetting_send_email',
        'fos_user_resetting_check_email',
        'fos_user_resetting_reset',
        'fos_user_change_password',
    ];

    /**
     * @var RouterInterface
     */
    private $router;

    /**
     * @var UserPasswordEncoderInterface
     */
    private $encoder;
    /**
     * @var UserManager
     */
    private $userManager;

    public function __construct(UserManager $userManager, RouterInterface $router, UserPasswordEncoderInterface $encoder)
    {
        $this->router = $router;
        $this->encoder = $encoder;
        $this->userManager = $userManager;
    }

    /**
     * {@inheritdoc}
     */
    public function start(Request $request, AuthenticationException $authException = null)
    {
        if ($request->hasSession()) {
            if (in_array($request->attributes->get('_route'), static::NO_REFERER_ROUTES, true)) {
                $this->removeTargetPath($request->getSession(), static::PROVIDER_KEY);
            } else {
                $this->saveTargetPath($request->getSession(), static::PROVIDER_KEY, $request->getUri());
            }
        }

        return parent::start($request, $authException);
    }

    /**
     * {@inheritdoc}
     */
    protected function getLoginUrl()
    {
        return $this->router->generate(static::LOGIN_ROUTE);
    }

    /**
     * {@inheritdoc}
     */
    public function getCredentials(Request $request)
    {
        if ($request->getPathInfo() !== $this->router->generate('fos_user_security_check')) {
            return null;
        }

        $usernameOrEmail = $request->request->get(self::USERNAME_OR_EMAIL_FORM_FIELD);
        $request->getSession()->set(Security::LAST_USERNAME, $usernameOrEmail);
        $password = $request->request->get(self::PASSWORD_FORM_FIELD);

        return new UsernamePasswordCredentials(
            $usernameOrEmail,
            $password
        );
    }

    /**
     * {@inheritdoc}
     *
     * @param UsernamePasswordCredentials $credentials
     * @param UserProvider                $userProvider
     */
    public function getUser($credentials, UserProviderInterface $userProvider)
    {
        return $userProvider->loadUserByUsername($credentials->getUsernameOrEmail());
    }

    /**
     * {@inheritdoc}
     *
     * @param UsernamePasswordCredentials $credentials
     * @param UserInterface|User          $user
     */
    public function checkCredentials($credentials, UserInterface $user)
    {
        if (!$this->encoder->isPasswordValid($user, $credentials->getPassword())) {
            throw new BadCredentialsException();
        }

        $user->setLastLogin(new \DateTime());
        $this->userManager->updateUser($user);

        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
    {
        // if the user hit a secure page and start() was called, this was
        // the URL they were on, and probably where you want to redirect to
        if ($request->hasSession()) {
            $targetPath = $this->getTargetPath($request->getSession(), $providerKey) ?: $this->router->generate('root');
        } else {
            $targetPath = $this->router->generate('root');
        }

        return new RedirectResponse($targetPath);
    }
}