I would authenticate a user in a very direct way (FOSUserBundle, Symfony2.2). I'am trying with a trivial example, but it doesn't work:
...
use FOS\UserBundle\Controller\RegistrationController as RegController;
...
class DefaultController extends Controller{
...
public function indexAction(){
$route = 'first_set_profile';
$url = $this->container->get('router')->generate($route);
$response = new RedirectResponse($url);
$userManager = $this->get('fos_user.user_manager');
$userToLogIn = $userManager->findUserByEmail('aa#bb.com');
new RegController(authenticateUser($userToLogIn, $response));
...
}
This script is running, but it is not authenticate the user with email aa#bb.com...
Thanks
This is how you can authenticate a demo user for example programmatic:
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
public function demologinAction(Request $request)
{
$userManager = $this->get('fos_user.user_manager');
$user = $userManager->findUserByEmail('demo#example.com');
if (!$user) {
throw $this->createNotFoundException('No demouser found!');
}
$token = new UsernamePasswordToken($user, $user->getPassword(), 'main', $user->getRoles());
$context = $this->get('security.context');
$context->setToken($token);
$router = $this->get('router');
$url = $router->generate('dashboard_show');
return $this->redirect($url);
}
The third parameter in the UsernamePasswordToken must be the firewall name.
Related
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;
}
when i enabled confirmation email in register fosuserbundle it redirect automaticly to page login and in profilet i have status 302 for routing fos_user_registration_check_email also user is not created and when i disabled confirmation email i haven't any error and user is created.
controller:
/**
* #Route("/register", name="register_babysitter")
*/
public function registerAction(Request $request)
{
/** #var $dispatcher EventDispatcherInterface */
$dispatcher = $this->get('event_dispatcher');
$user= new BabySitter();
$event = new GetResponseUserEvent($user, $request);
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_INITIALIZE, $event);
if (null !== $event->getResponse()) {
return $event->getResponse();
}
$form= $this->createForm(BabySitterType::class, $user);
$form->setData($user);
$form->handleRequest($request);
if ($form->isSubmitted()) {
if ($form->isValid()) {
$this->uploadDocument->upload($user->getPicture(), $this->getParameter('pictures_directory'));
$this->uploadDocument->upload($user->getCriminalRecord(), $this->getParameter('criminalRecord_director_babySitter'));
$this->uploadDocument->uploadIdCard($user->getIdCards(), $user,$this->getParameter('idCard_directory'));
$event = new FormEvent($form, $request);
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_SUCCESS, $event);
if (null === $response = $event->getResponse()) {
$url = $this->generateUrl('fos_user_registration_confirmed');
$response = new RedirectResponse($url);
}
$response = $event->getResponse();
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_COMPLETED, new FilterUserResponseEvent($user, $request, $response));
return $response;
}
$event = new FormEvent($form, $request);
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_FAILURE, $event);
if (null !== $response = $event->getResponse()) {
return $response;
}
}
return $this->render('AppBundle:BabySitter:register.html.twig', array(
'form' => $form->createView()
));
}
config:
fos_user:
db_driver: orm
firewall_name: main
user_class: AppBundle\Entity\User
service:
mailer: fos_user.mailer.twig_swift
from_email:
address: "test#gmail.com"
sender_name: "test#gmail.com"
registration:
confirmation:
enabled: true
help me please and thanks
You can also implements the method confirmAction() and confirmedAction() and to create your own logic:
/**
* Receive the confirmation token from user email provider, login the user.
*
*
* #Route("/register/confirm/{token}", name="registration_confirm")
*
* #param Request $request
* #param string $token
*
* #return Response
*/
public function confirmAction(Request $request, $token)
{
/** #var $userManager \FOS\UserBundle\Model\UserManagerInterface */
$userManager = $this->get('fos_user.user_manager');
$user = $userManager->findUserByConfirmationToken($token);
if (null === $user) {
throw new NotFoundHttpException(sprintf('The user with confirmation token "%s" does not exist', $token));
}
/** #var $dispatcher EventDispatcherInterface */
$dispatcher = $this->get('event_dispatcher');
$user->setConfirmationToken(null);
$user->setEnabled(true);
$event = new GetResponseUserEvent($user, $request);
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_CONFIRM, $event);
$userManager->updateUser($user);
if (null === $response = $event->getResponse()) {
$url = $this->generateUrl('register_confirmed');
$response = new RedirectResponse($url);
}
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_CONFIRMED, new FilterUserResponseEvent($user, $request, $response));
return $response;
}
/**
* Tell the user his account is now confirmed.
*
* #Route("/register/confirmed", name="register_confirmed")
*/
public function confirmedAction()
{
$user = $this->getUser();
if (!is_object($user) || !$user instanceof UserInterface) {
throw new AccessDeniedException('This user does not have access to this section.');
}
return $this->render('frontend/register_success.html.twig', array(
'user' => $user,
'targetUrl' => $this->getTargetUrlFromSession(),
));
}
Remember also in the template of the email to use the route registration_confirm.
Basically, in these two actions, you could define the route you want to redirect once your user is register.
In my controller, I use the security.token_storage service to get the user connected like :
$client = $this->container->get('security.token_storage')->getToken()->getUser();
$username = $client->getNom()." ".$client->getPrenom();
In my functional test, I try to log in a user to retrieve it in my controller but if I debug inside, it says me that i'm anonymous :
private function logIn()
{
$client = static::createClient();
$firewallName = 'main';
$token = new UsernamePasswordToken("admin", "admin", "main", array());
static::$kernel->getContainer()->get('security.token_storage')->setToken($token);
$session = static::$kernel->getContainer()->get('session');
$session->set('_security_'.$firewallName, serialize($token));
$session->save();
$cookie = new Cookie($session->getName(), $session->getId());
$client->getCookieJar()->set($cookie);
return $client;
}
public function testIndex()
{
$client = $this->logIn();
$crawler = $client->request('GET', '/');
$login = $crawler->filter("#username_index")->text();
$this->assertEquals($login, 'ADMIN NOM Admin Prenom');
}
How i can pass my user of my test to my main code ?
I know that fosUserBundle from Symfony can send EmailConfirmation automactly, just adding:
fos_user:
# ...
registration:
confirmation:
enabled: true
but i have my own register's form in my own controller. (I am NOT using register's form of FOSUSER). and i don't know how to send an emailconfirmation when an user register in my system.
these are my register's functions I am using:
public function index(Request $request)
{
$customer = new Customer();
$form = $this->createForm(CustomerType::class, $customer);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$pass = $form->get('password')->getData();
$email = $form->get('email')->getData();
$this->register($email, $email, $pass);
$em->persist($customer);
$em->flush($customer);
header("Refresh:0");
}
return $this->render('backend/customer/customer_register.html.twig', array('form' => $form->createView()));
}
and this Auxiliar Function:
private function register($email, $username, $password)
{
$userManager = $this->get('fos_user.user_manager');
$email_exist = $userManager->findUserByEmail($email);
if ($email_exist) {
return false;
}
$user = $userManager->createUser();
$user->setUsername($username);
$user->setEmail($email);
$user->setEmailCanonical($email);
$user->setEnabled(1);
$user->setPlainPassword($password);
$user->addRole('ROLE_CUSTOMER');
$userManager->updateUser($user);
return true;
}
I have tried using
$confirmationEnabled = $this->container->getParameter('fos_user.registration.confirmation.enabled');
but doesn't work
Please, I don't know how to start. it is neccessary to have any configuration of swift mailer?
if someone can help me I would appreciate it very much
Thanks, Thank you very much
You can take a look at the code used in FOSuserbundle at
Controller/RegistrationController::registerAction()
dispatches an event FOSUserEvents::REGISTRATION_SUCCESS which calls the function
EventListener/EmailConfirmationListener::onRegistrationSuccess()
It generates a token and set it to the user Entity $user->setConfirmationToken($this->tokenGenerator->generateToken()); then sends the email $this->mailer->sendConfirmationEmailMessage($user);
note the mailer is instance of FOS\UserBundle\Mailer\MailerInterface
and the token generator FOS\UserBundle\Util\TokenGeneratorInterface
Good morning.
Tldr: I think that, I need for Symfony Test Client something similiar to js xhr settings: withcredentals:true.
Symfony 3.1. I have action in rest api controller:
/**
* #Rest\GET("/get-stuff")
* #Rest\View
* #Security("is_granted('IS_AUTHENTICATED_FULLY')")
*/
public function GetStuffAction($userId)
{
// get userId from session
$userId = $this->getUser()->getId();
$em = $this->getDoctrine()->getManager();
$Stuff = $em->getRepository('MyApiBundle:Stuff')->findBy(['user' => $userId]);
return $this->viewGroup($Stuff, ['stuff']);
}
And it does work correct.
Now I want Test, so I have :
class TestCase extends WebTestCase
{
public function testIndex()
{
$this->client = self::createClient();
$this->storage = new MockFileSessionStorage(__dir__.'/../../../../app/cache/test/sessions');
$this->session = new Session($this->storage);
$this->logIn($this->getUser(), new Response());
$this->client->request('GET', '/get-stuff');
$content = $this->client->getResponse()->getContent();
$this->assertEquals({"message":"Full authentication is required to access this resource.","code":0},$content);
}
public function logIn(User $user, Response $response)
{
$this->session->start();
$this->cookie = new Cookie('MOCKSESSID', $this->storage->getId());
$this->cookieJar = new CookieJar();
$this->cookieJar->set($this->cookie);
$this->token = new UsernamePasswordToken($user, 'user', 'main', $user->getRoles());
$this->session->set('_security_main', serialize($this->token));
$this->getSecurityManager()->loginUser(
$this->container->getParameter('fos_user.firewall_name'),
$user,
$response
);
$this->session->save();
}
}
And test for it gives me message: "Full authentication is required to access this resource". After method logIn() I can read session data which are connected with logged user.
How can I make to be logged during this part to not receive message about authentication?:
$this->client->request('GET', '/get-stuff');
$content = $this->client->getResponse()->getContent();
More details:
1. My test class extends WebTestCase.
2. My user is overwritten for FosUserBundle.
I suppose that is something like in javascript:
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
but I don't know what.
Thank you in advance for helping solve my problem!
Ok, I was good way to do this:
public function logIn(User $user) {
$session = $this->session;
$firewallContext = 'secured_area';
$token = new UsernamePasswordToken($user, 'user', 'main', $user->getRoles());
$session->set('_security_'.$firewallContext, serialize($token));
$session->save();
$cookie = new Cookie($session->getName(), $session->getId());
$this->client->getCookieJar()->set($cookie);
}