I have a Drupal 8 site and I need to dynamically redirect the user after they set their password for the first time after using their one-time login link.
I cannot figure out any way to hook into the workflow for this condition. Is it possible?
I have a Drupal 8 site and I need to dynamically redirect the user after they set their password for the first time after using their one-time login link.
I cannot figure out any way to hook into the workflow for this condition. Is it possible?
If you wanna redirect users, the below solution won't work, because '/user/reset/{uid}/{timestamp}/{hash}/login'
controlled by UserController::resetPassLogin
action if you see the return of resetPassLogin
:
- @return \Symfony\Component\HttpFoundation\RedirectResponse
- Returns a redirect to the user edit form if the information is correct.
- If the information is incorrect redirects to 'user.pass' route with a
- message for the user.
I figure out a solution but i'm not sure if its the best way to do it:
for example if i want to redirect the user after first login to admin/content
, i will override the resetPassLogin
action like the following:
myModule.routing.yml
myModule.reset.login:
path: '/user/reset/{uid}/{timestamp}/{hash}/login'
defaults:
_controller: '\Drupal\myModule\Controller\CustomUserController::customResetPassLogin'
_title: 'Reset password'
requirements:
_user_is_logged_in: 'FALSE'
options:
_maintenance_access: TRUE
no_cache: TRUE
myModule/src/Controller/CustomUserController.php
namespace Drupal\myModule\Controller;
use Drupal\user\Controller\UserController;
use Drupal\Component\Utility\Crypt;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
class CustomUserController extends UserController {
public function customResetPassLogin($uid, $timestamp, $hash) {
// The current user is not logged in, so check the parameters.
$current = REQUEST_TIME;
/** @var \Drupal\user\UserInterface $user */
$user = $this->userStorage->load($uid);
// Verify that the user exists and is active.
if ($user === NULL || !$user->isActive()) {
// Blocked or invalid user ID, so deny access. The parameters will be in
// the watchdog's URL for the administrator to check.
throw new AccessDeniedHttpException();
}
// Time out, in seconds, until login URL expires.
$timeout = $this->config('user.settings')->get('password_reset_timeout');
// No time out for first time login.
if ($user->getLastLoginTime() && $current - $timestamp > $timeout) {
$this->messenger()
->addError($this->t('You have tried to use a one-time login link that has expired. Please request a new one using the form below.'));
return $this->redirect('user.pass');
}
elseif ($user->isAuthenticated() && ($timestamp >= $user->getLastLoginTime()) && ($timestamp <= $current) && Crypt::hashEquals($hash, user_pass_rehash($user, $timestamp))) {
user_login_finalize($user);
$this->logger->notice('User %name used one-time login link at time %timestamp.', [
'%name' => $user->getDisplayName(),
'%timestamp' => $timestamp,
]);
$this->messenger()
->addStatus($this->t('You have just used your one-time login link. It is no longer necessary to use this link to log in. Please change your password.'));
// Let the user's password be changed without the current password
// check.
$token = Crypt::randomBytesBase64(55);
$_SESSION['pass_reset_' . $user->id()] = $token;
/**
* @TODO: change the route name to yours
*/
return $this->redirect(
'system.admin_content',
[],
[
'absolute' => TRUE,
]
);
}
$this->messenger()
->addError($this->t('You have tried to use a one-time login link that has either been used or is no longer valid. Please request a new one using the form below.'));
return $this->redirect('user.pass');
}
}
NOTE : change system.admin_content
by your route name.
You could try using hook_user_login() in a custom module or theme.
function my_module_user_login($account) {
// Get the end part of the URL.
$request_uri = \Drupal::request()->getRequestUri();
// Check if the URL is a reset / one time login link.
if (strpos($request_uri, 'user/reset') !== false) {
_my_module_custom_function();
}
}
function _my_module_custom_function() {
// Do stuff.
}