Manually authenticate a user for a specific subdomain in Symfony 5 - symfony

I need to redirect the user after successful registration to their own subdomain (test for this example).
/**
* #Route("/signup", name="app_signup", host="admin.mysymfony.local")
*/
public function signup(
Request $request,
UserPasswordEncoderInterface $passwordEncoder,
LoginFormAuthenticator $authenticator,
GuardAuthenticatorHandler $guardAuthenticatorHandler
): Response
{
$user = new User();
$form = $this->createForm(SignupType::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$user = $form->getData();
$user->setPassword($passwordEncoder->encodePassword($user, $user->getPassword()));
$roles = $user->getRoles();
$roles[] = 'ROLE_ADMIN';
$user->setRoles($roles);
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($user);
$entityManager->flush();
$this->get('session')->set('user_id', $user->getId());
return $guardAuthenticatorHandler->authenticateUserAndHandleSuccess(
$user,
$request,
$authenticator,
'main'
);
}
return $this->render('security/signup.html.twig', [
'form' => $form->createView(),
]);
}
This works fine and the user is redirected to this method after successful authentication:
/**
* #Route("/signup/complete", name="app_signup_complete", host="admin.mysymfony.local")
*/
public function signupComplete(
Request $request,
UserPasswordEncoderInterface $passwordEncoder,
LoginFormAuthenticator $authenticator,
GuardAuthenticatorHandler $guardAuthenticatorHandler
): Response
{
if ($this->getUser() && $this->isGranted('ROLE_ADMIN') ) {
error_log('User authenticated');// this is logged successfully
}
if ( strpos($request->getHost(), 'admin.') == 0 ) {
$host = str_replace('admin.', 'test.', $request->getHost());
$homeUrl = $this->generateUrl('app_home');
$testHomeUrl = $request->getScheme() . '://' . $host. $homeUrl;
return $this->redirect(
$testHomeUrl
);
}
}
This is the method that is called after redirection to the user subdomain:
/**
* #Route("/home", name="app_home")
*/
function index(MessageGenerator $messageGenerator) {
if ( $this->getUser() && $this->isGranted('ROLE_ADMIN')) {
$message = $messageGenerator->getHappyMessage();
$htmlResponse = '<html><body>';
$htmlResponse .= "<p>Lucky message: ".$message. '</p>';
$htmlResponse .= "<p>User id : {$this->getUser()->getId()}."
. '</p>';
$htmlResponse .= "<p>Is granted ROLE_USER : {$this->isGranted('ROLE_USER')}."
. '</p>';
$htmlResponse .= "<p>Is granted ROLE_ADMIN : {$this->isGranted('ROLE_ADMIN')}."
. '</p>';
$htmlResponse .= '</body></html>';
return new Response(
$htmlResponse
);
}
else {
return new Response(var_export($this->get('session')->get('user_id'), true));
}
}
As expected it falls in the else section and the value of user_id passed to the session is not recognized because it is a different subdomain.
All suggestions are welcome and please if there is something that needs clarification let me know.

Related

How to pass variables to a RedirectResponse

I've a variable name $email but I don't know how to send it to dashController.php:
$action = $this->client->auth($username, $password);
if (isset($action->success) && $action->success){
$email = $action->data->email;
$response = new RedirectResponse('/dash');
$cookie = new Cookie('JWT', $action->data->jwt->token, new \DateTime($action->data->jwt->expires_at));
$response->headers->setCookie($cookie);
return $response;
}
in dashController.php
class dashController extends authContainer {
#[Route("/dash", "dashboard")]
public function indexAction(): Response
{
return $this->render('dash.twig', [
'email' => ...
]);
}}
If your class inherit from Symfony AbstractController class, you can use the
redirectToRoute method helper. Your code will be like :
if (isset($action->success) && $action->success){
$email = $action->data->email;
$response = $this->redirectToRoute('dashboard');
$cookie = new Cookie('JWT', $action->data->jwt->token, new \DateTime($action->data->jwt->expires_at));
$response->headers->setCookie($cookie);
return $response;
}

