Why Laravel Auth::attempt method is not working? - php

I want to do user authentication, method Auth::attempt() is not working, but data is correct (laravel 5.2)
public function postLogin(Request $request)
{
$this->validate($request, [
'name' => 'required|max:255',
'password' => 'required'
]);
$username = $request->input('name');
$password = $request->input('password');
if (Auth::attempt(['name' => $username, 'password' => $password])) {
return redirect('home.get');
} else {
return "FALSE";
}

If you're using the php artisan make:auth. There's a "use AuthenticatesUsers;" the default code will login and check with email and password. Hence, you need to copy the credential function put into LoginController (override the default code). The code below shows how to login using Email or name with password.
protected function credentials(Request $request)
{
$field = filter_var($request->get($this->name()), FILTER_VALIDATE_EMAIL)
? $this->name()
: 'name';
return [
$field => $request->get($this->name()),
'password' => $request->password,
];
}

You need to attempt by email and password by default

Related

Auth::attempt always return false even with proper input

Here are the facades I used
namespace App\Http\Controllers;
use App\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
I've successfully created user signup page with hashed password using bcrypt.
//Get singnup view
public function getSignup()
{
return view('user.signup');
}
//Process signup
public function postSignup(Request $request)
{
$this->validate($request, [
'email' => 'email|required|unique:users',
'password' => 'required|min:4'
]);
$user = new User([
'email' => $request->input('email'),
'password' => bcrypt($request->input('password')),
]);
$user->save();
return redirect()->route('product.index');
}
And now I'm stuck at the signin page. The Auth::attempt always return false. I even tried to store a plain password in my database and signin without bcrypt but it still returned false. I have no idea where I'm wrong right now.
//Get signin view
public function getSignin()
{
return view('user.signin');
}
//Process signin
public function postSignin(Request $request)
{
$this->validate($request, [
'email' => 'email|required',
'password' => 'required|min:4'
]);
$credentials = array(
'email' => $request->input('email'),
'password' => bcrypt($request->input('password'))
);
if(Auth::attempt($credentials))
{
return redirect()->route('user.profile');
}
return redirect()->route('product.index');
}
You don't need bcrypt() in Auth::attempt(). Remove it and try again.
In config\auth, change guard driver setting is set to api.
'defaults' => [
'guards' => 'api',
'passwords' => 'users'
]
But Laravel doesn't support attempt() function with guard api. Thus, you should use some packages like Passport (You can reference here)
Or simplier, just configure you guard driver with Auth::guard('api')->attempt($credentials)
Hope this solve your problem.

Check an user is exist or not in RegisterController Laravel and redirect back to registration page

How to redirect back in laravel default authentication system.For example in Auth\RegisterController
protected function validator(array $data)
{
return Validator::make($data, [
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'contact_no' => 'required|unique:users',
'password' => 'required|string|min:6|confirmed',
]);
}
protected function create(array $data)
{
$email = $data['email'];
$token = $data['token'];
$checkUser = Invitation::where('email', $email)
->where('token', $token)
->first();
if (!$checkUser) {
return redirect()->back()->with('error', 'Credentials not matched !');
}
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'contact_no' => $data['contact_no'],
'password' => bcrypt($data['password']),
]);
before creating an user i want to check the user is exist or not with a token came from another table.I checkuser with a query and if i use this before the create method ,
if (!$checkUser) {
return redirect()->back()->with('error', 'Credentials not matched !');
}
it throws an error
Type error: Argument 1 passed to Illuminate\Auth\SessionGuard::login() must be an instance of Illuminate\Contracts\Auth\Authenticatable, instance of Illuminate\Http\RedirectResponse given,
problem occurred with the redirect inside the if condition.If i dd('error') inside if it shows error when check user return null
Use isset to check if a user exists.
if (!isset($checkUser)) {
return redirect()->back()->with('error', 'Credentials not matched !');
}
And lastly, I recommend using Laracasts/Flash for a more fluent flash messaging. So your code would be something like this.
flash()->error('Credentials not matched.');
return redirect()->back();
To sum up my suggestion:
if (!isset($checkUser)) {
flash()->error('Credentials not matched.');
return redirect()->back();
}
You can add your logic in the validator method of the RegisterController like this :
protected function validator(array $data)
{
\Validator::extend('has_invitation', function($attribute, $value, $parameters) use($data){
$checkUser = Invitation::where('email', $data['email'])
->where('token', $value)
->first();
return !$checkUser;
}, "Credentials not matched !");
return Validator::make($data, [
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:6|confirmed',
'token' => 'required|has_invitation'
]);
}
If there is an error in validation laravel will automaticly redirect to the registration page.
Make a change in if condition in protected function create(array $data) in RegisterController
if (!$checkUser) {
return null;
}
and overwrite the register method from trait RegistersUsers in RegisterController
public function register(Request $request)
{
$this->validator($request->all())->validate();
$user = $this->create($request->all());
if(!$user) return redirect()->back()->with('error','Credentials Not Matched! ');
event(new Registered($user));
$this->guard()->login($user);
return $this->registered($request, $user)
?: redirect($this->redirectPath());
}

