Trying to figure out how to use Laravel's Hash and Auth class in a login function. When my user registers, I use this:
$password = Hash::make(Input::get('password'));
The result is stored in the database table. In the login function, I want to check if password and email are valid, so I do this:
if (Auth::attempt(array('email' => $email, 'password' => $password, 'activated' => 1)))
But the password in Auth::attempt is plain text. What should I pass there for it to compare with the version stored in table (result of Hash::make()) previously.
Auth::attempt will automatically do the hashing for you. Just pass it the password (from input)
Related
enter image description here
I can create the user in the database but unlike the ones that exist that were added with seed it doesn't have an encrypted password and doesn't have a token, I need to generate the token to stop the user when he registers
enter image description here
use bcrypt for password hash and use random str for token before save data.
example:
User::create([
'email' => $request->email,
'password' => bcrypt($request->password),
'token' => Str::random(80)
]);
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.
I'm struggling myself trying to find the reason but can't. It always falss to "else". I'm using sqliteand this is my code:
public function doLogin(Request $request)
{
$email = $request['email'];
$password = $request['password'];
if ( Auth::attempt(['email' => $email, 'password' => $password]) )
return redirect()->route('home');
return redirect()->back();
}
route
Route::post('/doLogin',['as' => 'doLogin', 'uses' => 'Auth\LoginController#doLogin']);
Already printed the variables, the values are exatcly the same as the database.
Possible cause of the problem ?
Testing the Variable Receiving Value (Prints the right values)
$usuario = \App\User::find(1)->pluck('email', 'password');
return ($usuario);
Printed Value:
{"teste123":"teste#teste.com"}
Also, If I try this:
public function doLogin(Request $request)
{
$email = $request->input('email');
$password = $request->input('password');
dd($request->all());
}
I get this:
array:4 [▼
"_token" => "xxxxxxxxxxxxxxxxxxxxxxxxxxx"
"email" => "teste#teste.com"
"password" => "teste123"
"action" => null
]
Is it normal action = null ?
It looks like you're storing your passwords in your database as plaintext, and that seems to be the issue. You should never do this, as if you have a security leak, then the infiltrator could easily have access to all of your users' passwords.
That also seems to be the issue as to why your Auth::attempt is failing. Auth::attempt goes into SessionGuard.php, which eventually calls validateCredentials from EloquentUserProvider.php. This function hashes the password it is given and checks that against what is in the database. Laravel is expecting your password in the database to be hashed (by default it is bcrypt), so the passwords are not matching. It hashes the plaintext password from the $request so it no longer matches the plaintext in your DB.
Laravel comes with the command php artisan make:auth. If you use this, then you shouldn't have to do your doLogin function. You can just send the logins along the default route. Then when you're testing, sign up your account through the registration to ensure that it's saved in your database in a hash, instead of plaintext.
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 find it difficult to wrap my head around the password grant authentication process.
What I'm trying to achieve: A mobile device sends the username and the password of a registered user to the API and gets the access token as a response in JSON form.
What I've achieved so far: The API receives the user credentials (username and password) and authenticates the user using Laravel's built-in Auth authentication system.
I know that at this point I should proceed to Oauth authentication. Once the credentials pass the Auth step, I have the user's username, password (specified in the users table) and I can get the client_id and client_secret from the oauth_clients table, but I'm not sure how to accomplish the rest. Do I need to make another POST request? If yes, then how do I do it from the controller?
I am actually implementing this right now. Let me show you some code.
This is my part of my login function:
// this does the process for getting the access token
$oauth = AuthorizationServer::performAccessTokenFlow();
// some hacks
$oauth = (array) $oauth;
// more hacks
$oauth = json_decode($oauth["\0*\0data"], true);
// checks if a token was actually generated
if(!in_array('bearer', $oauth))
{
// returns what was generated if the token is missing
return Responser::error(400, $oauth);
}
You would have to post additional data on your login other than the username and password of the user.
So your post request will contain:
username=the_username
password=the_password
grant_type=password
client_id=the_client_id
client_secret=the_client_secret
note that grant_type=password is constant.
Now you have to check the configurations of the package too found at app/config/packages/lucadegasperi/oauth2-server-laravel/oauth2.php:
You should have the following code:
'password' => array(
'class' => 'League\OAuth2\Server\Grant\Password',
'access_token_ttl' => 604800,
'callback' => function($username, $password){
$credentials = array(
// change this to username if username is the field on your database
'email' => $username,
'password' => $password,
);
$valid = Auth::validate($credentials);
if (!$valid) {
return false;
}
return Auth::getProvider()->retrieveByCredentials($credentials)->id;
}
),
And you are done.
update
the code above that generates the token is inside this function:
// allow user to login with username or email and password
$user_pass = array('username' => $username, 'password' => $password);
$email_pass = array('email' => $username, 'password' => $password);
// check if input is email and use $email_pass combination or else use $user_pass combination
$login = ($isEmail->passes() ? $email_pass : $user_pass);
// try to authenticate username & password
if (Auth::attempt($login))
{
// now you are authenticated here
// get the client id and secret from the database
// maybe use curl or some hacks
// login stuff and token generation
}
This is a bit of an old post, but if you are looking to do this without having multiple post requests, you could always just do something like:
//Get Oauth creds
$apiCreds = OauthClient::where('email', Input::get('email'))->first();
//Provide additional post data for password grant
Input::merge([
'grant_type' => 'password',
'client_id' => $apiCreds->id,
'client_secret' => $apiCreds->secret,
'username' => Input::get('email'),
'password' => Input::get('password'),
'scope' => 'all'
]);
//Login
return AuthorizationServer::performAccessTokenFlow();