Login stops working after changing the input field name "email" to "login-email" - laravel

I am developing a Laravel 6.6.2 project and I came across this problem I can't seem to fix.
In the file login.blade.php view i'm trying to change name="email" in the input fields to name="login-email". But when I do this the login doesn't work anymore. So I think that Laravel uses the name email somewhere to validate the login. I can't find where Laravel looks for the name email instead of login-email and if this even is needed to change?
The reason I need to change this is because javascripts use the name value too. (Because I brought a template). I am still learning Laravel so don't be to harsh. Thanks in Advance.

Laravel has excellent documentation. This is always a good place to start.
# Authenticating
https://laravel.com/docs/6.x/authentication#included-authenticating
Username Customization
By default, Laravel uses the email field for authentication. If you would like to customize this, you may define a username method on your LoginController:
In your case, you would return login-email from the username method.
public function username()
{
return 'login-email';
}
Of course, you will also need to add or rename this field in the database if you haven't already.
Alternatively to renaming the field in the database, you could override the credentials method.
protected function credentials(Request $request)
{
return [
'email' => $request->{$this->username()},
'password' => $request->password,
];
}

Related

Cannot test laravel livewire model hidden attribute with assertSet

I have a simple LIvewire component consisting of a form to create a new User, and it work, i can tell since i've been asked to write tests after the project already reached staging.
The Livewire component use a new User instance (non presisted, i.e. user->exists is false) to store inserted data before persisting it, and the user model hides the password attribute trough the protected $hidden array.
Now, i can sucesfully create new users trough the form page in my local environment, but when it comes to testing, it gives me error.
The test
Livewire::test(
FormComponent::class,
)
->set('user.name', 'user name')
->set('user.email', 'user#email.com')
->set('user.password', 'password')
->assertSet('user.name', 'user name')
->assertSet('user.email', 'user#email.com')
->assertSet('user.password', 'password');
The error
Failed asserting that null matches expected 'password'.
What i find out
Setting my compoment user instance trough the form page goes fine because livewire recognize it as a model, so do something like user->password = 'password', while when setting it from the test with set() it access its property with the access operator as it is an array, i.e.: user['password] = 'password'.
Commenting out the password entry in the $hidden array made the test pass.
This will explain the difference in the property setting.
Conclusion
Since the $hidden array is meant to hide model properties in its array/json representation it should not interfere with automated tests, moreover when using Livewire own methods, so to me this looks like a LIvewire Bug.
Help
Does anyone have aver encountered this bug?
Update#1
I've opened an issue on Livewire github page for this.
You have diagnosed this pretty well. When Livewire serializes the User model, password is not included because it is in the $hidden array. Even though the User model has not been persisted yet, serialization is the same.
I would guess that your input fields all use the defer modifier, which is why your fields are working in the browser; however, when you call set() in the test, it simulates a Livewire request, so the $hidden attributes are being wiped.
An alternate assertion for testing the password is my recommendation here. Try asserting that the created user can login with the selected password.
$this->assertTrue(
auth()->attempt(['email' => 'user#email.com', 'password' => 'password'])
);

laravel separate Login Errors

when we use laravel after enter email and password and when our email or password pr both of them are wrong, the laravel tell us just one message for all probably situations , i just want to separate the errors , e.g your password is wrong or your email not found or we cannot find this user etc.
i just customize the auth.php file in lang folder and set this :
'failed' => 'Login Failed!!',
i want to add more condition for my login errors
please help me to do this task
thanks for your helping :)
Not a good idea to do it separately in terms of protecting the privacy of the users, because the general error message doesn't categorically inform the potentially malicious person or bot that "You found the right email, now all you have to guess is the password".
The simple way is adding exists:users validation to the validateLogin method of AuthenticatesUsers trait by overriding it on Login Controller:
// app\Http\Controllers\Auth\LoginController.php
use Illuminate\Http\Request;
protected function validateLogin(Request $request)
{
$request->validate([
$this->username() => 'required|string|exists:users',
'password' => 'required|string',
]);
}
It will check if the entered username (by default email) exists on users table or not.
It not a good idea to separate both as it will let others know which section or input they entered wrong.
You can add on the message of login failed!!! but dont let the user know which part they entered wrongly.

Laravel Socialite - Use socialite to fill in fields and redirect back to the form without losing other information

