Skip to content

Instantly share code, notes, and snippets.

@FlYos
Last active April 14, 2023 21:22
Show Gist options
  • Star 20 You must be signed in to star a gist
  • Fork 9 You must be signed in to fork a gist
  • Save FlYos/9828431 to your computer and use it in GitHub Desktop.
Save FlYos/9828431 to your computer and use it in GitHub Desktop.
Redirection user by roles after login/logout in symfony2

Description of this Gist

This is the how to for redirection implementation by roles after login or logout in Symfony2

Step

  1. Copy AfterLoginRedirection.php and AfterLogoutRedirection.php to your bundle under the "Redirection" directory
  2. Edit your services.yml file in your bundle and copy/paste the content of services.yml
  3. Edit your security.yml file...
  4. ... add success_handler: redirect.after.login in form_login: section
  5. ... add success_handler: redirect.after.logout in logout: section

More

For more informations, you can read my explanation on my blog (in french only)

<?php
/**
* @copyright Copyright (c) 2009-2014 Steven TITREN - www.webaki.com
* @package Webaki\UserBundle\Redirection
* @author Steven Titren <contact@webaki.com>
*/
namespace Webaki\UserBundle\Redirection;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
class AfterLoginRedirection implements AuthenticationSuccessHandlerInterface
{
/**
* @var \Symfony\Component\Routing\RouterInterface
*/
private $router;
/**
* @param RouterInterface $router
*/
public function __construct(RouterInterface $router)
{
$this->router = $router;
}
/**
* @param Request $request
* @param TokenInterface $token
* @return RedirectResponse
*/
public function onAuthenticationSuccess(Request $request, TokenInterface $token)
{
// Get list of roles for current user
$roles = $token->getRoles();
// Tranform this list in array
$rolesTab = array_map(function($role){
return $role->getRole();
}, $roles);
// If is a admin or super admin we redirect to the backoffice area
if (in_array('ROLE_ADMIN', $rolesTab, true) || in_array('ROLE_SUPER_ADMIN', $rolesTab, true))
$redirection = new RedirectResponse($this->router->generate('backoffice_homepage'));
// otherwise, if is a commercial user we redirect to the crm area
elseif (in_array('ROLE_COMMERCIAL', $rolesTab, true))
$redirection = new RedirectResponse($this->router->generate('crm_homepage'));
// otherwise we redirect user to the member area
else
$redirection = new RedirectResponse($this->router->generate('member_homepage'));
return $redirection;
}
}
<?php
/**
* @copyright Copyright (c) 2009-2014 Steven TITREN - www.webaki.com
* @package Webaki\UserBundle\Redirection
* @author Steven Titren <contact@webaki.com>
*/
namespace Webaki\UserBundle\Redirection;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Http\Logout\LogoutSuccessHandlerInterface;
class AfterLogoutRedirection implements LogoutSuccessHandlerInterface
{
/**
* @var \Symfony\Component\Routing\RouterInterface
*/
private $router;
/**
* @var \Symfony\Component\Security\Core\SecurityContextInterface
*/
private $security;
/**
* @param SecurityContextInterface $security
*/
public function __construct(RouterInterface $router, SecurityContextInterface $security)
{
$this->router = $router;
$this->security = $security;
}
/**
* @param Request $request
* @return RedirectResponse
*/
public function onLogoutSuccess(Request $request)
{
// Get list of roles for current user
$roles = $this->security->getToken()->getRoles();
// Tranform this list in array
$rolesTab = array_map(function($role){
return $role->getRole();
}, $roles);
// If is a commercial user or admin or super admin we redirect to the login area. Here we used FoseUserBundle bundle
if (in_array('ROLE_COMMERCIAL', $rolesTab, true) || in_array('ROLE_ADMIN', $rolesTab, true) || in_array('ROLE_SUPER_ADMIN', $rolesTab, true))
$response = new RedirectResponse($this->router->generate('fos_user_security_login'));
// otherwise we redirect user to the homepage of website
else
$response = new RedirectResponse($this->router->generate('homepage'));
return $response;
}
}
security:
encoders:
FOS\UserBundle\Model\UserInterface: sha512
role_hierarchy:
ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
providers:
fos_userbundle:
id: fos_user.user_provider.username_email
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
pattern: ^/
form_login:
provider: fos_userbundle
csrf_provider: form.csrf_provider
login_path: /login
check_path: /login_check
success_handler: redirect.after.login
logout:
path: /logout
target: /
success_handler: redirect.after.logout
anonymous: true
access_control:
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/membre, role: ROLE_USER }
- { path: ^/crm, role: ROLE_COMMERCIAL }
- { path: ^/backoffice, role: ROLE_ADMIN }
services:
redirect.after.login:
class: Webaki\UserBundle\Redirection\AfterLoginRedirection
arguments: [@router]
redirect.after.logout:
class: Webaki\UserBundle\Redirection\AfterLogoutRedirection
arguments: [@router, @security.context]
@jeffsacco
Copy link

Followed your steps and get this error

There is no extension able to load the configuration for "redirect.after.login" (in /opt/local/apache2/tpp/src/Tundra/Bundle/PayrollBundle/DependencyInjection/../Resources/config/services.yml). Looked for namespace "redirect.after.login", found none

Anyone else see this?

@jeffsacco
Copy link

Found the issue. The indentation in the service.yml file need to be exact. I just placed it in there and that error occurs.

@DONIKAN
Copy link

DONIKAN commented Dec 3, 2015

Big thanks, it work after deleting this line in service.yml
[...] logout: true

@notabigboy
Copy link

I still don't understand how if one user has many roles but each role has only one redirect link, where the user will be redirected after login? Do symfony allow many to one relationship user to the role than many to many?

@medbenhenda
Copy link

@notabigboy:
1- An user have many roles. In this code the redirection is make depending the principal role of the user
for example the list roles of the user is

array(0 => 'ROLE_ADMIN', 1 => 'ROLE_USER')

The principal role here is "ROLE_ADMIN"
2-The role is an attribute of the user entity. So no relationship context here.
In case, if you want to have separate roles for each user, you can create Role entity, that should implementing Symfony\Component\Security\Core\Role\RoleInterface

@MariemM
Copy link

MariemM commented Mar 16, 2016

Hello @jeffsacco
I have the same error please if you find the solution, please let me know ! Thank you.

@mariemferid
Copy link

thanks <3 <3

@Fatima-Zahra96
Copy link

I have follow the steps but it dosen't work for me may be its not compatible with Symfony3?

@Broasca
Copy link

Broasca commented Sep 17, 2019

Logout updated for symfony 4+

AfterLogoutRedirection.php

<?php

namespace App\Redirection;

use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Http\Logout\LogoutSuccessHandlerInterface;
use Symfony\Component\Security\Core\Security;

class AfterLogoutRedirection implements LogoutSuccessHandlerInterface
{
	/**
	 * @var RouterInterface
	 */
	private $router;
	/**
	 * @var Security
	 */
	private $security;

	/**
	 * @param RouterInterface $router
	 * @param Security $security
	 */
	public function __construct(RouterInterface $router, Security $security)
	{
		$this->router = $router;
		$this->security = $security;
	}
	/**
	 * @param Request $request
	 * @return RedirectResponse
	 */
	public function onLogoutSuccess(Request $request)
	{
		...
	}
}

services.yaml

    redirect.after.logout:
        class: App\Redirection\AfterLogoutRedirection
        arguments: ["@router", "@security.helper"]

@AkashicSeer
Copy link

Symfony needs to update the docs to contain examples and information on how this works and how to do it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment