2

I am following the Symfony book and cookbook recipes and I met problem with simple login form - no matter if entered login/pass are valid, message shows up - 'Invalid credentials'. Users are loaded via Doctrine (User class which implements UserInterface). Source codes :

Security file:

providers:
    user_provider:
      entity:
        class: BakaMainBundle:User

firewalls:

    dev:
        pattern: ^/(_(profiler|wdt)|css|images|js)/
        security: false

    default:
        anonymous: ~
        http_basic: ~
        provider: user_provider
        form_login:
           login_path: /login
           check_path: /login_check
           target_path_parameter: /index/welcome

access_control:
  - { path: ^/admin, roles: ROLE_ADMIN }

encoders:
  Baka\MainBundle\Entity\User:
    algorithm: bcrypt
    cost: 12

Controller :

class SecurityController extends Controller
{
    /**
     * @Route("/login", name="login_route")
     */
    public function loginAction()
    {
        $authUtils = $this->get('security.authentication_utils');
        $error = $authUtils->getLastAuthenticationError();
        $enteredUsername = $authUtils->getLastUsername();

        return $this->render('BakaMainBundle::Login.html.twig',
            array
            (
                'last_username' => $enteredUsername,
                'error' => $error,
                'site' => 'login'
            ));
    }

    /**
     * @Route("/login_check", name="login_check")
     */
    public function loginCheckAction()
    {

    }
}

User repository :

class UserRepository extends \Doctrine\ORM\EntityRepository implements UserProviderInterface
{
    public function loadUserByUsername($username)
    {
        $user = $this->createQueryBuilder('u')
            ->where('u.username = :username OR u.email = :email')
            ->setParameter('username', $username)
            ->setParameter('email', $username)
            ->getQuery()
            ->getOneOrNullResult();

        if ($user === null)
        {
            $returnMessage = sprintf(
                '%s - such username of email adress does not exist in database! Try again with other login data.',
                $username);
            throw new UnsupportedUserException($returnMessage);
        }

        return $user;
    }

    public function refreshUser(UserInterface $user)
    {
        $userClass = get_class($user);
        if (!$this->supportsClass($userClass))
        {
            throw new UnsupportedUserException
            (sprintf('Ops! Something goes wrong. Your user class is not supported by security system.'));
        }

        return $this->find($user->getId());
    }

    public function supportsClass($userclass)
    {
        return $this->getEntityName() === $userclass || is_subclass_of($userclass, $this->getEntityName());
    }

And the form html tag :

<form action="{{ path('login_check') }}" method="post">

Any suggestions? I will be grateful for resolving my problem.

baka1408
  • 433
  • 4
  • 21
  • I would like to add that the Symfony is not really even invoking my 'UserRepository:loadUserByUsername($username)' method, nor query to DB. That's probably the main problem. – baka1408 Nov 15 '15 at 22:34

2 Answers2

1

I think you should use the class namespace instead of the bundle name, when specifying the provider class. Also, you need to specify which property you will be selecting as the "username" from your Entity:

security:
    providers:
        user_provider:
          entity:
            class: Baka\MainBundle\Entity\User
            property: username (this should be an existing property of your entity class)

Also, your User entity needs to implement Symfony\Component\Security\Core\User\UserInterface (or AdvancedUserInterface). Once you're done with that, everything should work if you have users in the database with a properly encoded password.

You should read:

  1. How to Load Security Users from the Database (the Entity Provider) to understand how to load users from the database
  2. Security to get better understanding of how the security component works and how it should be configured.
tftd
  • 16,203
  • 11
  • 62
  • 106
  • I've read both of articles you mentioned and done exactly the same as they suggested. Property: is not included in my code due to usage of custom repository which implements UserProviderInterface - "To finish this (users repository which handles typing email or login instead of plain login), just remove the property key from the user provider in security.yml." Is that possible to point explicitly to that repository class in security.yml? Changing to class namespace made no difference too. – baka1408 Nov 15 '15 at 22:22
  • You need to point the repository in your `Entity`. To see how to do that checkout the official doctrine documentation [here](http://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/reference/working-with-objects.html#custom-repositories). If you don't have a `repositoryClass` set on your `Entity`, that might be the cause of your problem. – tftd Nov 15 '15 at 22:36
  • Yeah, It's already pointed in the Entity - "@ORM\Entity(repositoryClass="Baka\MainBundle\Entity\UserRepository")", but symfony is not invoking query DB method from repository at all. – baka1408 Nov 15 '15 at 22:39
0

I've already identified the reason of issue, and it transpired to be trivial - field which serves as an Encoded Password row in the DB had 15 characters long limit :

    /**
     * @ORM\Column(type="string", length=15)
     */
    protected $password;

And since '12 rounds' bcrypt needs much more digits to represent plain password, Doctrine was forced to shorten encrypted pass so it was impossible to decode later. After changing to suggested by Symfony size the problem has gone :

    /**
     * @ORM\Column(type="string", length=4096)
     */
    protected $password;

Thank you for all support.

baka1408
  • 433
  • 4
  • 21
  • You actually don't need that much characters in your column. I usually set mine to 255, even though with `bcrypt` I don't need more than 60. You can check [this](http://stackoverflow.com/a/5882472/393805) answer for reference. – tftd Nov 16 '15 at 14:23