Home > Software design >  password is empty on login symfony 5.3
password is empty on login symfony 5.3

Time:06-27

Error in view : Symfony\Component\Security\Core\Exception\BadCredentialsException: The presented password cannot be empty.

in log: security.DEBUG: Authenticator does not support the request. {"firewall_name":"main","authenticator":"App\Security\AppCustomAuthenticator"} []

and: security.DEBUG: Authenticator does not support the request. {"firewall_name":"main","authenticator":"Symfony\Component\Security\Http\Authenticator\FormLoginAuthenticator"} []

in security.yaml:

security:
# https://symfony.com/doc/current/security/experimental_authenticators.html
enable_authenticator_manager: true
# https://symfony.com/doc/current/security.html#c-hashing-passwords
password_hashers:
    App\Entity\User:
        algorithm: auto
    Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface:
        algorithm: auto

# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
providers:
    # used to reload user from session & other features (e.g. switch_user)
    app_user_provider:
        entity:
            class: App\Entity\User
            property: email
    # used to reload user from session & other features (e.g. switch_user)
    # used to reload user from session & other features (e.g. switch_user)
firewalls:
    dev:
        pattern: ^/(_(profiler|wdt)|css|images|js)/
        security: false
    main:
        lazy: true
        provider: app_user_provider
        #provider: users_in_memory
        custom_authenticators:
            - App\Security\AppCustomAuthenticator
        form_login:
            # "login" is the name of the route created previously
            login_path: login
            check_path: login
            failure_path: login
            enable_csrf: true
            username_parameter: _email
            password_parameter: _password
            target_path_parameter: go_to
        logout:
            path: logout
            # where to redirect after logout
            target: Accueil
            invalidate_session: true
        # activate different ways to authenticate
        # https://symfony.com/doc/current/security.html#firewalls-authentication
        # https://symfony.com/doc/current/security/impersonating_user.html
        # switch_user: true
        ##ad a remember me option aut login
        remember_me:
            secret: '%kernel.secret%'
            # ...
            always_remember_me: true
# Easy way to control access for large sections of your site
# Note: Only the *first* access control that matches will be used
access_control:
    # - { path: ^/admin, roles: ROLE_ADMIN }
    # - { path: ^/profile, roles: ROLE_USER }

in controller:

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;

class SecurityController extends AbstractController
{
   /**
     * @Route("/login", name="login", methods={"GET","POST"})]
     * 
     */
    public function index(AuthenticationUtils $authenticationUtils): Response
      {
        // get the login error if there is one
        $error = $authenticationUtils->getLastAuthenticationError();

        // last username entered by the user
        $lastUsername = $authenticationUtils->getLastUsername();

        return $this->render('security/login.html.twig', [
            'controller_name' => 'LoginController',
            'last_email' => $lastUsername,
            'error'         => $error,
        ]);
    }
    /**
     * @Route("/logout", name="logout", methods={"GET"})
     */
    public function logout(): void//?Response
    {

    }
}

in UserRepository:

        namespace App\Repository;
        
        use App\Entity\User;
        use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
        use Doctrine\Persistence\ManagerRegistry;
        use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
        use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
        use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
        
        /**
         * @method User|null find($id, $lockMode = null, $lockVersion = null)
         * @method User|null findOneBy(array $criteria, array $orderBy = null)
         * @method User[]    findAll()
         * @method User[]    findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
         */
        class UserRepository extends ServiceEntityRepository implements PasswordUpgraderInterface
        {
            public function __construct(ManagerRegistry $registry)
            {
                parent::__construct($registry, User::class);
            }
        
            /**
             * Used to upgrade (rehash) the user's password automatically over time.
             */
            public function upgradePassword(PasswordAuthenticatedUserInterface $user, string $newHashedPassword): void
            {
                if (!$user instanceof User) {
                    throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', \get_class($user)));
                }
        
                $user->setPassword($newHashedPassword);
                $this->_em->persist($user);
                $this->_em->flush();
            }
        
            // /**
            //  * @return User[] Returns an array of User objects
            //  */
            /*
            public function findByExampleField($value)
            {
                return $this->createQueryBuilder('u')
                    ->andWhere('u.exampleField = :val')
                    ->setParameter('val', $value)
                    ->orderBy('u.id', 'ASC')
                    ->setMaxResults(10)
                    ->getQuery()
                    ->getResult()
                ;
            }
            */
        
        public function findOneBySomeField($value): ?User
        {
            return $this->createQueryBuilder('u')
                ->andWhere('u.exampleField = :val')
                ->setParameter('val', $value)
                ->getQuery()
                ->getOneOrNullResult()
            ;
        }
    }

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

