Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Symfony redirect after login with condition on user

My symfony3 login page redirects to home by default, as stated inside my security.yml file.

However, I want it to redirect to my "Edit profile" page if the user didn't fulfil it yet. In any other form I would make this in the controller, but since there is no $form->handleRequest($user) in the login form, I don't have a $user variable to test on.

There is a lot of SO topics about how to redirect user based on roles, and the documentation tells about redirecting from the action field of the form or within security.yml, but not any is what I'm looking for.

How can I redirect based on a condition ?

NB : for some reasons, I cannot use FOSUserBundle yet :-(

like image 668
Dan Chaltiel Avatar asked Jan 03 '17 09:01

Dan Chaltiel


2 Answers

I assume you are using the Guard Authentication system. ( http://symfony.com/doc/current/security/guard_authentication.html )

Then you should have a class extending the AbstractGuardAuthenticator class.

In that class, there is a method called onAuthenticationSuccess, in here you can put some logic for redirecting the request. If you return null here, it will just continue, and use the route configured in your security.yml.

You will need to pass the @router service to the Authenticator class through dependencyInjection.

Assuming you passed the router service, your method will look something like this:

public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
{
    /** @var User $user */
    $user = $token->getUser();

    if ($user->hasCompleteProfile() == false) {
        $url = $this->router->generate('edit_profile');

        return new RedirectResponse($url);
    }

    // Continue with default behaviour
    return null;
}
like image 61
Nico Kaag Avatar answered Nov 12 '22 00:11

Nico Kaag


If all else fails (or becomes an excessive pain to deal with) you can always simply introduce an intermediary route and do your logic in there.

That is, create an action who's sole purpose is to redirect users based on whatever logic is needed, and then put that as the target path in the security.yml firewall.

security:
    firewalls:
        main:
            pattern: ^/
            anonymous: ~
            form_login: 
                login_path: login
                check_path: login
                default_target_path: login_success
                always_use_default_target_path: true
            logout:
                path: logout

Where the login would be something like:

class AuthenticationController extends Controller
{
    /**
     * @Route("/login", name="login")
     * @Route("/logout", name="logout")
     */
    public function loginAction(Request $request)
    {
        // Standard login stuff here
    }

    /**
     * @Route("/login_success", name="login_success")
     */
    public function postLoginRedirectAction()
    {
        if (/* user needs to see location A */) {
            return $this->redirectToRoute("location_a");
        } else if (/* user needs to see location B */) {
            return $this->redirectToRoute("location_b");
        } else {
            return $this->redirectToRoute("index");
        }
    }
}
like image 5
Atli Avatar answered Nov 11 '22 22:11

Atli