Laravel force users to change password on first login attempt - laravel

Laravel 5.6 (5.7) force change password on first login attempt
In my project, I uploaded users in bulk by importing from excel with a default /general password for all users
The problem is, I have to write a script to force all users to change the password when they log-in for the first time.

The solution is that I have to add "password_changed_at" column to the users' table and in my home controller index I added this code below (since every new user is directed to home)
public function index()
{
if ((Auth::user()->password_change_at == null)) {
return redirect(route('change-password'));
}
else{
return view('home');
}
}
I did make use of change password of setting-up-change-password-with-laravel
but I added an update to the code which is below
//Change Password
$user = Auth::user();
$user->password = Hash::make($request->get('new-password'));
$user->password_change_at = \Carbon\Carbon::now(); //add new line of code
$user->save();

Related

Laravel retrieve deleted users multiple times

In my application, I have a button for deleting the account.
This is the function code:
public function deleteAccount()
{
$user = auth()->user();
auth()->logout();
request()->session()->invalidate();
request()->session()->regenerateToken();
$user->delete();
return redirect(route('login'))->with([
'status' => __('Your account has been deleted')
]);
}
I signed in with the same account with the "Remember" option on both Edge and Firefox browsers. When I click "Delete Account" on Edge, Laravel also dismisses me on Firefox because it deleted my account.
The problem is: On Firefox, Laravel is still trying to retrieve my account with Session and Cookies info because it hasn't been updated. And it runs again and again everywhere I use the auth() function.
How to avoid this? Or how do other sessions know that their information is out of date?
(I think it should only check once, like when it finds a user)
Demo code: https://github.com/tungwoodboi/demo-laravel-deleted-user
I found this in the SessionGuard class:
public function user()
{
if ($this->loggedOut) {
return;
}
// If we've already retrieved the user for the current request we can just
// return it back immediately. We do not want to fetch the user data on
// every call to this method because that would be tremendously slow.
if (! is_null($this->user)) {
return $this->user;
}
$id = $this->session->get($this->getName());
// First we will try to load the user using the identifier in the session if
// one exists. Otherwise we will check for a "remember me" cookie in this
// request, and if one exists, attempt to retrieve the user using that.
if (! is_null($id) && $this->user = $this->provider->retrieveById($id)) {
$this->fireAuthenticatedEvent($this->user);
}
// If the user is null, but we decrypt a "recaller" cookie we can attempt to
// pull the user data on that cookie which serves as a remember cookie on
// the application. Once we have a user we can return it to the caller.
if (is_null($this->user) && ! is_null($recaller = $this->recaller())) {
$this->user = $this->userFromRecaller($recaller);
if ($this->user) {
$this->updateSession($this->user->getAuthIdentifier());
$this->fireLoginEvent($this->user, true);
}
}
return $this->user;
}

Laravel - Change Password issue

I currently have a feature within my laravel application where a admin can create a new user account by filling in specific fields when you create the user it defaults the password value to password and is stored in the DB as a hash.
I've added a vue component for the password so it gives the admin the option to change to a custom password on creation.
My issue is when i want to add a custom password then click submit on creation of the user then try to login the custom password doesnt change but i can still login with the default password.
Store Method
public function store(Request $request)
{
$data = $request->all();
$data['name'] = $data['first_name'] . ' ' . $data['last_name'];
$data['password'] = bcrypt('password');
$data['change_password'] = true;
$user = User::create($data);
session()->flash('success', 'User created successfully.');
return back();
}
my guess is that the custom entered password isnt storing over the default password? can i get some help on this please.
You are assigning the password statically.
$data['password'] = bcrypt('password');
You need to change it to this.
$data['password'] = bcrypt($request->password);

Laravel 5 : Does Auth::user() query the database everytime I use it?

On the edit profile page for a user, I want to show the existing values of the current logged-in user details like name, email, gender etc. My questions are as follows
Is it recommendable to user Auth::user()->name , Auth::user()->email directly to populate the form fields ? Or shall I create a variable like $user = Auth::user(); in my controller and pass it on to my view to $user like a regular object?
Does using Auth::user(), multiple times on a given view file hit my database each time I use it?
Thanks in advance.
If you look at the SessionGuard.php file in Illuminate\Auth, you'll see the method user() which is used to retrieve the currently authenticated user:
/**
* Get the currently authenticated user.
*
* #return \Illuminate\Contracts\Auth\Authenticatable|null
*/
public function user()
{
if ($this->loggedOut) {
return;
}
// If we've already retrieved the user for the current request we can just
// return it back immediately. We do not want to fetch the user data on
// every call to this method because that would be tremendously slow.
if (! is_null($this->user)) {
return $this->user;
}
$id = $this->session->get($this->getName());
// First we will try to load the user using the identifier in the session if
// one exists. Otherwise we will check for a "remember me" cookie in this
// request, and if one exists, attempt to retrieve the user using that.
$user = null;
if (! is_null($id)) {
if ($user = $this->provider->retrieveById($id)) {
$this->fireAuthenticatedEvent($user);
}
}
// If the user is null, but we decrypt a "recaller" cookie we can attempt to
// pull the user data on that cookie which serves as a remember cookie on
// the application. Once we have a user we can return it to the caller.
$recaller = $this->getRecaller();
if (is_null($user) && ! is_null($recaller)) {
$user = $this->getUserByRecaller($recaller);
if ($user) {
$this->updateSession($user->getAuthIdentifier());
$this->fireLoginEvent($user, true);
}
}
return $this->user = $user;
}
// If we've already retrieved the user for the current request we can just return it back immediately. We do not want to fetch the user data on every call to this method because that would be tremendously slow.
if (! is_null($this->user)) {
return $this->user;
}
So, calling the user() multiple times won't make multiple calls to the database.
You'll get only 1 request to database, so using Auth::user() multiple times is not a problem.
I recommend you using Laravel Debugbar as the most comfortable way for app optimization.

