symfony2 custom User Provider prints "Bad credentials"

authentication, symfony

Solution

Has found answer to my question. Thanks to machour for responce. The problem was with SALT. So I updated the User.php class to

public function getSalt()
    {
        return '';
    }

Then it logs in correctly or I should have encoded password with salt to successfully login. If one know how to do it, please write it as answer, YAHOO ))

Problem

I always get message: "Bad credentials" when I try to login in symfony2. I am doing this based to http://symfony.com/doc/current/cookbook/security/custom_provider.html. Please help me to figure out, where the problem is? Thanks in advance. security.yml looks like this ``` security: encoders: Zags\UserBundle\Security\User\User: plaintext role_hierarchy: ROLE_ADMIN: ROLE_USER ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH] providers: webservice: id: zags_user_provider firewalls: dev: pattern: ^/(_(profiler|wdt)|css|images|js)/ security: false login_firewall: pattern: ^/login$ anonymous: ~ secured_area: pattern: ^/ anonymous: ~ form_login: login_path: /login check_path: /login_check #anonymous: ~ #http_basic: # realm: "Secured Demo Area" access_control: - { path: ^/gender_type, roles: ROLE_USER } #- { path: ^/_internal/secure, roles: IS_AUTHENTICATED_ANONYMOUSLY, ip: 127.0.0.1 } ``` I have added these lines to routing.yml ``` login: pattern: /login defaults: { _controller: ZagsUserBundle:Security:login } login_check: pattern: /login_check ``` User.php class looks like this ``` <?php namespace Zags\UserBundle\Security\User; use Symfony\Component\Security\Core\User\UserInterface; class User implements UserInterface { private $username; private $password; private $salt; private $roles; public function __construct($username, $password, $salt, array $roles) { $this->username = $username; $this->password = $password; $this->salt = $salt; $this->roles = $roles; } public function getRoles() { return $this->roles; } public function getPassword() { return $this->password; } public function getSalt() { return $this->salt; } public function getUsername() { return $this->username; } public function eraseCredentials() { } public function equals(UserInterface $user) { return $user->getUsername() === $this->username; } } ?> ``` So this is my UserProvider.php class ``` <?php namespace Zags\UserBundle\Security\User; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Core\Exception\UnsupportedUserException; class UserProvider implements UserProviderInterface { public function loadUserByUsername($username) { // make a call to your webservice here $userData = array("username" => "latysh", "password" => "123", "salt" => "123", "roles" => array('ROLE_USER')); // pretend it returns an array on success, false if there is no user if ($userData) { $username = $userData['username']; $password = $userData['password']; $salt = $userData['salt']; $roles = $userData['roles']; // ... return new User($username, $password, $salt, $roles); } throw new UsernameNotFoundException(sprintf('Username "%s" does not exist.', $username)); } public function refreshUser(UserInterface $user) { if (!$user instanceof User) { throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_class($user))); } return $this->loadUserByUsername($user->getUsername()); } public function supportsClass($class) { return $class === 'Zags\UserBundle\Security\User\User'; } } ?> ``` and services.yml looks like this ``` parameters: zags_user_provider.class: Zags\UserBundle\Security\User\UserProvider services: zags_user_provider: class: "%zags_user_provider.class%" ``` SecurityController.php ``` <?php namespace Zags\UserBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\Security\Core\SecurityContext; class SecurityController extends Controller { public function loginAction() { $request = $this->getRequest(); $session = $request->getSession(); // get the login error if there is one if ($request->attributes->has(SecurityContext::AUTHENTICATION_ERROR)) { $error = $request->attributes->get(SecurityContext::AUTHENTICATION_ERROR); } else { $error = $session->get(SecurityContext::AUTHENTICATION_ERROR); $session->remove(SecurityContext::AUTHENTICATION_ERROR); } return $this->render('ZagsUserBundle:Security:login.html.twig', array( // last username entered by the user 'last_username' => $session->get(SecurityContext::LAST_USERNAME), 'error' => $error, )); } } ?> ``` and login.html.twig ``` {% if error %} <div>{{ error.message }}</div> {% endif %} <form action="{{ path('login_check') }}" method="post"> <label for="username">Username:</label> <input type="text" id="username" name="_username" value="{{ last_username }}" /> <label for="password">Password:</label> <input type="password" id="password" name="_password" /> {# If you want to control the URL the user is redirected to on success (more details below) <input type="hidden" name="_target_path" value="/account" /> #} <button type="submit">login</button> </form> ```

Original source