Symfony2: Make users complete registration after login if some fields are missing Symfony2: Make users complete registration after login if some fields are missing symfony symfony

Symfony2: Make users complete registration after login if some fields are missing


I've found the solution by myself, I've manually created a new exception:

<?phpnamespace Acme\UserBundle\Exception;use Symfony\Component\Security\Core\Exception\AuthenticationException;use HWI\Bundle\OAuthBundle\Security\Core\Exception\OAuthAwareExceptionInterface;/** * IncompleteUserException is thrown when the user isn't fully registered (e.g.: missing some informations). * * @author Alessandro Tagliapietra http://www.alexnetwork.it/ */class IncompleteUserException extends AuthenticationException implements OAuthAwareExceptionInterface{    private $user;    private $accessToken;    private $resourceOwnerName;    /**     * {@inheritdoc}     */    public function setAccessToken($accessToken)    {        $this->accessToken = $accessToken;    }    /**     * {@inheritdoc}     */    public function getAccessToken()    {        return $this->accessToken;    }    /**     * {@inheritdoc}     */    public function getResourceOwnerName()    {        return $this->resourceOwnerName;    }    /**     * {@inheritdoc}     */    public function setResourceOwnerName($resourceOwnerName)    {        $this->resourceOwnerName = $resourceOwnerName;    }    public function setUser($user)    {        $this->user = $user;    }    public function getUser($user)    {        return $this->user;    }    public function serialize()    {        return serialize(array(            $this->user,            $this->accessToken,            $this->resourceOwnerName,            parent::serialize(),        ));    }    public function unserialize($str)    {        list(            $this->user,            $this->accessToken,            $this->resourceOwnerName,            $parentData        ) = unserialize($str);        parent::unserialize($parentData);    }}

In this way, in the custom Oauth user provider when i check if an user exist or I create a new user i check if the required fields are missing:

if (!$user->getEmail()) {    $e = new IncompleteUserException("Your account doesn't has a mail set");    $e->setUser($user);    throw $e;}

In that case the user will be redirected to the login form, with that exception in session, so in the login page I do:

if($error instanceof IncompleteUserException) {    $session->set(SecurityContext::AUTHENTICATION_ERROR, $error);    return $this->redirect($this->generateUrl('register_complete'));}

And it will be redirected to a form with the $user in the exception so it can ask only for the missing information and then login the user.


I ran into a similar issue while migrating to a sf site. After the migration I wanted the migrated users to complete their profile whereas the newly registered users could get started immediately.

I solved this similar to your idea using a RequestListener but added a whitelist of pages that the user is allowed without completion of his profile. Depending on the number of pages you want the user to have access to without completion of his profile you might also consider using a blacklist.

I did not check for th existance of a particular field uppon redirecting to the profile completion page but added a role "ROLE_MIGRATION" when migrating the usersdatabase. In your case you can add the role when creating the user through oauth.

Here the code of my request listener:

public function onRequest(GetResponseEvent $evt){    if (HttpKernelInterface::MASTER_REQUEST !== $evt->getRequestType())    {        return;    }    $token = $this->securityContext->getToken();    if(!is_object($token)) or not migrating    {        // user is not logged in        return;    }    $user = $token->getUser();    if(!$user instanceof User || !$user->hasRole('ROLE_MIGRATING'))    {        // different user class or already migrated        return;    }    $openPaths = array(        '/start-2.0',        '/css',        '/js',        '/images',        '/media',        '/geo',        '/_wdt',        '/logout', or not migrating        '/terms',        '/contact',        '/about',        '/locale/set'    );    foreach($openPaths as $p)    {        if(strpos($evt->getRequest()->getPathInfo(),$p)===0)        {            // path is open for migrating users            return;        }    }    header('Location: /start-2.0');    exit;}