% use "base.html.twig" with stylesheets as style_parent %}

{% block stylesheets %}
{{ block('style_parent') }}
    <link rel="stylesheet" href="{{ asset('css/login-form.css') }}">    
{% endblock %}

{% block title %}Se logger pour obtenir toutes les fonctionnalités{% endblock %}

{% block body %}

    {% use "background_menu.html.twig" with header as parent_menu %}
    {% block header %}
        {{ block('parent_menu') }}
    {% endblock %}

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

     {% if app.user %}
        <div >
            {{ app.user.email }}, Vous êtes Connecté, <a href="{{ path('logout') }}" >Déconnexion</a>
        </div>
    {% endif %}

    <form action="{{ path('login') }}" method="post">
    <h1 >Connectez-vous</h1>
    <div >
        <div >
            <label for="email">Email:</label>
            <input   type="text" id="email" name="_email" value="{% if last_email %}{{ last_email }}{% endif %}"/>
        </div>
        <div >
            <label for="password">Password:</label>
            <input  type="password" id="_password" name="password"/>
        </div>
        {% if error %}
        <div >{{ error }}</div>
        {% endif %}
        {# If you want to control the URL the user is redirected to on success #}
        <input type="hidden" name="_target_path" value="{{ path('Accueil') }}"/>
        <div >
            <a href="{{ path('register')}}" >S'inscrire</a>&nbsp;ou&nbsp;<a href="#" >Mot de Passe oublié</a>
        </div>
        <input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}">
        <input type="hidden" name="go_to" value="{{ path('Accueil') }}"/>
        <button type="submit" name="login">Connection</button>
    </div>
    </form>
    <br><br><br><br>
    {% use "footer.html.twig" with footer as parent_footer %}
    {% block footer %}
        {{ block('parent_footer') }}
    {% endblock %}
{% endblock %}

in AppCustomAuthenticator:

// src/Security/AppCustomAuthenticator.php

namespace App\Security;

use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
use Symfony\Component\Security\Http\Authenticator\AbstractAuthenticator;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface;
use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;

class AppCustomAuthenticator extends AbstractAuthenticator
{
    private $router;

    public function __construct(UrlGeneratorInterface $router)
    {
        $this->router = $router;
    }
    /**
     * Called on every request to decide if this authenticator should be
     * used for the request. Returning `false` will cause this authenticator
     * to be skipped.
     */
    public function supports(Request $request): ?bool
    {
        return $request->headers->has('X-AUTH-TOKEN');
    }

    public function authenticate(Request $request): PassportInterface
    {
        $apiToken = $request->headers->get('X-AUTH-TOKEN');
        if (null === $apiToken) {
            // The token header was empty, authentication fails with HTTP Status
            // Code 401 "Unauthorized"
            throw new CustomUserMessageAuthenticationException('No API token provided');
        }

        return new SelfValidatingPassport(new UserBadge($apiToken));
    }

    public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
    {
        // on success, let the request continue
        //return null;
        return new RedirectResponse($this->router->generate('Accueil'));
    }

    public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
    {
        $data = [
            // you may want to customize or obfuscate the message first
            'message' => strtr($exception->getMessageKey(), $exception->getMessageData())

            // or to translate this message
            // $this->translator->trans($exception->getMessageKey(), $exception->getMessageData())
        ];

        return new JsonResponse($data, Response::HTTP_UNAUTHORIZED);
    }
}

CodePudding user response:

I changed the input password for:

<input  type="password" id="_password" name="_password"/>

now i have in log:

security.DEBUG: Authenticator does not support the request. {"firewall_name":"main","authenticator":"App\\Security\\AppCustomAuthenticator"} []

and the error twig:

Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException: Invalid CSRF token

CodePudding user response:

Now it was your answer:

<input  type="password" id="_password" name="_password"/>

<input   type="text" id="_email" name="_email" value="{% if last_email %}{{ last_email }}{% endif %}"/>

And after replace:

<input type="hidden" name="go_to" value="{{path('Accueil') }}"/>

by:

<input type="hidden" name="go_to" value="Accueil"/>

And in security.yaml:

form_login:
                # "login" is the name of the route created previously
                login_path: login
                check_path: login
                failure_path: login
                enable_csrf: true
                username_parameter: _email
                password_parameter: _password
                target_path_parameter: go_to
  • Related