Laravel update password only if it is set

I am working on a laravel project with user login. The admin can create new users and edit existing users. I have got a password and a passwordConfirm field in the update-user-form. If the admin puts a new password in the form, it should check for validation and update the record in the db. If not, it shouldn't change the password (keep old one), but update the other user data (like the firstname).
If I try to send the form with an empty password and passwordConfirm field, it doesn't validate. I got a validation error, that the password must be a string and at least 6 characters long, but I don't know why. It seems like the first line of my update function will be ignored.
UserController.php
public function update(User $user, UserRequest $request) {
$data = $request->has('password') ? $request->all() : $request->except(['password', 'passwordConfirm']);
$user->update($data);
return redirect('/users');
}
UserRequest.php
public function rules() {
return [
'firstname' => 'required|string|max:255',
'lastname' => 'required|string|max:255',
'email' => 'required|string|email|max:255',
'password' => 'string|min:6',
'passwordConfirm' => 'required_with:password|same:password',
];
}
If you want to validate a field only when it is present then use sometimes validation rule in such cases.
Add sometimes validation to both password & passwordConfirm. Remove the $data line from update();
// UserController.php
public function update(User $user, UserRequest $request) {
$user->update($request->all());
return redirect('/users');
}
// UserRequest.php
public function rules() {
return [
'firstname' => 'required|string|max:255',
'lastname' => 'required|string|max:255',
'email' => 'required|string|email|max:255',
'password' => 'sometimes|required|string|min:6',
'passwordConfirm' => 'sometimes|required_with:password|same:password',
];
}
Reference - https://laravel.com/docs/5.4/validation#conditionally-adding-rules
I always do this in my projects:
//Your UserController file
public function update(User $user, UserRequest $request) {
$user->update($request->all());
return redirect('/users');
}
//Your UserRequest file
public function rules() {
$rules= [
'firstname' => 'required|string|max:255',
'lastname' => 'required|string|max:255',
'email' => 'required|string|email|max:255'
];
if($this->method()=="POST"){
$rules['password']='sometimes|required|string|min:6';
$rules['passwordConfirm']='sometimes|required_with:password|same:password';
}
return $rules;
}
So, as you can see if your method is POST it means that you want to add a new user so its going to ask for password and passwordConfirm but if your method is PATCH or PUT it means you don't need to validate password and passwordConfirm.
Hope it helps
Maybe you should try the following:
// ... more code
// Removes password field if it's null
if (!$request->password) {
unset($request['password']);
}
$request->validate([
// ... other fields,
'password' => 'sometimes|min:6'
// ... other fields,
]);
// ... more code
you should replace "has" with "filled" in your code
$data = $request->filled('password') ? $request->all() : $request->except(['password', 'passwordConfirm']);
and actually it's better if you use the expression like this
$request->request->remove('password_confirmation');
( ! $request->filled('password') ) ? $request->request->remove('password'):"";
( $request->has('password') ) ? $request->merge([ 'password' => Hash::make($request->post()['password']) ]):"";
//then you can use
$user->update($request->all());
Even better, however, you have to use separate request classes for create and update "php artisan make:request" for ex:
UserUpdateRequest.php and UserCreateRequest.php
for UserCreateRequest your rule is
'password' => 'required|confirmed|min:6',
for UserUpdateRequest your rule is
'password' => 'sometimes|nullable|confirmed|min:6',
and your controller head add this line
use App\Http\Requests\UserCreateRequest;
use App\Http\Requests\UserUpdateRequest;
and your update method must change
public function update(UserUpdateRequest $request, $id)
{
//
}
Standard way of doing this
UserRequest.php
first import Rule
use Illuminate\Validation\Rule;
in your rules array:
'password' => [Rule::requiredIf(fn () => $this->route()->method == "POST")]
Example:
public function rules()
{
return [
'name' => 'required',
'email' => ['required', 'email'],
'password' => [Rule::requiredIf(fn () => $this->route()->method == "POST"), 'confirmed'],
];
}
below php 7.4 use this way
'password' => [Rule::requiredIf(function(){
return $this->route()->method == "POST";
})]