I have a website, which has a form. Within the form, I have a button linked to socialite where a user can click on it and it will retrieve the name and email from Facebook. Then, I redirect the user back to the form to either fill in the remaining information or submit the form.
However, all of the other information is lost upon return to the page.
I have tried to pass a 'Request $request' within the function. However, it never actually gets the information as the button isn't exactly submitting the form.
Is there any way of ensuring that the previous information is pushed through to the Route and that this information is then pushed back to the redirect?
Here is my code so far:
web.php
Route::get('login/{service}', 'Auth\LoginController#redirectToProvider')->name('social');
Route::get('login/{service}/callback', 'Auth\LoginController#handleProviderCallback');
LoginController.php
public function handleProviderCallback(Request $request, $service)
{
$user = Socialite::driver($service)->stateless()->user();
return redirect()->back()
->with(['social' => 'social', 'name' => $user->name, 'email' => $user->email])
->withInput($request->all);
}
(Note: within the view, I am, of course, using {{ old('input_name') }} to get the inputs whenever the form fails after submission.)
Is there any way to get the information from Socialite and return back to the form without losing the previous information?
All suggestions, help, and comments are highly appreciated :)
Thanks!!
The problem is when the user is redirected to social provider, say facebook, the form data will not in that request, so when facebook redirects to the callback you will not find the form data there! ( facebook will not carry it for you )
You likely need to use some javascript here. look at hellojs

Laravel - user login

I use Laravel 5.4 and need to login user in my system. I have next login.blade.php
where i have email and password field. In my controller I have next
protected function log() {
$email=Input::get('email');
$pass=Input::get('password');
$user = DB::select("SELECT * FROM users where email = '".$email."' and password = '".$pass."'");
foreach($user as $users){
if(Input::get('email') == $users->email){
return redirect('/');
}else{
return view('site.warning');
}
}
}
How can I return logged user in my redirect('/') and show them in my site.
Any idea?
Use the attempt() method:
if (Auth::attempt(['email' => $request->email, 'password' => $request->password])) {
From the docs:
The attempt method accepts an array of key / value pairs as its first argument. The values in the array will be used to find the user in your database table. So, in the example above, the user will be retrieved by the value of the email column. If the user is found, the hashed password stored in the database will be compared with the password value passed to the method via the array.
This method will work for you if you're using bcrypt() or Hash::make() to generate password hash.
Please do not create your own login system!
Now that's out of the way the explanation.
There is (almost) no good reason to create your own login system, as your code already showed. Your current code is very VERY insecure due to storing passwords in plain text. Please read up on resent security advice.
The even better option is using Laravels build-in auth.
https://laravel.com/docs/5.4/authentication
If you do try to use this build-in authentication methods you will be able to get the current authenticated user by using Auth::user() this can be used in your blade files as well as in your controllers.
You cannot (maybe you can) but you certainly should't store user's password unhashed. Laravel has build artisan command: php artisan make:auth. You may use it, and retrieve him in the show method for example (thro the URL, passing id). Or just retrieve him via Auth::user(). Planty of choices.

handle $errors and old input with 2 forms in a single page

I'm using laravel 5.2.
I'm trying to have 2 similar forms in one single page, one for registering, and one for logging in.
The problem is after some validation error, i can't recognize which one of the two was submitted to place some errors display and fill the correct form with the old input.
I had the idea of trying sending an hidden variable with the forms to recognize which one of the two was used, but when i get back to the forms page i can't retrieve the old('hidden_field').
I also tried to get the path of the referer page to check if i could recognize them from it, but it doesn't work.
Any different idea for a solution??
I. Deal with old input
- Make 1 attribute with different name in those 2 forms. So you can use old() normally
II. Deal with $errors. Use named error bag
- In your Controller
public function postRegister(Request $request){
$validator = Validator::make($request->all(), $array_rules);
if ($validator->fails()){
return redirect('url')->withErrors($validator, 'form_register');
}
}
public function postLogin(Request $request){
$validator = Validator::make($request->all(), $array_rules);
if ($validator->fails()){
return redirect('url')->withErrors($validator, 'form_login');
}
}
- In your view
//Access each form's errors normally
$errors->form_login->all()
$errors->form_register->all()
// Use old input normally
old('name_register');
old('name_login');
Hope this help you.
Thanks to a suggestion in the comments, i found out i had to add a validation rule to my hidden input field in order to pass it again to the view, and get the value with the old() method.
I could use it then to recognize which one of the two forms has been used.

Resources