4

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>
2
  • Are you sure that you should be using the salt that way ? Was the password encoded with that salt ? Commented Nov 30, 2012 at 13:06
  • HI machour I did not encode password with salt. Let me try it, thank you very much! Commented Dec 1, 2012 at 4:46

2 Answers 2

5

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 ))

Sign up to request clarification or add additional context in comments.

1 Comment

this is a great example for newbies to Symfony security to use. I had an issue which you cleared up for me through your example code. Thanks.
2
$factory = $this->get('security.encoder_factory');
$encoder = $factory->getEncoder($user);
$pass = $encoder->encodePassword($user->getPassword(), $user->getSalt());

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.