Unable to authenticate a user in Laravel: 'invalid username or password'

I have the username and password passed via a post request from my view to the controller. The controller responsible for handling the post request:
public function postLogin(Request $request) {
$this->validate($request, [
'username' => 'required',
'password' => 'required'
]);
if (!Auth::attempt([
'username' => $request['username'],
'password' => $request['password'] ])) {
return redirect()->back()->with(['fail' => 'invalid username or password']);
}
return redirect()->route('auth.dashboard');
}
The problem is I keep getting 'fail' message: 'invalid username or password'.
I looked at the table inside the phpmyadmin, and the username and password were pretty simple (username: Admin & password: 12345).
This is the database for the admins table :
class CreateAdminsTable extends Migration
{
public function up()
{
Schema::create('admins', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->string('username')->unique();
$table->string('password');
$table->rememberToken();
});
}
public function down()
{
Schema::drop('admins');
}
}
For reference, I am using Laravel 5.2
update 1: The users are created via the registration controller, which stores the username and password in the database. Here is the controller:
public function postRegister(Request $request) {
$admin = new Admin();
$this->validate($request, [
'username' => 'required|unique:admins|max:30|min:3',
'password' => 'required|min:5',
'password_confirm' => 'required'
]);
$password = $request['password'];
$passwordConfirm = $request['password_confirm'];
if ($password !== $passwordConfirm) {
return redirect()->back()->with(['fail' => 'password fields do not match!']);
}
$hashedPassword = password_hash($password, PASSWORD_BCRYPT);
$admin->username = $request['username'];
$admin->password = $hashedPassword;
$admin->save();
return redirect()->route('index')->with(['success' => 'Successfully created account!']);
}
i prefer using Hash::make instead of password_hash. because there's an additional option in Hash::make that was passed to password_hash. Thats why the hashing didnt matched
your always getting false in Auth::attempt because the password in your database in not hash. Hash your password in your database first. You could use the seeder in order to seed in the database
class UserSeeder extends Seeder
{
public function run()
{
//your admin model
Admin::create([
'username' => 'admin',
'password' => Hash::make(123)
]);
}
}
hope this will help.
Please change login function with following code.
public function postLogin(Request $request) {
$this->validate($request, [
'username' => 'required',
'password' => 'required'
]);
if (Auth::attempt([
'username' => $request['username'],
'password' => $request['password'] ],$remember)) {
return redirect()->route('auth.dashboard');
}
return redirect()->back()->with(['fail' => 'invalid username or password']);
}
Note : Here $remember should be a 1/0 or TRUE/FALSE.
Hope this will help you.
Laravel will expect hashed passwords.
So if the password in phpmyadmin is visible, it won't work be able to be verified in Laravel. I would expect the password in phpmyadmin to look like this $2y$13$Cn0gwiUfg2mq5Y3/V98aB.NZ4GJqjbwhvKlsSAOYkVNHKlWRmwZ1W

Can't redirect after login success in laravel 5 authentication

I have problem with my authentication in laravel 5, it works if I enter the wrong username and password and the error appear, but when success, it doesn't redirect to dashboard, and no errors appear.
here's my code 'AuthController':
public function login(LoginRequest $request){
$this->validate($request, [
'username' => 'required', 'password' => 'required',
]);
$remember = (Input::get('remember')) ? true : false;
if($this->auth->validate(['username' => Input::get('username'),'password' => Input::get('password'), 'active' => 1], $remember)){
return redirect('/dashboard');
}else{
return redirect('/login')->withErrors([
'failed' => 'Username or Password is invalid. Please try again.',
]);
}
}
class AuthController extends Controller
{
protected $redirectTo = '/';
protected $loginPath = '/login';
}
Much easier....

Categories