'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 %}
Solution 1:[1]
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.
Solution 2:[2]
just output {{ error }} below the "frontend" error message to get the full stacktrace etc...
Solution 3:[3]
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 %}
Solution 4:[4]
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
Solution 5:[5]
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
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Sam |
| Solution 2 | VVN |
| Solution 3 | Pierre-Olivier Vares |
| Solution 4 | jeffsama |
| Solution 5 | emix |

