title: Symfony UserProviderInterface and security provider entity
body: <p>As soon as I remove the <code>property:username</code> from my security.yml I can not login via the form.</p>
  
  <p>Only error seeing:</p>
  
  <pre><code>Authentication request could not be processed due to a system problem.
  </code></pre>
  
  <p>Where could I start debugging? </p>
  
  <p>From <code>app/logs/dev.log</code> I get</p>
  
  <pre><code>security.INFO: Authentication request failed: The Doctrine repository
  "Doctrine\ORM\EntityRepository" must implement UserProviderInterface.
  </code></pre>
  
  <p>What does that mean?</p>
  
  <p>This is what I've got so far following <a href="http://symfony.com/doc/current/cookbook/security/entity_provider.html" rel="nofollow">http://symfony.com/doc/current/cookbook/security/entity_provider.html</a></p>
  
  <p>security.yml</p>
  
  <pre><code>security:
      providers:
          administrators:
              entity: { class:AcmePasswordBundle:User, property: username }
  
      encoders:
          Acme\PasswordBundle\Entity\User:
              algorithm: bcrypt
              #cost: 12
  
      role_hierarchy:
          ROLE_ADMIN: ROLE_USER
          ROLE_SUPER_ADMIN: [ ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH ]
  
      firewalls:
          dev:
              pattern: ^/(_(profiler|wdt|error)|css|images|js)/
              security: false
  
          admin_area:
              anonymous: ~
              pattern: .*
              form_login:
                  login_path: acme_password_login
                  check_path: acme_password_login_check
                  target_path_parameter: _target_path
              logout:
                  path:   /logout
                  target: /
  
      access_control:
          - { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
          - { path: ^/free, roles: IS_AUTHENTICATED_ANONYMOUSLY }
          - { path: ^/, roles: ROLE_ADMIN }
  </code></pre>
  
  <p>Entity\User.php</p>
  
  <pre><code>&lt;?php
  
  namespace Acme\PasswordBundle\Entity;
  
  use Doctrine\ORM\Mapping as ORM;
  use Symfony\Component\Security\Core\User\AdvancedUserInterface;
  
  class User implements AdvancedUserInterface, \Serializable
  {
      /**
       * @var integer
       */
      private $id;
  
      /**
       * @var string
       */
      private $username;
  
      /**
       * @var string
       */
      private $email;
  
      /**
       * @var string
       */
      private $password;
  
      /**
       * @var boolean
       */
      private $isActive;
  
      public function __construct()
      {
          $this-&gt;isActive = true;
      }
  
      /**
       * @return integer
       */
      public function getId()
      {
          return $this-&gt;id;
      }
  
      /**
       * @return string
       */
      public function getUsername()
      {
          return $this-&gt;username;
      }
  
      /**
       * @return string
       */
      public function getEmail()
      {
          return $this-&gt;email;
      }
  
      /**
       * @return string
       */
      public function getPassword()
      {
          return $this-&gt;password;
      }
  
      /**
       * @param string $username
       * @return User
       */
      public function setUsername($username)
      {
          $this-&gt;username = $username;
  
          return $this;
      }
  
      /**
       * @param string $email
       * @return User
       */
      public function setEmail($email)
      {
          $this-&gt;email = $email;
  
          return $this;
      }
  
      /**
       * @param string $password
       * @return User
       */
      public function setPassword($password)
      {
          $this-&gt;password = $password;
  
          return $this;
      }
  
  
      /**
       * (PHP 5 &amp;gt;= 5.1.0)&lt;br/&gt;
       * String representation of object
       * @link http://php.net/manual/en/serializable.serialize.php
       * @return string the string representation of the object or null
       */
      public function serialize()
      {
          return serialize(array(
              $this-&gt;id,
              $this-&gt;username,
              $this-&gt;password,
              // see section on salt below
              // $this-&gt;salt,
          ));
      }
  
      /**
       * (PHP 5 &amp;gt;= 5.1.0)&lt;br/&gt;
       * Constructs the object
       * @link http://php.net/manual/en/serializable.unserialize.php
       * @param string $serialized &lt;p&gt;
       * The string representation of the object.
       * &lt;/p&gt;
       * @return void
       */
      public function unserialize($serialized)
      {
          list (
              $this-&gt;id,
              $this-&gt;username,
              $this-&gt;password,
              // see section on salt below
              // $this-&gt;salt
          ) = unserialize($serialized);
      }
  
      /**
       * Returns the roles granted to the user.
       *
       * &lt;code&gt;
       * public function getRoles()
       * {
       *     return array('ROLE_USER');
       * }
       * &lt;/code&gt;
       *
       * Alternatively, the roles might be stored on a ``roles`` property,
       * and populated in any number of different ways when the user object
       * is created.
       *
       * @return Role[] The user roles
       */
      public function getRoles()
      {
          return array('ROLE_ADMIN');
      }
  
      /**
       * Returns the salt that was originally used to encode the password.
       *
       * This can return null if the password was not encoded using a salt.
       *
       * @return string|null The salt
       */
      public function getSalt()
      {
          return null;
      }
  
      /**
       * Removes sensitive data from the user.
       *
       * This is important if, at any given point, sensitive information like
       * the plain-text password is stored on this object.
       */
      public function eraseCredentials()
      {
          // TODO: Implement eraseCredentials() method.
      }
  
      /**
       * Checks whether the user's account has expired.
       *
       * Internally, if this method returns false, the authentication system
       * will throw an AccountExpiredException and prevent login.
       *
       * @return bool true if the user's account is non expired, false otherwise
       *
       * @see AccountExpiredException
       */
      public function isAccountNonExpired()
      {
          return true;
      }
  
      /**
       * Checks whether the user is locked.
       *
       * Internally, if this method returns false, the authentication system
       * will throw a LockedException and prevent login.
       *
       * @return bool true if the user is not locked, false otherwise
       *
       * @see LockedException
       */
      public function isAccountNonLocked()
      {
          return true;
      }
  
      /**
       * Checks whether the user's credentials (password) has expired.
       *
       * Internally, if this method returns false, the authentication system
       * will throw a CredentialsExpiredException and prevent login.
       *
       * @return bool true if the user's credentials are non expired, false otherwise
       *
       * @see CredentialsExpiredException
       */
      public function isCredentialsNonExpired()
      {
          return true;
      }
  
      /**
       * Checks whether the user is enabled.
       *
       * Internally, if this method returns false, the authentication system
       * will throw a DisabledException and prevent login.
       *
       * @return bool true if the user is enabled, false otherwise
       *
       * @see DisabledException
       */
      public function isEnabled()
      {
          return $this-&gt;isActive;
      }
  }
  </code></pre>
  
  <p>Entity\UserRepository.php</p>
  
  <pre><code>&lt;?php
  
  namespace Acme\PasswordBundle\Entity;
  
  use Symfony\Component\Security\Core\User\UserInterface;
  use Symfony\Component\Security\Core\User\UserProviderInterface;
  use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
  use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
  use Doctrine\ORM\EntityRepository;
  use Doctrine\ORM\NoResultException;
  
  class UserRepository extends EntityRepository implements UserProviderInterface
  {
  
      /**
       * Loads the user for the given username.
       *
       * This method must throw UsernameNotFoundException if the user is not
       * found.
       *
       * @param string $username The username
       *
       * @return UserInterface
       *
       * @see UsernameNotFoundException
       *
       * @throws UsernameNotFoundException if the user is not found
       */
      public function loadUserByUsername($username)
      {
          $q = $this
              -&gt;createQueryBuilder('u')
              -&gt;where('u.username = :username OR u.email = :email')
              -&gt;setParameter('username', $username)
              -&gt;setParameter('email', $username)
              -&gt;getQuery();
  
          try {
              // The query::getSingleResult() method throws an exception
              // if there is no record matching the criteria.
              $user = $q-&gt;getSingleResult();
          } catch (NoResultException $e) {
              $message = sprintf(
                  'Unable to find an active admin AcmePasswordBundle:User object identified by "%s".',
                  $username
              );
              throw new UsernameNotFoundException($message, 0, $e);
          }
          return $user;
      }
  
      /**
       * Refreshes the user for the account interface.
       *
       * It is up to the implementation to decide if the user data should be
       * totally reloaded (e.g. from the database), or if the UserInterface
       * object can just be merged into some internal array of users / identity
       * map.
       *
       * @param UserInterface $user
       *
       * @return UserInterface
       *
       * @throws UnsupportedUserException if the account is not supported
       */
      public function refreshUser(UserInterface $user)
      {
          $class = get_class($user);
          if(!$this-&gt;supportsClass($class)) {
              throw new UnsupportedUserException(
                  sprintf(
                      'Instances of "%s" are not supported.',
                      $class
                  )
              );
          }
          return $this-&gt;find($user-&gt;getId());
      }
  
      /**
       * Whether this provider supports the given user class.
       *
       * @param string $class
       *
       * @return bool
       */
      public function supportsClass($class)
      {
          return $this-&gt;getEntityName() === $class
              || is_subclass_of($class, $this-&gt;getEntityName());
      }
  
  }
  </code></pre>
  
  <p>Thanks for advices and suggestions!</p>