Symfony 4, Login, how debug the error 'Invalid credentials'?

From symfony 4, I would like create a simple authentication form. I created a User class (the identifier is the email field, not the 'Username', I created a class controller and configured the security.yml file.

I created some users with this static method : (for tests, password by default is 'test')

class User implements \Serializable, UserInterface
{
// ...
  public static function new_alea($email, $isActive = false, $password="test"){
    $instance = new self();
    $instance->isActive = $isActive;
    $instance->email = $email;

    $brypt = new BCryptPasswordEncoder(4);
    $instance->password = $brypt->encodePassword($password, null);

    return $instance;
  }
// ...
}

Its work, there are some user in my database with encrypted passwords.

But when I go to the form page and try to login (fill email/password fields and click on the submit button), I get the error "Invalid credentials."

What this error means ? How/where do I debug my code for find why this error occurs ?

Below, mains part of my code, maybe you'll see an error I didn't see :

the security.yaml file :

security:
    encoders:
        App\Entity\User:
            algorithm: bcrypt
    providers:
        my_db_provider:
            entity:
                class: App\Entity\User
                property: email
    firewalls:
        main:
            provider: my_db_provider
            anonymous: ~
            form_login:
                login_path: login
                check_path: login
    role_hierarchy:
        # ...

the User Entity Class :

class User implements \Serializable, UserInterface
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     * @ORM\Column(type="integer")
     */
    private $id;

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

    /**
     * @ORM\Column(type="string", length=255, unique=true)
     */
    private $email;

    /**
     * @ORM\Column(name="is_active", type="boolean")
     */
    private $isActive;

    private $plainPassword;

    public static function new_alea($email, $isActive = false, $password="coucou"){
        $instance = new self();
        $instance->isActive = $isActive;
        $instance->email = $email;

        $brypt = new BCryptPasswordEncoder(4);
        $instance->password = $brypt->encodePassword($password, null);

        return $instance;
    }

    public function eraseCredentials() {
        $this->plainPassword = null;
    }

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

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

    public function getRoles() {
        return array('ROLE_ADMIN');
    }

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

    public function setPassword($password) {
        $this->password = $password;
    }

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

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

    public function getPlainPassword() {
        return $this->plainPassword;
    }

    public function setPlainPassword($plainPassword): void {
        $this->plainPassword = $plainPassword;
    }

    // and others getters/setters

the login Controller :

class LoginController extends Controller
{
    /**
     * @Route("/login", name="login")
     */
    public function login(Request $request, AuthenticationUtils $authUtils)
    {
        // get the login error if there is one
        $error = $authUtils->getLastAuthenticationError();

        // last username entered by the user
        $email = $authUtils->getLastUsername();

        return $this->render('frontend/log/login.html.twig', array(
            'email' => $email,
            'error' => $error,
        ));
    }
}

And the template login.html.twig file :

{% extends 'base.html.twig' %}

{% block body %}

    {% if error %}
        <div>{{ error.messageKey|trans(error.messageData, 'security') }}</div>
    {% endif %}

    <form action="{{ path('login') }}" method="post">
        <label for="email">Email:</label>
        <input type="text" id="email" name="_email" value="{{ email }}" />

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

{% endblock body %}

Hi i get the same problem today, for me it was i put a restriction of the number of caracter in my string password. So the password was wrong because the encode took too many caracter. So i delete the limit of caracter and it works.

php, From symfony 4, I would like create a simple authentication form. I created a User class (the identifier is the email field, not the 'Username', I created a class  Today I installed Laragon and started a project with Symfony 4.3 to test somethings. Without doing nothing I got the message "An error occurred while loading the web

just output {{ error }} below the "frontend" error message to get the full stacktrace etc...

How to Build a Login Form (Symfony Docs), How to Build a Login Form: If you're looking for the form_login firewall option, see $authenticationUtils): Response { // get the login error if there is one $error If you're successful, the web debug toolbar will tell you who you are and what  The Debug Component WARNING: You are browsing the documentation for Symfony 4.1 which is not maintained anymore . Consider upgrading your projects to Symfony 5.0.

In your login template, add a {{ dump(error) }}. It includes the real error message (which will often suffice), and the whole stack trace if needed. And is more nicely formatted than just {{ error }} :

{% if error %}
    {{  dump(error) }}
    <div>{{ error.messageKey|trans(error.messageData, 'security') }}</div>
{% endif %}

Authentication (The Security Component, Authentication Success and Failure Events; Security Events listen on the security.authentication.failure event, for example, in order to log failed login attempts. Logging: Symfony comes with a minimalist PSR-3 logger: Logger. In conformance with the twelve-factor app methodology, it sends messages starting from the WARNING level to stderr. The minimal log level

I meet a similar problem, I solved by changing my passwords from plain text into encoded version.

# I create users by fixtures
$user->setEmail('admin@admin');
$user->setPassword('admin'); // Wrong

$user->setPassword($this->passwordEncoder->encodePassword(
    $user,
    'admin'
)); // Correct

Official Ref: https://symfony.com/doc/master/bundles/DoctrineFixturesBundle/index.html#accessing-services-from-the-fixtures

Using the form_login Authentication Provider (Symfony Docs), Login CSRF attacks can be prevented using the 1 2 3 4 5 6 7 8 9 10 For example, if the user requested The name of the request attributes used to define the success and failure login  Finishing the Login Form¶. Woh. The make:auth command just did a lot of work for you. But, you're not done yet. First, go to /login to see the new login form. Feel free to customize this however you want.

Use two router paths with the same function name and different label name so that it will moves to your login path when username and password is correct. It will moves to another path when you have invalid password or username.

EXAMPLE:

index:
 path: /
 controller: App\Controller\DefaultController::login

login:
  path: /login
  controller: App\Controller\DefaultController::login

How to Customize Error Pages (Symfony Docs), Overriding Error output for non-HTML formats; Overriding the Default special exception page with lots of debug information to help you discover the root problem: like redirecting the user to the login page, logging them out and other things. First, look at the logs in app/logs depending on your environment — dev.log for development, prod.log for production, etc.. If the code crashes before Symfony has a chance to run, check the logs of your web server — e.g. nginx.

Logging (Symfony Docs), For instance, using Monolog you can configure the logger to do different level) level: debug syslog_handler: type: syslog # log error-level messages and  Accessing and Debugging Symfony Form Errors. I recently saw an old post on StackOverflow called How to get form validation errors after binding the request to the form.It has a lot of answers, most of them are only partially right and a lot are outdated.

Security Configuration Reference (SecurityBundle) (Symfony Docs), values used by your application $ php bin/console debug:config security Defines the URL where the user is redirected after a 403 HTTP error (unless It's used for example to trigger the user authentication when trying to access to By default, you must submit your login form to the check_path URL as a POST request. Thanks for contributing an answer to Stack Overflow! Please be sure to answer the question.Provide details and share your research! But avoid …. Asking for help, clarification, or responding to other answers.

Customizing Errors & Logout > Symfony Security: Beautiful , TRACK. Symfony 4 >. COURSE. Symfony Security: Beautiful Authentication, Powerful Authorization But, if you look at your login template, when we print this error. Another way to look at this is on the web debug toolbar. See this little​  In Symfony 4.4, the new ErrorHandler component replaces the Debug component to remove the Twig dependency and make Symfony exceptions compliant with modern standards.

Comments
  • In the ... section of User are you implementing all the UserInterface methods? Especially getUsername()?
  • Yes, you can see the getUsername() in my paste :)
  • Hmmm. Under security: add "hide_user_not_found: false" That will change the message to either "user not found" or "invalid password". This will verify the problem is with the password and narrow things down a bit.
  • By the way, if you look at the Security Config Docs you will see that the bcrypt encoder has a default cost of 13. That could also be the problem. bcrypt encoder details
  • Ah ha! In your form, name="_email" should be name="_username" or else be overridden under form_login.