Binding entities to query parameters only allowed for entities have an identifier

I am using a Symfony 4 project, and I want to change the user password, so I created a method in my repository and called it to the controller, but this error it diplay to me,
Binding entities to query parameters only allowed for entities that have an identifier.
Repository
public function updateU($password,$email): ?Utilisateur
{
$dql = <<<DQL
SELECT u
FROM App\Entity\Utilisateur u
WHERE u.email = :email
AND u.password = :password
DQL;
return $this->getEntityManager()->createQuery($dql)
->setParameters(['email' => $email, 'password' => $password])
->getSingleScalarResult();
}
Controller
/**
* #Route("/Reset", name="Reset")
* Method({"GET"})
*/
public function New(
Request $request,
UtilisateurRepository $URe,
UserPasswordEncoderInterface $userPasswordEncoder,
EntityManagerInterface $entityManager,
MailerInterface $mailer
) {
$o = '';
$Varmail = $_GET['email'];
$user = new Utilisateur($o);
$form = $this->createFormBuilder($user)
->add('password', PasswordType::class)
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$to = $Varmail;
$sujet = 'Password Changed';
$Message = "Bonjour $Varmail Votre email est changé !";
$pass = $user->setPassword(
$userPasswordEncoder->encodePassword(
$user,
$form->get('password')->getData()
)
);
$URe->updateU($pass, $Varmail);
$Mai = new MailerController();
$Mai->sendEmail($mailer, $to, $sujet, $Message);
}
return $this->render('modifier_mdp/index.html.twig', [
'form' => $form->createView(),
]);
}
How can i solve it , And Thanks
In your updateU method, you are making a request to get, not update the data. It's better to use the ObjectManager to save the data, since you still have a updated instance of the Utilisateur object in the $user variable.
$user = $this->getDoctrine()->getManager()->getRepository(Event::class)->findOneBy(['email'=>$Varmail]);
$form = $this->createFormBuilder($user)->add('password', PasswordType::class)->getForm();
if ($form->isSubmitted() && $form->isValid()) {
// ...
$user->setPassword(
$userPasswordEncoder->encodePassword(
$user,
$form->get('password')->getData()
)
);
// save Utilisateur with new password
$em = $this->getDoctrine()->getManager();
$em->persist($user);
$em->flush();
}

Reset password symfony 4 (user not loggued)

