Password verify always returns fail in Laravel (Hash::check) - laravel

I've got an issue when I try to validate the post password via Hash::check in Laravel 5.5
I made a posts table (in this case sales table) with password column. When I try to create the post, it's working perfectly and the password is hashed and also belongs to logged in User. Then on the current post page is a button with an input (password) to delete that specific post, but the condition is always false.
My Controller public function destroy(Request $request, $id)
$input_pass = request('input_password');
$sale = Sale::find($id);
$hashed = $sale->password;
// Check if sale password is correct
if (Hash::check($input_pass, $sale->password)) {
$sale->delete();
} else {
// something else to do
}
For the post store, I used bcrypt method to hash the password. I've been also trying to dd('sale->password') which refers to column in sales table (correct) and dd('$input_pass') which refers to typed in password in DELETE form (also correct) - so I'm a little bit confused, why the pass don't match.

From your comment I find that you have a logical error where you initially hash your password and persist it in DB.
You are passing the string password to bcrypt where it should actually be something like request('password')
Change
'password' => bcrypt('password'),
to
'password' => bcrypt(request('password')),

Related

Laravel 5.6 - Reset Password Tokens how to ensure they match?

When a user forgets their password and try to reset it, they get a reset password email link with a token:
site.com/my/password/reset/ddc3669ab1bbd78abe620ef910716ae91678bb4beb5cd8896e21efaaa0c9d5c6
On the backend though, the token in the database password_resets table looks like it's hashed:
$2y$10$O6pgU21FhsOcgpgeqR8RReFYoCGhHNBH5bHKxtE6q1tJMTUufrbr.
So when the route is visited, the only piece of identifying information passed is the token:
ddc3669ab1bbd78abe620ef910716ae91678bb4beb5cd8896e21efaaa0c9d5c6
// Controller Method
passwordResetVerifyByToken($token){
$record = DB::table('password_resets')->where('token', $token)
->first();
}
Ofcourse we won't get a record, as the plain token from the email will NOT match the hashed one in the database with the above query. So with the plain emailed token link, when the user clicks it, how can we compare it to the one in the database to verify it exists and is a matching token?
You should use the Hash::check method, which will return true or false depending of if the hash of the reset token matches the stored database value.
if (Hash::check($token, $row->token)) {
// The passwords match...
}
Laravel docs:
https://laravel.com/docs/5.6/hashing#basic-usage
Dont worry Laravel Have there own advanced function Hash you should try this
if (Hash::check($token, $row->token)) {
// write your code or other function
}

Make email authentication case insensitive in Laravel 5.7

I use the default email authentication in Laravel 5.7.3 (just updated from 5.4) with a sqlite DB. At login my email address gets validated case sensitive which is not what I want. It should be allowed to login with "JohnDoe#foobar.com" as well as "johndoe#foobar.com".
I've tried to add an accessor at my user model to always lowercase the database value.
public function getEmailAttribute($value) {
return strtolower($value);
}
But this one doesn't seem to be used by Auth at all. Additionally I don't know where to change the user input in the incomming request to lower case.
Is there a simple config case sensitive switch? Or where do I need to change/add scripts?
Thanks for your support
Daniel
Your accessor should be fine, but you should make sure that you also lowercase the given value, e.g. In your controller:
Assuming that you're using the default LoginController shipped from Laravel:
I overwrote the credentials method from AuthenticatesUsers in App\Http\Controllers\Auth\LoginController
protected function credentials(Request $request)
{
$credentials = [
$this->username() => strtolower($request->get($this->username())),
"password" => $request->get("password")
];
return $credentials;
}
This works fine, when all emails stored in the database are already stored all-lowercase. If you're starting from scratch you can enforce the emails to be stored lowercase by default. Just implement the following mutator in your App\User:
public function setEmailAttribute($value)
{
$this->attributes['email'] = strtolower($value);
}
If you have stored mixed-case email already, you can update all emails to lowercase emails using this query:
UPDATE users SET email = LOWER(email);
But this still feels kind of incomplete and you maybe don't want to manipulate your data this way. I am pretty much sure that there are more possibilities to make this happen but unfortunately I am not able to dig into this further for now. However my next attempt would be to extend/write a custom UserProvider.
You have to call getEmailAttribute(/your email here/)
before login and signup like this
$request->email = getEmailAttribute($request->get('email'));

laravel login with remember me feature without field in the database

