how to make a password hash laravel 5.8 - laravel

// method untuk insert data ke table d_rak
public function store(Request $request)
{
$data=new User();
$data->name=$request->get('name');
$data->username=$request->get('username');
$data->nip=$request->get('nip');
$data->level=$request->get('level');
$data->email=$request->get('email');
$data->password=$request->get('password');
$data->save();
return redirect ('/users')->with('alert-success','Berhasil Menambahkan Data!');
}

Try this
use Illuminate\Support\Facades\Hash;
$data->password= Hash::make($request->get('password'));

Simply use bcrypt helper.
$data->password = bcrypt($request->get('password'));
or Hash facade.
$data->password = Hash::make($request->get('password'));

For use in controller:
$request->user()->fill([
'password' => Hash::make($request->newPassword)
])->save();
And check if is the correct password
The check method allows you to verify that a given plain-text string corresponds to a given hash. However, if you are using the LoginController included with Laravel, you will probably not need to use this directly, as this controller automatically calls this method:
if (Hash::check('plain-text', $hashedPassword)) {
// The passwords match...
}

Related

Laravel - How to not pass unused parameter in controller

I have a route for example -
Route::get('/api/{user}/companies/{company}', [CompanyController::class, 'getCompanies'])
and a function in this controller
public function getCompanies(User $user, Company $company) {
$companies = $company->all();
return response()->json(['companies' => $companies]);
}
I am not using the $user instance in the function and I would like to not pass a User $user param in it, but I want that the route has user id as a param for clarity on the frontend.
I found a solution of using middleware with the forgetParameter() method but I don't want to add new middleware or declare it only for this route.
I can just leave that unused param in my function and everything will work just fine, but I am curious is there some elegant solution for this case.
public function getCompanies(Company $company, ?User $user = null)
{
return response()->json(['companies' => $company->all()]);
}
Pass $user to the last position and give it a default value
I think you can put a _ instead of passing a parameter, but I could be wrong.

Hash password after Validator::make

I want to hash the password after validating the data.
My code:
public function create(Request $request){
$data = Validator::make($request->only(['name', 'email', 'password']), [
'name' => 'required|min:3:max:20',
'email' => 'required|email|unique:users',
'password' => 'required|min:6',
]);
if ($data->fails()) {
//Do something
}else{
User::create($data);
}
}
So how to hash the password after validation?
I tried to override the password inside $data, But it's not working
$data->safe()->only('password') = Hash::make($data->safe()->only('password'));
I can't use $request['password'] as I won't be able to validate it and check if it's empty ..etc.
An alternative approach would be to use an Eloquent Mutator to automatically hash the password field when it is set.
// User Model
public function setPasswordAttribute($value): void
{
$this->attributes['password'] = Hash::make($value);
}
I personally like this approach because you won't have to worry about it in the controllers. You can just set it once and forget about it. :)
The quick answer to your question would be to use the Eloquent make function.
$user = User::make($data);
$user->password = Hash::make($password);
$user->save();
Where $password is where ever you have the password stored. In your case:
$password = $data->safe()->only('password')
There may be a more efficient way, based on your exact intent. In general, the above solution will work.
The make function creates an Eloquent model, but does not store it in the database. That's why you can edit the values and then call $user->save()
Use a mutator method to set the password. Override the method by adding:
public function setPasswordAttribute($value)
{
$this->attributes['password'] = 'some random password generator';
}
there is document:
https://laravel.com/docs/8.x/eloquent-mutators#defining-a-mutator

Laravel Socialite - Different Providers With Same Email - Security How to Fix

Ok so I read how to implement Laravel socialite into my application so I can let users log in using Google or Facebook. I read how to do it here. The problem I encounter with this approach is that if a user logs in from say Google with email myemail#example.com then logs in from Facebook using myemail#example.com they are logging into the same account! Security issue right. So I thought that before I let them log in I would check the provider id which you can get, however when I try to compare the provider_id that I store in the database when they create the account with the provider_id stored in the socialite user variable I get this error:
Argument 1 passed to Illuminate\Auth\SessionGuard::login() must implement interface Illuminate\Contracts\Auth\Authenticatable, instance of Illuminate\Http\RedirectResponse given
Here is all the code I am using for Socialite:
<?php
namespace App\Http\Controllers;
use Socialite;
use App\User;
use Auth;
use Illuminate\Support\Facades\Redirect;
use Flash;
use Illuminate\Http\Request;
use App\Http\Requests;
class SocialiteController extends Controller
{
public function redirectToProvider($provider)
{
return Socialite::driver($provider)->redirect();
}
public function handleProviderCallback($provider)
{
try
{
$social_user = Socialite::driver($provider)->user();
}
catch(Exception $e)
{
return Redirect::to('auth/' . $provider);
}
$authUser = $this->findOrCreateUser($social_user);
Auth::login($authUser, true);
flash()->overlay('You have been logged in successfully!', 'Congratulations');
return Redirect::to('/');
}
//create a new user in our database or grab existing user
private function findOrCreateUser($social_user)
{
if ($authUser = User::where('email', $social_user->email)->first()) {
//this creates an error
if($authUser->provider_id == $social_user->id)
return $authUser;
else
{
flash()->overlay('An account for that email already exists!', 'Error');
return Redirect::to('/');
}
}
return User::Create([
'provider_id' => $social_user->id,
'name' => $social_user->name,
'email' => $social_user->email,
'nickname' => $social_user->nickname,
'avatar_img' => $social_user->avatar,
'role_id' => 1, //set role to guest
'social_login' => true //tell the database they are logging in from oauth
]);
}
}
The error message is actually self explained.
When you do User::where('provider_id', $social_user->id) you end up with builder object that implements
Illuminate\Database\Eloquent\Builder.
You can call ->get() on it to get the collection of results
(a collection of objects that implements
Illuminate\Contracts\Auth\Authenticatable
in your case, so you can iterate over them), or as you did, you can get the first match with ->first() (one object that implement
Illuminate\Contracts\Auth\Authenticatable).
You can read more in the Eloquent documentation.
The main point is that until you call ->get() or ->first() you are working with builder object.
There is actually ->find() method also, that is used to retrieve record by pk, you cannot use it to search for records by constraints (where), but it also returns model object.
The problem I encounter with this approach is that if a user logs in
from say Google with email myemail#example.com then logs in from
Facebook using myemail#example.com they are logging into the same
account! Security issue right.
In my opinion, this is an incorrect assumption. It is not a security issue.
OAuth is used as an authentication delegation, if a user controls accounts in different providers with the same email, it simply means he has more 3rd party OAuth services with which to validate control of his identity (email)
I would consider it a bug, if you limited me to only be able to sign in with one OAuth provider, and prohibited me to user another one with the same email.

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.

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