cakedc/users autologin after registration

220 Views Asked by At

I'm using the cakephp 4.2.6 with the cakedc/users plugin. I'd like to automatically login the user after registration without the need to first activate the account by clicking on the link in e-mail.

My idea is to creating an Event-Listener and listening to the Users.Global.afterRegister Event, but then I don't know how to login the user with the new Authentication.

2

There are 2 best solutions below

0
steinkel On BEST ANSWER

There is a similar use case covered in the plugin documentation https://github.com/CakeDC/users/blob/master/Docs/Documentation/Events.md

Your approach looks correct to me, using the afterRegister event to create the listener in a controller where you have access to the Authenticatication component,

// note this example is handling auto-login after the user validated the email sent (click the validation token link sent to his email address)
EventManager::instance()->on(
    \CakeDC\Users\Plugin::EVENT_AFTER_EMAIL_TOKEN_VALIDATION,
    function($event){
        $users = $this->getTableLocator()->get('Users');
        $user = $users->get($event->getData('user')->id);
        $this->Authentication->setIdentity($user);
    }
);

or using the request to retrieve the authentication service and set the identity like it's done here https://github.com/cakephp/authentication/blob/master/src/Controller/Component/AuthenticationComponent.php#L273

1
eliane86 On

this is what I ended up with and it seems to work so far:

<?php
namespace App\Event;
use Authentication\AuthenticationService;
use Authentication\AuthenticationServiceInterface;
use Authentication\AuthenticationServiceProviderInterface;
use Authentication\Middleware\AuthenticationMiddleware;
use Psr\Http\Message\ServerRequestInterface;

use Cake\Event\EventListenerInterface;
use Cake\Datasource\FactoryLocator;
use Cake\Log\Log;

class UserEventListener implements EventListenerInterface
{
    public function implementedEvents(): array
    {
        return [
            'Users.Global.afterRegister' => 'autoLogin',
        ];
    }

    public function autoLogin($event)
    {

        $user = $usersTable->get($event->getData('user')->id);
        $request = $event->getSubject()->getRequest();
        $response = $event->getSubject()->getResponse();
        $authenticationService = $this->getAuthenticationService($request);
        $authenticationService->persistIdentity($request, $response,  $user);
        
    }
        

    public function getAuthenticationService(ServerRequestInterface $request): AuthenticationServiceInterface
    {
        $authenticationService = new AuthenticationService([
            'unauthenticatedRedirect' => \Cake\Routing\Router::url([
            'controller' => 'Users',
            'action' => 'login',
            'plugin' => null,
            'prefix' => null
            ]),
            'queryParam' => 'redirect',
        ]);

        // Load identifiers, ensure we check email and password fields
        $authenticationService->loadIdentifier('Authentication.Password', [
            'fields' => [
                'username' => 'email',
                'password' => 'password',
            ]
        ]);

        // Load the authenticators, you want session first
        $authenticationService->loadAuthenticator('Authentication.Session');
        // Configure form data check to pick email and password
        $authenticationService->loadAuthenticator('Authentication.Form', [
            'fields' => [
                'username' => 'email',
                'password' => 'password',
            ],
            'loginUrl' => \Cake\Routing\Router::url([
            'controller' => 'Users',
            'action' => 'login',
            'plugin' => null,
            'prefix' => null
            ]),
        ]);

        return $authenticationService;
    }

}