Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Symfony2 security - There is no user provider for user "Ibw\UserBundle\Entity\User"

I'm creating a custom entity provider for my User entity. But when I enter the username and password in the login form I get this exception :

There is no user provider for user "Ibw\UserBundle\Entity\User".

When I switch back to the default Doctrine entity provider, Everything goes well.

First here's my security.yml:

security:
    role_hierarchy:
        ROLE_ADMIN:       ROLE_USER
        ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]

    firewalls:
        dev:
            pattern:  ^/(_(profiler|wdt)|css|images|js)/
            security: false
        secured_area:
            pattern:    ^/
            anonymous: ~
            form_login:
                login_path:   /login
                check_path:   /login_check
                default_target_path:  ibw_job_index
            logout:
                path:   /logout
                target: /

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

    providers:
        default_provider:
            entity: { class: Ibw\UserBundle\Entity\User }

    encoders:
        Ibw\UserBundle\Entity\User: sha512

Here's the Ibw\UserBundle\Entity\User class:

<?php
namespace Ibw\UserBundle\Entity;

use Doctrine\Bundle\DoctrineBundle\Registry;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\Security\Core\User\UserInterface;
use Doctrine\ORM\Mapping as ORM;

/**
 * Class User
 * @ORM\Table(name="users")
 * @ORM\Entity(repositoryClass="Ibw\UserBundle\Repository\UserRepository")
 */
class User implements UserInterface, \Serializable
{
    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="string", length=25, unique=true)
     */
    protected $username;

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

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

    public function __construct(ContainerInterface $container)
    {
        $this->isActive = true;
        $this->salt = md5(uniqid(null, true));
        $this->container = $container;
    }

    public function setUsername($username)
    {
        $this->username = $username;
        return $this;
    }

    public function setPassword($password)
    {
        $encoder = $this->container->get('security.encoder_factory')->getEncoder($this);
        $this->password = $encoder->encodePassword($password, $this->getSalt());
        return $this;
    }

    /**
     * @return Role[] The user roles
     */
    public function getRoles()
    {
        return array('ROLE_ADMIN');
    }

    public function getPassword()
    {
        return $this->password;
    }

    public function getSalt()
    {
        return $this->salt;
    }

    public function getUsername()
    {
        return $this->username;
    }

    public function eraseCredentials()
    {
        // TODO: Implement eraseCredentials() method.
    }

    public function serialize()
    {
        return serialize(array($this->id));
    }

    public function unserialize($serialized)
    {
        list($this->id) = unserialize($serialized);
    }


    public function getId()
    {
        return $this->id;
    }

    public function setSalt($salt)
    {
        $this->salt = $salt;

        return $this;
    }
}

And finally, here's my Ibw\UserBundle\Repository\UserRepository class:

<?php

namespace Ibw\UserBundle\Repository;

use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\NoResultException;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;

class UserRepository extends EntityRepository implements UserProviderInterface
{

    public function loadUserByUsername($username)
    {
        $q = $this->createQueryBuilder('u')
                    ->select('u')
                    ->where('u.username = :username')
                    ->setParameter('username', $username)
                    ->getQuery();

        try
        {
            $user = $q->getSingleResult();
        }
        catch (NoResultException $e)
        {
            $message = sprintf('Unable to find active admin identified by %s', $username);
            throw new UsernameNotFoundException($message, 0, $e);
        }
        return $user;
    }


    public function refreshUser(UserInterface $user)
    {
        $class = get_class($user);
        if(!$this->supportsClass($user))
        {
            $message = sprintf('Unsupported class type : %s', $class);
            throw new UnsupportedUserException($message);
        }

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


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

EDIT:

I tried to define it as a service also, in JobeetBundle/Resources/config/services.yml:

parameters:
    ibw.user.provider.class: Ibw\UserBundle\Repository\UserRepository
    ibw.user.provider.entity.class: Ibw\UserBundle\Entity\User

services:
    ibw.user.provider:
        class: %ibw.user.provider.class%
        factory_service: doctrine
        factory_method: getRepository
        arguments:
            - %ibw.user.provider.entity.class%

And in jobeet/app/config/security.yml:

providers:
    default_provider:
         id: ibw.user.provider
encoders:
    Ibw\UserBundle\Entity\User: sha512

But unfortunately it gives me the exact same error after I post the login form.

like image 560
Rafael Adel Avatar asked Oct 26 '13 01:10

Rafael Adel


1 Answers

I've tracked the problem inside ContextListener class, turned out that it's a typo!

Here in:

public function refreshUser(UserInterface $user)
{
    $class = get_class($user);
    if (!$this->supportsClass($user)) { //This should be $class not $user
        $message = sprintf('Unsupported class type : %s', $class);
        throw new UnsupportedUserException($message);
    }

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

Change that if to:

if (!$this->supportsClass($class)) {}
like image 167
Rafael Adel Avatar answered Oct 25 '22 22:10

Rafael Adel