'Symfony Password validation regex (Call to member function null)
Pretty new to the Symfony community but trying my best and I'm having a hard time on "how to validate password" topic.
When my user is connecting for the first time, he's redirected on a new page to change it to a stronger one. I check if it's strong enough with a regex and it's working but only if the user match the strong password policies on the first try. Otherwise he is disconnected and I get a "Call to a member function GetPassword() on null" error which I think I understand, I mean I get the why but don't know how to correct it.
I tried my regex on both the entity and on the symfony form (separately) but the same error occurs.
Thanks for your feedback (and kindness)
Here's my entity :
#[Assert\Regex('#^\S*(?=\S{8,})(?=\S*[a-z])(?=\S*[A-Z])(?=\S*[\d])\S*$#', message: 'Mot de passe trop faible')]
#[ORM\Column(type:'string')]
private $password;
And here is my controller :
#[Route("/", name:"")]
class LoginController extends AbstractController
{
#[Route(path: '/login', name: 'app_login')]
public function login(AuthenticationUtils $authenticationUtils): Response
{
// if ($this->getUser()) {
// return $this->redirectToRoute('target_path');
// }
// 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', ['last_username' => $lastUsername, 'error' => $error]);
}
#[Route(path: '/logout', name: 'app_logout')]
public function logout(): void
{
throw new \LogicException('This method can be blank - it will be intercepted by the logout key on your firewall.');
}
#[Route('/check', name: 'check')]
public function check(
UserRepository $repoUser
): Response
{
$user = $this->getUser();
$isPassword1234 = password_verify('1234',$user->getPassword());
if($isPassword1234){
return $this->redirectToRoute('mdp');
}
return $this->redirectToRoute('home');
}
#[Route('/mdp', name: 'mdp')]
public function changeMdp(
UserRepository $repository,
EntityManagerInterface $entityManager,
Request $request,
UserPasswordHasherInterface $passwordHasher
): Response {
$user = $this->getUser();
$form = $this->createForm(MdpType::class, $user );
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$user = $this->getUser();
$mdpSimple = $user->GetPassword();
$vraiMdp = $passwordHasher->hashPassword($user,$mdpSimple);
$user->setPassword($vraiMdp);
$entityManager->persist($user);
$entityManager->flush();
return $this->redirectToRoute('home');
}
$this->addFlash('error', ' Les deux mots de passes ne correspondent pas !');
return $this->renderForm('home/mdp.html.twig', compact('form', 'user'));
}
}
My security.yaml :
security:
enable_authenticator_manager: true
# https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords
password_hashers:
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
App\Entity\User:
algorithm: auto
# https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider
providers:
# used to reload user from session & other features (e.g. switch_user)
app_user_provider:
entity:
class: App\Entity\User
property: email
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
lazy: true
provider: app_user_provider
custom_authenticator: App\Security\UserAuthenticator
logout:
path: app_logout
# where to redirect after logout
target: app_login
# activate different ways to authenticate
# https://symfony.com/doc/current/security.html#the-firewall
# https://symfony.com/doc/current/security/impersonating_user.html
# switch_user: true
# Easy way to control access for large sections of your site
# Note: Only the *first* access control that matches will be used
role_hierarchy:
ROLE_SECTION: ROLE_USER
ROLE_UD: ROLE_SECTION
ROLE_NATIONAL: ROLE_UD
ROLE_ADMIN: ROLE_NATIONAL
access_control:
- { path: ^/recap, roles: ROLE_UD }
- { path: ^/national, roles: ROLE_NATIONAL }
- { path: ^/admin, roles: ROLE_ADMIN }
when@test: security: password_hashers: # By default, password hashers are resource intensive and take time. This is # important to generate secure password hashes. In tests however, secure hashes # are not important, waste resources and increase test times. The following # reduces the work factor to the lowest possible values. Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: algorithm: auto cost: 4 # Lowest possible value for bcrypt time_cost: 3 # Lowest possible value for argon memory_cost: 10 # Lowest possible value for argon
Solution 1:[1]
Now that you have shared your security I can tell you that the error is linked to that configuration
add this
access_control:
- { path: ^/check, roles: ROLE_USER }
- { path: ^/recap, roles: ROLE_UD }
- { path: ^/national, roles: ROLE_NATIONAL }
- { path: ^/admin, roles: ROLE_ADMIN }
If you don't tell symfony that the route needs authentication $this->getUser() in your controller will always returns null
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 | R4ncid |