I'm developing a website using Laravel with an existing database.
My User table doesn't have a remember me field. But I want users always login with remember me feature. Can anyone help?
"Remember me" functionality NEEDS a field in DB. Actually you have to store the "remember me" cookie somewhere in your program. Where is a better place than DB to do this??
First you have to add remember_token (100-character string) to your Users table in database which will be used to store the "remember me" token.
In the next step, On your login attemp you must add $remember parameter like this:
if (Auth::attempt(['email' => $email, 'password' => $password], $remember)) {
// The user is being remembered...
}
after this code, your user will be remembered by his remember cookie. SO he can be remembered like this:
if (Auth::viaRemember()) {
//
}
Anyway, if you want to store the remember_token in another table, you have define a model like RememberToken and add this relationship to your Users model:
public function rememberToken() {
return $this->hasOne('RememberToken'); // also add foreign keys
}
And now some overriding is needed!. First override getRememberToken() and setRememberToken() methods and also you need to override getRememberTokenName().
As a result EloquentUserProvider::retrieveByToken() should be changed in EloquentUserProvider class. You probably have to make your User model to join remember_tokens table on every query by adding global scope to it, and return 'remember_tokens.token' from getRememberTokenName() method.
Is it really necessary by the way?

Laravel Authentication With Two Tables

I am trying to use Laravel's built-in Authentication class. Upon reading it, it seems that it only looks into one table as per the config/auth.php file. As per the doc, I can use syntax like this:
if (Auth::attempt(['email' => $email, 'password' => $password, 'active' => 1])) {
// The user is active, not suspended, and exists.
}
My concern is, the email column is in my user table while password is in auth table. As I stated above, my understanding of Laravel's authentication is it only looks for one table only. Did I miss something?
Actually the solution is fantastically simple. You just need to override the getAuthPassword method which is defined in the Authenticatable trait, by adding this to your User model:
public function getAuthPassword()
{
return \DB::table('auth')->where('user_id', $this->id)->pluck('password');
}
And that's it, now the authentication system will get the password from the auth table before checking if it matches with user input.
You can authenticate user manually.
Retrieve user from your user table by email with his password from
auth table (via simple join or eloquent relations).
Validate that password is correct using \Hash::check($password, $hashedPassword); .
Login user manually usingAuth::login($user); if you are using Eloquent or Auth::loginUsingId($id); if simple DB query.
Docs:
Auth http://laravel.com/docs/5.1/authentication#other-authentication-methods
Hash http://laravel.com/docs/5.1/hashing

How to "Refresh" the User object in Laravel?

In Laravel you can do this:
$user = Auth::user();
Problem is, if I do changes on items on that object, it will give me what was there before my changes. How do I refresh the object to get the latest values? I.e. To force it to get the latest values from the DB?
You can update the cache object like this.
Auth::setUser($user);
for Example
$user = User::find(Auth::user()->id);
$user->name = 'New Name';
$user->save();
Auth::setUser($user);
log::error(Auth::user()->name)); // Will be 'NEW Name'
[This answer is more appropriate for newer versions of Laravel (namely Laravel 5)]
On the first call of Auth::user(), it will fetch the results from the database and store it in a variable.
But on subsequent calls it will fetch the results from the variable.
This is seen from the following code in the framemwork:
public function 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;
}
...
}
Now if we make changes on the model, the changes will automatically be reflected on the object. It will NOT contain the old values. Therefore there is usually no need to re-fetch the data from the database.
However, there are certain rare circumstances where re-fetching the data from the database would be useful (e.g. making sure the database applies it's default values, or if changes have been made to the model by another request). To do this run the fresh() method like so:
Auth::user()->fresh()
Laravel does do that for you, HOWEVER, you will not see that update reflected in Auth::user() during that same request. From /Illuminate/Auth/Guard.php (located just above the code that Antonio mentions in his answer):
// If we have already retrieved the user for the current request we can just
// return it back immediately. We do not want to pull the user data every
// request into the method because that would tremendously slow an app.
if ( ! is_null($this->user))
{
return $this->user;
}
So if you were trying to change the users name from 'Old Name' to 'New Name':
$user = User::find(Auth::user()->id);
$user->name = 'New Name';
$user->save();
And later in the same request you try getting the name by checking Auth::user()->name, its going to give you 'Old Name'
log::error(Auth::user()->name)); // Will be 'Old Name'
A little late to the party, but this worked for me:
Auth::user()->update(array('name' => 'NewName'));
Laravel already does that for you. Every time you do Auth::user(), Laravel does
// 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))
{
$user = $this->provider->retrieveByID($id);
}
It nulls the current user and if it is logged, retrieve it again using the logged id stored in the session.
If it's not working as it should, you have something else in your code, which we are not seeing here, caching that user for you.

Resources