I have a problem when i try to reset password on a non loggued user.
Entity users :
class Users implements AdvancedUserInterface, \Serializable, TwoFactorInterface, TrustedDeviceInterface {
[...]
}
Reset Password Action :
public function forgetPassword(Request $request, EntityManagerInterface $em, UserPasswordEncoderInterface $encoder)
{
$changePasswordModel = new ChangePassword();
$form = $this->createForm(ForgetPasswordType::class, $changePasswordModel);
$form->handleRequest($request);
$user = $em->getRepository("App:Users")->find(12);
if (!$request->get('token') || !$user || $user->getTokenExpire() <= new \DateTime())
{
return $this->redirectToRoute("404");
}
if ($form->isSubmitted() && $form->isValid())
{
$plainPassword = $form->getData()->getNewPassword();
$encoded = $encoder->encodePassword($user, $plainPassword);
$user->setPassword($encoded);
$em->persist($user);
$em->flush();
}
return $this->render('security/forget_password.html.twig', array(
'form' => $form->createView(),
'success' => $success
));
}
But i get this error :
The User object must implement the UserInterface interface.
Exact place of this error is on :
\vendor\symfony\security\Core\Validator\Constraints\UserPasswordValidator.php :
[...]
$user = $this->tokenStorage->getToken()->getUser();
if (!$user instanceof UserInterface) {
throw new ConstraintDefinitionException('The User object must
implement the UserInterface interface.');
}
[...]
When the user is loggued it work but when an user use a reset password it's because he lost his password. So it should work when the user is not loggued.
Thanks for your help !
Alex

JWT web token does not give back user infos

I have a problem with my API. After my login, I have a token, but unfortunately I can not read the information of my user with this token.
my code to have the token (that works):
/**
* #Rest\View()
* #Rest\Post("/api/createToken")
*/
public function createTokenAction(Request $request)
{
// reception payload
$username = $request->request->get('email');
$password = $request->request->get('password');
$user = $this->getDoctrine()
->getRepository('ApplicationSonataUserBundle:User')
->findOneBy(['email' => $username]);
// check user
if (!$user) {
$response = new JsonResponse('User not found');
$response->setStatusCode(Response::HTTP_NOT_FOUND);
return $response;
}
//check password
$encoder_service = $this->get('security.encoder_factory');
$encoder = $encoder_service->getEncoder($user);
$valid = $encoder->isPasswordValid($user->getPassword(), $password, $user->getSalt());
if (!$valid) {
$response = new JsonResponse('User Password is invalid');
$response->setStatusCode(Response::HTTP_NOT_FOUND);
return $response;
}
// store data inside my token
$token = $this->get('lexik_jwt_authentication.encoder')
->encode([
'id' => $user->getId(),
'email' => $user->getEmail(),
'exp' => time() + 3600 // 1 hour expiration
]);
$view = View::create($token);
$view->setFormat('json');
return $view;
}
then I try to use this code to read the information of my token:
/**
* #Rest\View()
* #Rest\Get("/api/user")
*/
public function getUsersAction(Request $request)
{
$response = $this->get('lexik_jwt_authentication.jwt_manager')->create($this->getUser());
$view = View::create($response);
$view->setFormat('json');
return $view;
}
but nothing does .. I do not understand why .. :/
If someone would have a track to offer me please

How to write unit test in symfony3

I want to know how to write standard unit test code for the below controller. I believe PHPUNIT is installed by default in symfony3 but I'm not sure how to execute it as well. Can someone guide me how to write testcontroller and execution command for symfony3 as well.
class RegistrationController extends Controller
{
/**
* #Route("/register", name="user_registration")
* #Security("has_role('ROLE_SUPER_ADMIN')")
*/
public function userAction(Request $request)
{
$user = new User();
$form = $this->createForm(UserType::class, $user);
$form->handleRequest($request);
if ($request->isMethod('POST') && $form->isValid()) {
$password = $this->get('security.password_encoder')
->encodePassword($user, $user->getPlainPassword());
$user->setPassword($password);
$em = $this->getDoctrine()->getManager();
$em->persist($user);
$em->flush();
$this->get('app.mailer')->sendUserCredentials($user);
$this->addFlash('notice', 'An account is created');
}
return $this->render('masteradmin/account/addUser.html.twig',
array('form' => $form->createView())
);
}
/**
* #Route(
* "/user/edit/{id}",
* requirements={"id" = "\d+"},
* name="user_edit"
* )
*/
public function editUserAction(User $user, Request $request)
{
if (!$this->get('security.authorization_checker')->isGranted('ROLE_SUPER_ADMIN')) {
throw new AccessDeniedException();
}
$em = $this->getDoctrine()->getManager();
$id = $request->attributes->get('id');
if (!$user = $em->getRepository('AppBundle:User')->findOneById($id)) {
throw new NotFoundHttpException('user details not found.');
}
$form = $this->createForm(UserType::class, $user)
->remove('plainPassword');
$form->handleRequest($request);
$data = $form->getData();
if ($form->isValid()) {
$em->persist($user);
$em->flush();
$this->addFlash('notice', 'Account information is updated');
return $this->redirectToRoute('user_list');
}
return $this->render(
'masteradmin/account/editUser.html.twig', ['form' => $form->createView()]
);
}

Resources