Force password reset on first login

Hello. I need to be able to create users through admin panel and force password reset on the user first login. I've already implemented email verification so I would need to request the password reset directly after verifying the email. What would be the best way to force password reset? I'm not sure if I should add a flag on the DB for the user table perhaps. Any help and comment is appreciated. Thanks.
8 Replies
Dan Harrin
Dan Harrin14mo ago
you could add a flag to their account and then use middleware to send them to the Profile page or something
Jean Roumeau
Jean Roumeau14mo ago
Ok. That seems clean. And would you hook to the "Forgot password" flow?
Brian Kidd
Brian Kidd14mo ago
You could also set a default password when creating the user and then trigger a password link to be emailed to them. If your app has Fortify, you can do
Password::broker(config('fortify.passwords'))->sendResetLink(['email' => $email]);
Password::broker(config('fortify.passwords'))->sendResetLink(['email' => $email]);
Jean Roumeau
Jean Roumeau14mo ago
Indeed. Its just that I've enabled email verification also so the user would receive two emails (first to verify and then to reset password) which is not as smooth as I would like.
Dan Harrin
Dan Harrin14mo ago
forgotten password isnt for authenticated users which is why i suggested to send them to the profile page where they can also change their password
Brian Kidd
Brian Kidd14mo ago
My new users signup through a Stripe payment link and I listen for the checkout webhook where I create all initial data, send an email to the new user stating “check your email for a link to set your password” then I trigger the action above. If they get the link and reset their password, haven’t they essentially verified their email address? If he’s creating them in the admin panel, they aren’t authenticated yet, are they? I’m under the impression he’s creating them and having to provide an initial password but maybe I’m not reading this right.
Jean Roumeau
Jean Roumeau14mo ago
Indeed. Users aren't authenticated. But actually i'm not sure if email verification logs the user in. (need to check that)
cheesegrits
cheesegrits14mo ago
I do this in one of my apps, with Fortify. I send a reset link the way Brian showed when creating the user (with a random password), and at the same time I set a session variable ('cotak.password.create') ...
session(['cotak.password.create' => true]);
$broker = Password::broker(config('fortify.passwords'));
$status = $broker->sendResetLink(
['email' => $user->email]
);
session(['cotak.password.create' => true]);
$broker = Password::broker(config('fortify.passwords'));
$status = $broker->sendResetLink(
['email' => $user->email]
);
... then in my AuthServiceProvider boot() I have this ... which checks to see if that session variable is set, and if so it changes the wording of the email if that session variable is set (and if not, uses the default password reset verbiage) ...
ResetPassword::toMailUsing(function ($notifiable, $token) {
$url = route('password.reset', $token) . '?email=' . $notifiable->getEmailForPasswordReset();
$interval = CarbonInterval::minutes(config('auth.passwords.' . config('auth.defaults.passwords') . '.expire'))->cascade()->forHumans();

if (session()->has('cotak.password.create')) {
session()->forget(['cotak.password.create']);

return (new MailMessage)
->subject(Lang::get('Create Password Notification'))
->greeting(Lang::get('Welcome to COTAK!'))
->line(Lang::get('You are receiving this email because a COTAK account has been created for this email address.'))
->action(Lang::get('Create Password'), $url)
->line(Lang::get('Please create a password. This password create link will expire in :count.', ['count' => $interval]))
->line(Lang::get('If you do not create a password within this timeframe, your agency administrator will have to send a "Reset Password" link'))
->line(Lang::get('If you did not request an account, no further action is required.'));
} else {
// default verbiage goes here
}
});
ResetPassword::toMailUsing(function ($notifiable, $token) {
$url = route('password.reset', $token) . '?email=' . $notifiable->getEmailForPasswordReset();
$interval = CarbonInterval::minutes(config('auth.passwords.' . config('auth.defaults.passwords') . '.expire'))->cascade()->forHumans();

if (session()->has('cotak.password.create')) {
session()->forget(['cotak.password.create']);

return (new MailMessage)
->subject(Lang::get('Create Password Notification'))
->greeting(Lang::get('Welcome to COTAK!'))
->line(Lang::get('You are receiving this email because a COTAK account has been created for this email address.'))
->action(Lang::get('Create Password'), $url)
->line(Lang::get('Please create a password. This password create link will expire in :count.', ['count' => $interval]))
->line(Lang::get('If you do not create a password within this timeframe, your agency administrator will have to send a "Reset Password" link'))
->line(Lang::get('If you did not request an account, no further action is required.'));
} else {
// default verbiage goes here
}
});