Cartalyst Sentry and registration user

It is possible to create user from Admin panel, by administrator without password? I imagine follow procedure:
Administrator create user without password
User get email with instruction for entering password and activation account
User can register with email and his password
I don't think so. That's why when I create my users I generate a random password.
$user->password = str_shuffle("Random_Password"); // generate random initial password
I have done this before by hacking the 'forgotten password' functionality of Laravel (rather that reinventing the wheel). I can't say how well this fits into Sentry but it was pretty trivial to do it in plain old Laravel:
Create user with blank password
Add an entry into the password reminders table (manually, don't use Auth::remind or whatever it is as it'll send an email, but do use the code from the class to generate the token)
Send welcome email to user with link to /user/confirm (or whatever, the point is that it doesn't have to be /user/forgotten-password) and hook that route up in the normal way for forgotten password with an added check for $user->password == '' if you wanna make sure only unconfirmed people can go to that page (not that it really matters).
You may also wish to extend the timeout on the forgotten passwords or, as I did (proper hacky I know), when the user's in the /user/confirm version of the forgotten password functionality, just refresh the timeout in the table before passing through to Laravel's auth system for checking.
Our code is something like this:
On register:
// however you register the user:
$user = new User;
$user->email = Input::get('email');
$user->password = '';
$user->save();
// create a reminder entry for the user
$reminderRepo = App::make('auth.reminder.repository');
$reminderRepo->create($user);
Mail::send(
'emails.registered',
[
'token' => $reminder->token,
],
function ($message) use ($user) {
$message->to($user->email)->setSubject(Lang::get('account.email.registered.subject', ['name' => $user->name]));
}
);
Now the confirm link:
class AccountController extends Controller
{
public function confirm($token)
{
$reminder = DB::table('password_reminders')->whereToken($token)->first();
if (! $reminder) {
App::abort(404);
}
// reset reminder date to now to keep it fresh
DB::table('password_reminders')->whereToken($token)->update(['created_at' => Carbon\Carbon::now()]);
// send token to view but also email so they don't have to type it in (with password reminders it's is a good thing to make users type it, but with confirm account it feels weird)
return View::make('account.confirm-account')->withToken($token)->withEmail($reminder->email);
}
public function postConfirm($token)
{
$credentials = Input::only('email', 'password', 'password_confirmation', 'token');
$response = Password::reset($credentials, function ($user, $password) {
$user->password = $password;
$user->save();
});
switch ($response) {
case Password::INVALID_PASSWORD:
case Password::INVALID_TOKEN:
case Password::INVALID_USER:
return Redirect::back()->withInput()->with('message-error', Lang::get($response));
case Password::PASSWORD_RESET:
Auth::login(User::whereEmail(Input::get('email'))->first());
return Redirect::route('account.home')->with('message-info', Lang::get('messages.confirm_account.succeeded'));
}
}

Fire event on Eloquent User Model password property update

I have a User model with a password property.
If I retrieve it from the Database using:
$user = User::find(3);
And change the password value(in Controller):
$user->password = Input::get('passwordValue')
I want to trigger the Eloquent updating event that will first create a salt and concatenate the $salt with $passwordValue before assigning the value to $user->password something like:
$user->password = md5($salt . $passwordValue)
After this I can save the $user:
$user->save();
I want this event to fire every time the user changes his password in his profile page.
You can define a setter for the password field in your model:
public function setPasswordAttribute($value)
{
$salt = 'whatever';
$this->attributes['password'] = md5($salt.$value);
}
Then, in your controller (or whatever) code, just set the password using the plaintext version:
$user->password = Input::get('new_password');
However, it should be noted that, in Laravel, you really shouldn't be setting the password by using md5 with a salt, but instead use the hashing functions that Laravel provides:
$this->attributes['password'] = Hash::make($value);
That'll create a much stronger, bcrypt-generated password. You do, however, have to change the way you check the password, though it's pretty simple:
if (Hash::check($plaintext_password, $user->password)) {
// password is correct
}
However, further to this, you should use the Auth functions to handle logins so you don't even need to use Hash::check() directly:
if (Auth::attempt(array('username' => Input::get('username'), 'password' => Input::get('password'))) {
// logged in, redirect
} else {
// attempt failed, set message and redirect
}

Resources