I would like to redirect users after they log in. Is it possible to use hook_user_login()
to make the redirection? How do I add the parameter for the redirection?
18 Answers
You need to alter the login form and add a submit handler which will take care of the redirection. You cannot use $form_state->setRedirectUrl()
directly in the form alter, since it will be overwritten by UserForm::submitForm()
.
/**
* Implements hook_form_FORM_ID_alter().
*/
function mymodule_form_user_login_form_alter(&$form, FormStateInterface $form_state) {
$form['#submit'][] = 'mymodule_user_login_submit';
}
/**
* Form submission handler for user_login_form().
*
* Redirects the user to the dashboard after logging in.
*/
function mymodule_user_login_submit(&$form, FormStateInterface $form_state) {
$url = Url::fromRoute('mymodule.dashboard');
// Check if a destination was set, probably on an exception controller.
// @see \Drupal\user\Form\UserLoginForm::submitForm()
$request = \Drupal::service('request_stack')->getCurrentRequest();
if (!$request->request->has('destination')) {
$form_state->setRedirectUrl($url);
}
else {
$request->query->set('destination', $request->request->get('destination'));
}
}
-
4As described by @kiamlaluno, one can also use
$form_state->setRedirect('mymodule.dashboard);
Jan 6, 2017 at 6:57 -
3Please explain users who follow this answer what mymodule.dashboard should/would do. How to change that to <front>, just for an example. Since user dashboard is the default redirect after login, this example here is useless. The new user do not know which parts to alter and how for his redirect.– nilsunOct 21, 2017 at 10:53
-
1To redirect to the front page, you can use the example above but change the line that generates the $url object to $url = Url::fromUri('internal:/');– oknateNov 9, 2017 at 21:41
-
1I don't understand what's happening in the
else
here? Maintaining an existing redirect?– user1359Oct 12, 2018 at 15:14 -
2you have to use use Drupal\Core\Url; to make it working correctly Oct 24, 2018 at 9:13
Redirecting users after they log in on a Drupal 8 site is not different from how it was done on Drupal 7, except the code needs to be adapted for Drupal 8.
In particular:
hook_user_login()
is not used to redirect users after they log in, simply for the fact that redirecting users in that hook would stop otherhook_user_login()
implementations from being invoked.The correct way to redirect users is adding a form submission handler to the login form that uses code similar to the following one.
$form_state->setRedirect('user.page');
Notice that user.page is the routing name for the Drupal path where you want the user to be redirected.
If you have an instance of theDrupal\Core\Url
class, you could also use the following code.$form_state->setRedirectUrl($url);
Keep in mind that the first method is preferable when you are redirecting users to a page in the same site they logged in; the second method is normally used to redirect users using an external URL.
Bit late to the party but as per https://www.drupal.org/node/2068293#comment-11712455 you can set the destination in hook_user_login() to redirect at the end of the login processing.
i.e.
/**
* Implements hook_user_login().
*/
function mymodule_user_login(\Drupal\user\UserInterface $account) {
// Ignore password reset.
$route_name = \Drupal::routeMatch()->getRouteName();
if ($route_name !== 'user.reset.login') {
// Do not interfere if a destination was already set.
$current_request = \Drupal::service('request_stack')->getCurrentRequest();
if (!$current_request->query->get('destination')) {
// Default login destination to the dashboard.
$current_request->query->set(
'destination',
\Drupal\Core\Url::fromRoute('mymodule.dashboard')->toString()
);
}
}
}
Using FormState::setRedirect() as per the other answers will probably cover most people's use cases and is potentially the 'right' answer, however using the destination query param with hook_user_login means that any form submit* that logs in the user will redirect but without interference or prior knowledge of any other part of the form/request.
i.e. it will still work with a custom login form and using destination does not stop any other hooks (it is implemented by \Drupal\Core\EventSubscriber\RedirectResponseSubscriber
at the end of response processing).
*Any form submit that invokes hook_user_login (user_login_finalize()) and does not manually call FormState::setResponse().
-
1This has the advantage of working if authentication happens from something other than a login form. But does this interfere with other hook_user_login implementations from other modules?– JonathanJul 29, 2017 at 18:34
-
1@Jonathan No, it only sets the destination and doesn't do an early request->send() or anything (i.e. like d7 drupal_goto), it will allow all other hooks, form callbacks etc to run like normal before it is acted upon. This is just how the standard drupal login redirect does it.– Sut3khJul 30, 2017 at 21:39
-
1Please explain users who follow this answer what mymodule.dashboard should/would do. How to change that to <front>, just for an example. Since user dashboard is the default redirect after login, this example here is useless. The new user do not know which parts to alter and how for his redirect.– nilsunOct 21, 2017 at 10:54
-
3@nilsun
mymodule.dashboard
is the route name and can be replaced with any route name (i.e.\Drupal\Core\Url::fromRoute('<front>')->toString()
or\Drupal\Core\Url::fromRoute('entity.node.canonical', ['node' => 123])->toString()
). For more information see drupal.org/docs/8/api/routing-system/routing-system-overview and api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Url.php/…– Sut3khDec 21, 2017 at 22:16 -
4This breaks password reset so I'm down-voting the answer. (Creating a form submission handler for user_login_form as suggested in another answer works.)– hansfnNov 5, 2018 at 13:51
there are couple of solutions to do this: if you want to do it in your custom module:
Solution 1: use a custom form submit hander
/**
* Implements hook_form_alter().
*/
function YOUR_MODULE_NAME_form_alter(&$form, \Drupal\Core\Form\FormStateInterface\FormStateInterface $form_state, $form_id) {
if ($form_id == 'user_login_form') {
$form['#submit'][] = 'myredirect_submit_handler';
}
}
/**
* Custom submit handler for login form.
*/
function myredirect_submit_handler($form, FormStateInterface $form_state) {
$url = Url::fromRoute('YOUR_ROUTE_MACHINE_NAME');
$form_state->setRedirectUrl($url);
}
Solution 2: ( which I noticed it's not working on drupal > 8.3)
you can use hook_user_login and try to redirect to yourpath
function yourmodule_user_login($account) {
// We want to redirect user on login.
$response = new RedirectResponse("yourpath");
$response->send();
return;
}
Solution 3:
you can use Rules module, create "redirection action" after "user logged in" triggered
Solution 4:
Use one of the following contirb modules
-
-
3I was getting
ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION
errors in certain circumstances with the above - I suggest replacingreturn;
withexit;
, to ensure the redirect - which sets headers - is the last thing to be executed.– user34185Jul 14, 2016 at 14:19 -
2hook_user_login() is called before the submit handlers so this would prevent them from being called. Yogesh's answer below is a better way of doing this.– imcleanOct 1, 2018 at 1:29
-
login_destination is solid, quite customizable and works like a charm wth Drupal 9.5 Nov 11 at 19:00
You can simply do it by using Rules
React on: After user has logged in
- Add action: Redirect >> then use a parameter or type your url.
-
3The main caveat on this is that Rules is still in pre-release ALPHA for Drupal 8 so take care if you need stability on your website Aug 30, 2018 at 18:08
-
1Rules messes up the login system when the site has redirect to a page after user logs in. Beware Mar 1, 2019 at 10:52
In D8 and later, you can use user default page module for this purpose.
This module allows you to customize the destination that a user is redirected to after logging in or logged out. You can customize by roles or individual users.
-
1Works but it doesn't take in consideration password reset links, when the user uses the one time link to set their password it redirects them to the page you set in this module and not the user account.– SorinAug 24, 2017 at 14:58
-
1This module still breaks password reset so I'm down-voting the answer. See drupal.org/project/user_default_page/issues/2991916 (Creating a form submission handler for user_login_form as suggested in another answer works.)– hansfnNov 5, 2018 at 13:52
-
-
You can also alter the user login form and add your own custom submit handler to set $form_state redirect, instead of directly redirecting user to your custom URL using hook_user_login.
<?php
/**
* Implements hook_form_alter().
*/
function [MODULENAME]_form_alter(&$form, \Drupal\Core\Form\FormStateInterface\FormStateInterface $form_state, $form_id) {
switch ($form_id) {
// Alter login form and add own custom submit handler.
case 'user_login_form':
$form['#submit'][] = '_[MODULENAME]_user_login_form_submit';
break;
}
}
/**
* Custom submit handler for login form.
*/
function _[MODULENAME]_user_login_form_submit($form, FormStateInterface $form_state) {
// Set redirect to login form.
$form_state->setRedirect('YOUR.MENU-ROUTER.NAME');
}
Adding it in $form_state redirect will make sure that the other submit handlers/login hooks get called.
Like Drupal7 we can't set $form_state['redirect'] directly, because $form_state is now class object. Checkout FormState::setRedirect() for further details.
hook_user_login()
doesn't work for redirection, it's used if you want to do something with the user when he logs in. Fx core suggests users to set the local timezone if it's not set.
Instead you need to use hook_form_alter
on all of the login forms and add a custom submit handler which sets the redirect on the form state object.
I use the following snippet quite a lot so I thought I'd share it. You can add different redirects depending on which role the user has.
use Symfony\Component\HttpFoundation\RedirectResponse;
/**
* Redirect on login.
*/
function MYMODULE_user_login($account) {
$roles = $account->getRoles();
if(in_array('webmaster', $roles)) {
$response = new RedirectResponse('/admin/content');
$response->send();
}
}
-
-
@FloDevelop, maybe use Event subscribers like in stefvanlooveren.me/blog/… Nov 11, 2021 at 11:21
I am displaying the login form in my own controller. That way it's possible to manipulate the form (and so redirect the user after login) without the non-OO hooks:
$fb = $this->formBuilder();
$rc['top'] = ['#markup' => '<p>Willkommen im Kundenbereich von proreos.
Bitte melden Sie sich hier mit Ihrem
Benutzernamen oder Ihrer Email Addresse an.</p>'];
$form = $fb->getForm("Drupal\user\Form\UserLoginForm");
$ug = $this->getUrlGenerator();
$redir = $ug->generateFromRoute('proreos.home', [],
['query' => $this->getDestinationArray(), 'external' => FALSE]);
$form['#action'] = $redir;
$rc['login'] = $form;
return $rc;
Change the 'proreos.home' route to whatever destination you need.
Regards
Rainer
Simply add destination
parameter to login url.
Example: http://example.com/user/login?destination=/my-page
If you doing it for 403 ( Access Denied ) pages use following module:
https://www.drupal.org/project/redirect_403_to_login_page
https://www.drupal.org/project/redirect
- Install the above module
- Add custom url path as the destination parameter in the url
So, configure the above module to redirect from
/user/login to /user/login?destination='CUSTOM_NODE_PATH'
- Wanted to use r4032login module to allow authenticated users access the concerned page, when they copy/paste the url or use an hyperlink from word/excel for example.
- Other 'login redirect' modules would override this functionality and would only allow users to land on a configured single page even when the destination parameters are included in the url
You can use logintoboggan module for redirection. It has other configuratrions which may be useful if you want other functionlaities like login using usernames.
-
2Good answer for D7, but this question is tagged D8, and there's no Drupal 8 version of Logintoboggan yet. Jan 17, 2019 at 14:43
Another option specifically for this issue is a simple Drupal 8 contributed module: Redirect After Login. The module can be found here:
https://www.drupal.org/project/redirect_after_login
As the description shows, it is a simple, focused module that is covered by the Drupal security advisory policy.
/**
* hook_user_login Redirect to English language whenever admin login
**/
function modulename_user_login($account) {
// We want to redirect user on login.
$response = new Symfony\Component\HttpFoundation\RedirectResponse("/en/admin/config");
$response->send();
return;
}
I was working on a way to get around the other things that depend on hook_user_login because many other options are breaking in the newer versions of 8. Some other re-direct modules do a lot of leg-work that is either no longer relevant and/or just out-right hogging resources. I put together this simple logic into a custom module for handling the login processes:
function hook_user_login( UserInterface $account ) {
// Doing checks to see if the login is from an HTML origin or not.
// Could be from RESTful request to logins
$request = \Drupal::request();
if ($request->getRequestFormat() !== 'html') {
// default
return;
}
// Get the destination to see where the login request is going.
// This is useful to check for interactions from user creations.
$destination = $request->query->get('destination');
// Check the destination. If the destination will result in a re-direct
// to your homepage (here statically defined, but could be programmatic)
// then you can force re-direct to a different page. This is the URL defined
// in config > system > basic site settings.
if ($destination && $destination === '/whatever-homepage-uri-is') {
// Regular login, send to alternate welcome page
$response = new RedirectResponse('/welcome');
$response->send();
exit;
}
// default
return;
}
I have been using this successfully with Drupal 8.8.3 and it does not break my REST login requests from another module I built, re-directs correctly for new account creations, and then re-directs to a different page on a regular site login.
Or you simply use a one in all module Url Redirect https://www.drupal.org/project/url_redirect for both the D.7 and D8 distributions
User redirect is another option in Drupal(8/9) to redirect the user after login or logout.
This module covers wider approach where multiple roles are assigned to different users.