Sylius: RFC: Let's have auto login after user confirmation and password reset

Created on 7 May 2020  路  7Comments  路  Source: Sylius/Sylius

Initially proposed for Monofony, but it makes sense for Sylius as well. Maybe even more for Sylius.

Describe the proposed solution
You create yourself an account. You fill in a big form. Now you get redirected to your email to confirm it. You close the app, go to your email, find the mail, open it, click the link, and you are redirected to a login form with a flash message that you can now safely login.

But you have to input again the username, the password. Cognitive load++.

Same for reset password: you go to the website, it asks you to login. You input your email and a password you remember, it's wrong. Try a couple of variants, end up with the same error - wrong password.

You decide to reset it. Then you go to reset password. Enter your email, submit, sends you back to login with a flash message to check your email. Again: You close the app, go to your email, find the mail, open it, click the link, and you are redirected to a form where you can set the new password. You write it, twice and hit submit.

Back to login, with a flash message. Now you have to insert the username, again, and then the new password. Again. Cognitive load++. Rage++.

Solution

<?php

namespace App\EventSubscriber;


use Sylius\Bundle\UserBundle\Security\UserLoginInterface;
use Sylius\Bundle\UserBundle\UserEvents;
use Sylius\Component\User\Repository\UserRepositoryInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\EventDispatcher\GenericEvent;
use Webmozart\Assert\Assert;

class AutologinSubscriber implements EventSubscriberInterface
{
    /**
     * @var \App\Repository\UserRepository
     */
    private $userRepository;
    /**
     * @var \Sylius\Bundle\UserBundle\Security\UserLoginInterface
     */
    private $userLogin;
    /**
     * @var string
     */
    private $firewallContextName;

    public function __construct(
        UserRepositoryInterface $userRepository,
        UserLoginInterface $userLogin,
        string $firewallContextName
    ) {
        $this->userRepository = $userRepository;
        $this->userLogin = $userLogin;
        $this->firewallContextName = $firewallContextName;
    }

    /**
     * @return array|string[]
     */
    public static function getSubscribedEvents(): array
    {
        return [
            UserEvents::POST_PASSWORD_RESET => 'autoLogin',
        ];
    }

    public function autoLogin(GenericEvent $event)
    {
        $user = $event->getSubject();
        Assert::notNull($user);

        $user->setEnabled(true);
        $this->userRepository->add($user);

        $this->userLogin->login($user, $this->firewallContextName);
    }
}
    Sylius\Component\User\Repository\UserRepositoryInterface: '@sylius.repository.app_user'

    App\EventSubscriber\AutologinSubscriber:
        class: App\EventSubscriber\AutologinSubscriber
        arguments:
            $firewallContextName: '%firewall.app.context%'
--- a/config/packages/security.yaml
+++ b/config/packages/security.yaml
@@ -5,6 +5,9 @@ imports:

 parameters:
     secret: '%env(resolve:APP_SECRET)%'
+    firewall.app.context: 'app'
+    firewall.admin.context: 'admin'
+    firewall.api.context: 'api'

 security:

@@ -22,7 +25,7 @@ security:

     firewalls:
         admin:
-            context: admin
+            context: '%firewall.admin.context%'
             pattern: /admin(?:/.*)?$
             provider: sylius_admin_user_provider
             form_login:
@@ -54,10 +57,11 @@ security:
             fos_oauth: true
             stateless: true
             anonymous: true
+            context: '%firewall.api.context%'

         app:
             switch_user: true
-            context: app
+            context: '%firewall.app.context%'
             pattern: /.*
             provider: sylius_app_user_provider
             form_login:
diff --git a/config/routes/frontend/security.yaml b/config/routes/frontend/security.yaml
index 3465090..7f89171 100644
--- a/config/routes/frontend/security.yaml
+++ b/config/routes/frontend/security.yaml
@@ -49,7 +49,7 @@ app_frontend_password_reset:
         _controller: sylius.controller.app_user:resetPasswordAction
         _sylius:
             template: frontend/account/resetPassword.html.twig
-            redirect: app_frontend_login
+            redirect: app_frontend_homepage

The solution above is a PoC I implemented for my needs. It works for me. If you are interested, I can submit it in a PR to be included in Sylius by default.

Feature RFC

All 7 comments

  1. One doesn't need shared context to auto-login when password is reset
  2. Such functionality should be opt-in only in my opinion.

@mikemix how would you implement it in a different way, from the technical point of view?

besides the technical implementation, don't you find (business) value in the improvement I have proposed?

I cannot find a good (business) justification for the current behavior where the user is asked to do lots of unnecessary steps that can be automated for the sake of UX.

@CoderMaggie any input on this?

This issue has been automatically marked as stale because it has not had any recent activity. It will be closed in a week if no further activity occurs. Thank you for your contributions.

can we have some input from the Sylius Team? cc @pamil

I'm also in favor of such behavior. That's not very a fluid process currently and it needs way too much steps.

@pamil
mr bean waiting

Was this page helpful?
0 / 5 - 0 ratings

Related issues

inssein picture inssein  路  3Comments

bnd170 picture bnd170  路  3Comments

hmonglee picture hmonglee  路  3Comments

reyostallenberg picture reyostallenberg  路  3Comments

igormukhingmailcom picture igormukhingmailcom  路  3Comments