How to automatically login customer after registration with Symfony
Tags: php, symfony
Published: 2020-10-01 16:21:01

A lot of websites allow you to be logged just after registration and I think that great for the user experience. So today I will show you how to do it with Symfony.
## Basic configuration
* Both Symfony and composer should be installed. If you use the light version of SF, make sure you have the maker bundle installed because I will use it.
* And that's it 😊

### Let's start
First I'm going to use : `php bin/console make:user`
```php
//I leave User by default
 The name of the security user class (e.g. User) [User]:
 >
// Yes I want to store it
 Do you want to store user data in the database (via Doctrine)? (yes/no) [yes]:
 >
//Default value (email) is good
 Enter a property name that will be the unique "display" name for the user (e.g. email, username, uuid) [email]:
 >
// Yes I want to hash password and I let SF do it for me
 Will this app need to hash/check user passwords? Choose No if passwords are not needed or will be checked/hashed by some other system (e.g. a single sign-on server).

 Does this app need to hash/check user passwords? (yes/no) [yes]:
 >
```
Our entity is now ready. Symfony just created both User Entity and UserRepository. 
Now let's add the authentification by using : 
`php bin/console make:auth`
```php
// I choose 1 for the complete authenticator
 What style of authentication do you want? [Empty authenticator]:
  [0] Empty authenticator
  [1] Login form authenticator
 > 1
1
//I prefer to call it LoginFormAuthenticator
 The class name of the authenticator to create (e.g. AppCustomAuthenticator):
 > LoginFormAuthenticator
//It's fine for me
 Choose a name for the controller class (e.g. SecurityController) [SecurityController]:
 >
//Yes I want a logout URL
 Do you want to generate a '/logout' URL? (yes/no) [yes]:
 >
```
Now we've got 4 folders in our src : 
**Controller**
* SecurityController.php

**Entity**
* User.php

**Repository**
* UserRepository.php

**Security**
* LoginFormAuthenticator.php

Let's check the last one. As you can see, there are all the logics for the authentification. You can modify the parameters you want. For example here you can change the error message when the email is wrong : 
```php
 public function getUser($credentials, UserProviderInterface $userProvider)
    {
        $token = new CsrfToken('authenticate', $credentials['csrf_token']);
        if (!$this->csrfTokenManager->isTokenValid($token)) {
            throw new InvalidCsrfTokenException();
        }

        $user = $this->entityManager->getRepository(User::class)->findOneBy(['email' => $credentials['email']]);

        if (!$user) {
            // fail authentication with a custom error
            throw new 
CustomUserMessageAuthenticationException('Email could not be found.');
        }

        return $user;
    }
```
When the User is logged, I would like to redirect him to the home page. Lets pretend we've already created the HomeController with the name: "app_home".
In LoginFormAuthenticator.php there is a onAuthenticationSuccess's function. I will change the default value with a redirection to the homepage
```php
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $providerKey)
    {
        if ($targetPath = $this->getTargetPath($request->getSession(), $providerKey)) {
            return new RedirectResponse($targetPath);
        }
//I will delete the below line
        throw new \Exception('TODO: provide a valid redirect inside '.__FILE__);
//And replace it by this one
return new RedirectResponse($this->urlGenerator->generate('app_home'));
    }
```
Great now our users will be redirect to the homepage. Let's finish it. Create a new RegisterController and the form ( I guess you know how to do it 😉). 
I called my form RegisterType. So now thanks to the autowiring I am going to allow the user to be logged after registration. I will use autowiring for the Request, EntityManager,UserPasswordEncoderInterface, LoginFormAuthentificator and GuardAuthenticatorHandler :
```php
/**
     * @Route("/register", name="app_register")
     */
    public function registration(Request $request, EntityManagerInterface $manager,UserPasswordEncoderInterface $passwordEncoder, LoginFormAuthentificator $login, GuardAuthenticatorHandler $guard)
    {
//Basic code for registration
        $user = new User();
        $form = $this->createForm(RegisterType::class, $user);
        $form->handleRequest($request);
//I always use a unmapped plainPassword for the real password
        if ($form->isSubmitted() && $form->isValid()){
            $user->setPassword($passwordEncoder->encodePassword($user, $form['plainPassword']->getData()));

            $manager->persist($user);
            $manager->flush();
//Just to be UX, I had a flash message
            $this->addFlash('success', 'The registration is successfull');
//This is how the User could be logged after the registration
//Guard handle it
//'main' is your main Firewall. You can check it in config/packages/security.yaml
            return $guard->authenticateUserAndHandleSuccess($user,$request,$login,'main');
        }

        return $this->render('security/registration.html.twig', ['form' => $form->createView(),]);
    }
```
This is how to do it with SF, I hope it's gonna help you in your future registration !

That's all folks 😁