Fire event on Eloquent User Model password property update - laravel

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
}

Related

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 - reset password for multiple accounts

I am using Laravel's "reset password".
There is something particular in our architecture: several accounts can have the same email address, the login is the unique key.
I would like to change the password reset controller so that, in password reset view:
- if the user put its email, the password is set for all accounts with this email (should I do it in a middleware? now only a random account is set, the first one I guess)
- if the user put its login, we change the password of its login only
Do you think this is possible? (for new accounts it will be impossible to create a new account with an existing email, but now we have about 8000 users with double email accounts, so this cannot be changed unfortunately).
thanks a lot in advance for your advices!
here is my code and I don't know where to start
[EDIT]
Here is my code after Mostakim Billah's suggestion:
I rewrote the existing resetPassword et reset function (let them as they were) and added the //HERE part
public function reset(Request $request)
{
$request->validate($this->rules(), $this->validationErrorMessages());
$response = $this->broker()->reset(
$this->credentials($request), function ($user, $password) {
$this->resetPassword($user, $password);
}
);
return $response == Password::PASSWORD_RESET
? $this->sendResetResponse($request, $response)
: $this->sendResetFailedResponse($request, $response);
}
protected function resetPassword($user, $password)
{
$user->password = Hash::make($password);
$user->setRememberToken(Str::random(60));
$user->save();
// HERE: set passwords for other users with the same email
**User::where('email', $user->email)
->where('login', '!=', $user->login)
->where('password', null)
->update(['password' => Hash::make($password)]);**
event(new PasswordReset($user));
$this->guard()->login($user);
}
You can override reset method(which is in ResetsPasswords trait) in ResetPasswordController class and do whatever you want in this method.

Why Laravel `bcrypt` or Hashing a random string password is mismatched when checking?

I am generating a random string which I want to save or update as new password to an existing user on a Laravel app.
This is how I do it in my controller:
public function changePassword(){
// Generate new Password
$newPassword = bin2hex(openssl_random_pseudo_bytes(16/2, $crypto));
$user = Auth::user();
$user->password = bcrypt($newPassword);
$user->save();
if(Hash::check($newPassword, $user->password)){
return response($user);
}
return response('Password Mismatched', 401);
}
The response is giving me the "Password Mismatched" 401 error. Why
is it that it gives me a mismatched password?
Depending on how your User model is set up, it may be calling bcrypt() or Hash::make() on the password attribute automatically, which, when combined with manually calling the function results in a "hash of a hash" situation. To avoid thing, simply remove the manual call to the function and allow the User model to handle it automatically:
$user = Auth::user();
$user->password = $newPassword;
$user->save();
use Hash::make() while saving password to db like this,
public function changePassword(){
// Generate new Password
$newPassword = bin2hex(openssl_random_pseudo_bytes(16/2, $crypto));
$user = Auth::user();
$user->password = Hash::make($newPassword);
$user->save();
if(Hash::check($newPassword, $user->password)){
return response($user);
}
return response('Password Mismatched', 401);
}
This might work.

Hash::check() return false in laravel 5

I'm just starting with laravel 5, I'm doing a simple login function to check if email and password passed by user matches with the email and password stored in the database. I've been reading the documentation ([https://laravel.com/docs/5.0/hashing1) but Hash::check($content['password'], $user->{'password'}) returns false always. My code looks like this.
When I create a new user I hash the password like that:
$content = json_decode($request->getContent(), true);
$user -> password = Hash::make($content['email']);
And my login function looks like that:
public function login(Request $request)
{
$content = json_decode($request -> getContent(), true);
$user = DB::table('users')->where('email', $content['email'])->first();
if (Hash::check($content['password'], $user->{'password'}))
{
// Redirect to dashboard
}
}
Thanks in advance!!
Actually you are hashing the email instead of password while creating the user. change the code from
$user->password = Hash::make($content['email']);
To
$user->password = Hash::make($content['password']);
i came up with same issue. check database users table, password field. make the size of the field to 60 or more. this fixed mine.
The facade Hash just will encrypt your data:
Hash::make('123456');
is the same that:
$password = bcrypt('123456');
to login a user you need to use AuthController functions:
Auth::attempt(['email' => 'test#test.com' , 'password' => Hash::make('password')]);
it's a example.
If you're receiving a request, you can add this method to login:
if(Auth::attempt(['email' => $request->email, 'password' => $request->password , 'active' => 1])){
flash()->success('Successfully logged in!');
return redirect('/');
}
the attempt function will hash your password field and will compare with database data.

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'));
}
}

Resources