LoginController
public function login(Request $request)
{
$request->validate([
'email'=>'required|exists:users',
'password'=>'required|exists:users',
]);
$email=$request->email;
$password=$request->password;
if (Auth::attempt(['email' => $email, 'password' => $password,'role'=>'admin'])) {
$token = $request->user()->createToken($request->email)->plainTextToken;
return response([
'token'=>$token,
'message'=>'Admin logged in successfully',
],200);
}
if (Auth::attempt(['email' => $email, 'password' => $password,'role'=>'user'])) {
$token = $request->user()->createToken($request->email)->plainTextToken;
return response([
'token'=>$token,
'message'=>'User logged in successfully',
],200);
}
return response([
'message'=>'Email or password is wrong',
],401);
}
I am creating a login API. So, I want to show email is wrong and password is wrong if the user or admin enters wrong email and wrong password. Here, when I enter the correct email and wrong password it displays only password is wrong error which is ok but when I enter the wrong email and correct password it shows two error messages that the email is wrong and the password is wrong. It should have shown only email is wrong error but why it is showing two errors can anyone explain it to me?
There are two type of validation rules in the laravel docs for this type of case.
exists - The field under validation must exist in a given database table.
'email' => 'exists:users,email'
unique - The field under validation must not exist within the given database table.
'email' => 'unique:users,email'
In both case specify the column name with a comma.
You cannot use exists in this way for checking the password. All you can do is check that it has been provided.
'password'=>'required|exists:users',
This will check that the supplied value is present in the password field of ANY user. Since the passwords are hashed, it would never match any user, never mind the user being checked.
As a security point, you should not indicate which of the items is wrong because this is a weakness and tells the person accessing the API that they have correctly guessed a username or a password.
Change both validations to required only and leave the Auth::attempt() to do the rest, returning the 401 if the credentials are not matched.
Related
I am confuse how can I validate a user's username if I am updating it. Here's the scenario, if I click a specific user in list of users page it will redirect into a page which has a form with user's data in the form. Now, I have:
public function updateUser(Request $request){
$this->validate($request, [
'username' => 'required|unique:users',
'name' => 'required|max:255'
]);
}
UPDATE
$this->validate($request, [
'name' => 'unique:roles,name,'.$request->id
]);
I know the part where 'username' => 'required|unique:users' is checking if the username exists in the users table, but what if I dont want to change/update the username, and I just want to update the other field, then it says that the username is already exists. How can I validate it in a right way.
Need help guys. This can also help others for this kind of problem.
Laravel will accept a new parameter for the key of the table. This should be the id of the element you would like to ignore in your query.
something like 'username' => 'required|unique:users,username,'.$request->get('id'),
You will have to pass the id variable in your request when updating.
Laravel documentation: https://laravel.com/docs/5.4/validation#rule-unique
You can also try using the Rule class (search for "Forcing A Unique Rule To Ignore A Given ID"), which was added in Laravel version 5.3.
You can see an example of usage of my answer in the documentation at:
https://laravel.com/docs/5.2/validation#rule-unique (search for "Forcing A Unique Rule To Ignore A Given ID")
Update as per question update:
$this->validate($request, [
'name' => 'required|unique:roles, name,'.$request->id
]);
you want to update profile and at that time you stuck with this error "username is already exists". so my suggestion is just remove the required validation from username if username is not updated then don't send it to server, so you no need to check whether it's exists or not in table and also if want to check particular column you can write like this
public function updateUser(Request $request){
$this->validate($request, [
'username' => 'unique:users,column-name',
'name' => 'required|max:255'
]);
}
in above case if we receive a username then we check it's uniqueness else not
You just need to check if the user exists or not
'username' => 'exists:users'
If the user exists in the database you will update it.
What wrong you are doing is: You are trying to update a user and validating that the username should be unique (this validation should be applied during user creation), that is not correct.
Thanks.
EDIT 1
Generally, username or email is a key column which you should not allow the user to update. Otherwise, this problem will always exist.
EDIT 2
I agree with the actual scenario that we can not assume that the username field will always remain same and the user can not update it. If the user is updating the username then you can try this code.
'username' => 'required|unique:users,username,'.$user->id
If your table uses a primary key column name other than id, you may specify it as the fourth parameter:
'username' => 'required|unique:users,username,'.$user->id.',user_id'
I have laravel 5.2 project and need to add Authentication, but I need to connect it to my table, that has Username and Password, also change default email/password to username/password. Also in my table passwords are not crypted.
I have change login.blade.php file from email field to username.
Also change user.php model:
protected $table = 'LoginTable';
Also change AuthController.php. Add this:
protected $username = 'username';
and change validator and create methods:
return Validator::make($data, [
'username' => 'required|max:255',
'password' => 'required|min:6|confirmed',
]);
return User::create([
'username' => $data['username'],
'password' => bcrypt($data['password']),
]);
But I cant login.It's saying 'These credentials do not match our records.'.
How can I check what is the problem? Can anyone help me with this issue?
UPDATE
I have change password to hashed password, but still cant make auth work.It is still saying:
These credentials do not match our records.
I want to mention that in Database I have only username and password, and dont have name and email.
If you are trying to authenticate with an existing user with an unencrypted password it won't work.
Laravel auth requires all passwords to be encrypted to pass validation. So first you'll need to update the database and encrypt all passwords with the same encryption key defined in config/app.php or in the .env file.
Also as a rule of thumb you should never ever keep clear text passwords in the database.
I'm new in Laravel. I try to make profile update page... all works good but if I try to apply rule to set email field unique:users I have problem when user try to update for example name and don't want change email.
public function rules()
{
return [
'name' => 'required|max:255',
'email' => 'required|email|max:255|unique:users',
];
}
I want restrict that user to use the same e-mail that someone else is using... but I want to ignore that if this is the same e-mail already in that user profile and he don't want to change that.
public function updateData(UpdateDataRequest $request)
{
DB::table('users')
->where('id', Auth::user()->id)
->update(array('email' => $request->email, 'name' => $request->name));
return redirect('panel');
}
How to do it right?
This exact situation is used as an example in the docs.
https://laravel.com/docs/5.2/validation#rule-unique
Forcing A Unique Rule To Ignore A Given ID:
Sometimes, you may wish to ignore a given ID during the unique check. For example, consider an "update profile" screen that includes the user's name, e-mail address, and location. Of course, you will want to verify that the e-mail address is unique. However, if the user only changes the name field and not the e-mail field, you do not want a validation error to be thrown because the user is already the owner of the e-mail address. You only want to throw a validation error if the user provides an e-mail address that is already used by a different user. To tell the unique rule to ignore the user's ID, you may pass the ID as the third parameter:
'email' => 'unique:users,email_address,'.$user->id
If your table uses a primary key column name other than id, you may specify it as the fourth parameter:
'email' => 'unique:users,email_address,'.$user->id.',user_id'
In new version. laravel using Rules to ignore a user or record
https://laravel.com/docs/5.8/validation#rule-unique
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($data, [
'email' => [
'required',
Rule::unique('users')->ignore($user->id),
],
]);
$user->id can be a specific id or the id of current user which is login
try to this validation(Laravel 8.x)
'email' => ['email:rfc','confirmed','unique:App\Models\User,email'],
There is an option available to login using the username or email fields at a time. But I would to login to site using both fields, username OR email,
means: if user input value is matched with username column or email column, then login to the system.
laravel 5.1 having trait AuthenticatesUsers contains this code. which only checks for single column.
$credentials = $this->getCredentials($request);
if (Auth::attempt($credentials, $request->has('remember'))) {
return $this->handleUserWasAuthenticated($request, $throttles);
}
Kindly guide me, login attempt for both column (email or username)
Assuming that you know how to validate the form field, just have username validation as well in your validation rules
Then in your controller validate the login like
if (Auth::attempt(['username' => $request->username, 'password' => $request->password])){
//suceess
}
elseif (Auth::attempt(['email' => $request->email, 'password' => $request->password])){
//logged in using email
}
else{
echo fail
}
Have a look at this thread as well
Hey trying to get a validation check working on a boolean field called 'activated'. Basically if the boolean is 1 then the account is active, meaning they can login. If it is anything else then users cannot login.
Here is my check from the User Model:
public $checkActive = array(
'activated'=>array(
'rule'=>array('equalTo', '1'),
'message'=>'The account must be activated, please check your email.'
));
Unfortunately users are able to login when they are not suppose to.
I believe that validation in models are only tested when data is being saved.
If you are using the Authentication component, you can define a 'scope' which is a condition which must equal true for the user to be authenticated.
'scope' => array('User.activated' => 1)
More info and an example: http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html)
If you have written your own authentication then you could add the condition to your current find statement.
$this->User->find('all', array('conditions' => array('username' => $username, 'password' => $password, 'activated' =>1);
Hope this answers your question.