I am really new to laravel but had experience using PHP, I have this problem with the Auth::attempt() method. It seems that even thought $request->get() gets the value the attempt method doesn't work. I tried checking my Database Table using Schema::hasTable and yes it exists. I am not using the email and password instead I am using a username and password for the login.
LoginController.php
class LoginController extends Controller
{
public function login(){
return view('pages.login');
}
public function dashboard(){
return view('pages.dashboard');
}
public function checklogin(Request $request)
{
$rules = array(
'Username' => 'required|string|min:5',
'Password' => 'required|min:6'
);
$validator = Validator::make($request->all(), $rules);
if ($validator->fails()) {
return Redirect::to('/login')
->withErrors($validator) // send back all errors to the login form
->withInput($request->except('Password')); // send back the input (not the password) so that we can repopulate the form
}else{
$userdata = array(
'Password' => $request->get('Password'),
'Username' => $request->get('Username')
);
if (Auth::attempt($userdata,true)) {
// validation successful!
echo 'SUCCESS!';
echo Auth::user()->FirstName;
} else {
// validation not successful, send back to form
echo "ERROR!";
}
}
//Just checking if the value was really been posted
echo $request->get('username').$request->get('password');
}
public function logout()
{
Auth::logout();
return redirect('/');
}
}
Here is the model I created
UsersInfo.php
use Illuminate\Database\Eloquent\Model;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Auth\Authenticatable as AuthAuthenticatable;
class UsersInfo extends Model implements Authenticatable
{
use AuthAuthenticatable;
protected $table = 'UsersInfo';
public $primaryKey = 'id';
protected $fillable = [
'Username','Password','MobileNum','AccountNum','FirstName','LastName','Address'
];
public function getAuthPassword(){
return $this->Password;
}
}
auth.php
<?php
return [
'defaults' => [
'guard' => 'web',
'passwords' => 'UsersInfo',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'UsersInfo',
],
'api' => [
'driver' => 'token',
'provider' => 'UsersInfo',
'hash' => false,
],
],
'providers' => [
'Users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
'UsersInfo' => [
'driver' => 'eloquent',
'model' => App\UsersInfo::class,
],
// 'users' => [
// 'driver' => 'database',
// 'table' => 'users',
// ],
],
'passwords' => [
'UsersInfo' => [
'provider' => 'UsersInfo',
'table' => 'password_resets',
'expire' => 60,
'throttle' => 60,
],
],
'password_timeout' => 10800,
];
When passing the credentials to attempt the field holding the password must be named password (in this exact case). This is how the user provider knows what field in the credentials is supposed to be the password. The password is something that is checked after a record is found and is not part of the query.
$userdata = [
'password' => $request->input('Password'),
'Username' => $request->input('Username'),
];
Passwords are hashed, you can not directly compare this to the database value, the password field is not part of the query to find the user. Every thing else in the credentials array is a where condition.
Related
I hope my english is good enough to explain my problem. I'm working with laravel 7, and I'm trying to implement my own AuthController, because I can't use migrations and I can't use a table 'users' because I have a db implemented. I've read all the documentation of laravel about authentication and spent days reading a lot of posts with this problem, and I tried everything but still does not work. The problem is with the attempt method. My register method is working fine, but I can't login, actually I tried to put manually the data(that's why credentials are commented) to find the problem but I don't know why is not working
My Regsiter method.
public function storeUser(Request $request)
{
//dd($request);
$request->validate([
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:administradores,ADMIN_Correo',
'password' => 'required|string|min:8|confirmed',
'password_confirmation' => 'required',
]);
Administrador::create([
'ADMIN_Nombre' => $request->name,
'ADMIN_Correo' => $request->email,
'ADMIN_Contrasena' => Hash::make($request->password),
]);
//return redirect('home');
}
My Login method.
public function authenticate(Request $request)
{
/*$request->validate([
'ADMIN_Correo' => 'required|string|email',
'ADMIN_Contrasena' => 'required|string',
]);*/
//$credentials = $request->only('ADMIN_Correo', 'ADMIN_Contrasena');
if (Auth::guard('admin')->attempt(['ADMIN_Correo' => 'edwin2#gmail.com
','ADMIN_Contrasena' => '12345678'])) {
return redirect()->intended('home');
}else{
echo 'error';
}
//return redirect('login')->with('error', 'Oppes! You have entered invalid credentials');
}
My config/auth.php file
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
'hash' => false,
],
'admin' => [
'driver' => 'session',
'provider' => 'admins',
]
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Administrador::class,
],
'admins' => [
'driver' => 'eloquent',
'model' => App\Administrador::class,
],
],
My Model
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class Administrador extends Authenticatable
{
use Notifiable;
protected $table = 'administradores';
protected $primaryKey = 'ADMIN_Id';
public $timestamps = false;
public $incrementing = true;
protected $fillable = ['ADMIN_Nombre','ADMIN_Correo','ADMIN_Contrasena'];
protected $guard = 'admin';
public function getAuthPassword()
{
return $this->ADMIN_Contrasena;
}
}
NOTES The field for password:(ADMIN_Contrasena) is varchar 255
I am trying to create a new type of login that works alongside users table called business_users.
I have added the associated, tables, models and config into my auth.php files.
Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Auth\User as Authenticatable;
class BusinessUser extends Authenticatable
{
protected $fillable = ['first_name', 'last_name', 'email', 'password', 'username'];
protected $hidden = [
'password', 'remember_token',
];
protected $guard = 'business_user';
public function business()
{
return $this->belongsTo('App\Business');
}
public function username()
{
return 'username';
}
public function getAuthPassword()
{
return $this->password;
}
}
auth.php
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'business_user' => [
'driver' => 'session',
'provider' => 'business_users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
'hash' => false,
],
],
...
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
'business_users' => [
'driver' => 'eloquent',
'model' => App\BusinessUser::class,
],
],
Route (which fakes a login for testing)
Route::get('/business/fake-login', function () {
$user = \App\BusinessUser::first();
if (Auth::guard('business_user')->attempt(['username' => $user->username, 'password' => $user->password])) {
return redirect()->intended('/business/dashboard');
}
});
I am trying to use the business.username and business.password to login but the Auth:guard condition above returns false.
Can anyone explain what I'm doing wrong?
(fyi I am using Laravel 7.x)
You are retriving $user from the database, the password is encrypted.
Auth::attempt() will encrypt the password for you, so in the check password part, your password is actually being encrypted twice.
Instead, you may use Auth:attempt() like this:
$res = Auth::guard('business_guard')->attempt([
'username' => "test",
'password' => "test",
]);
dd( $res );
To understand further, you can go to EloquentUserProvider.php
public function validateCredentials(UserContract $user, array $credentials)
{
$plain = $credentials['password'];
return $this->hasher->check($plain, $user->getAuthPassword());
}
Use you original code, and dd() the $plain to see what's going on.
I have 4 types of users in my application and details are stored in 4 different tables, so how can I implement Laravel's Authentication?
Route::post('/adlogin', 'mainController#adminlogin');
Route::get('/sellerlogin', function () {
return view('seller.pages.login');
});
Route::post('/sellerlog_in', 'mainController#sellerlogin');
Use this as your controller
<?php
namespace App\Http\Controllers\Auth;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
//Use Dependencies
use Auth;
class AdminLoginController extends Controller
{
Middleware used here is admin which you have to create in config/auth.php
public function __construct()
{
$this->middleware('guest:admin', ['except'=>'logout']);
}
Create a view for your admin Login
public function showLoginForm()
{
return view('auth.admin_login');
}
public function login(Request $request)
{
//Validate the Form Data
$this->validate($request, [
'email'=>'required|email',
'password'=>'required|min:5'
]);
//Attempt to log the Admin In
$email= $request->email;
$password= $request->password;
$remember= $request->remember;
After Successfully login where you want to redirect like here I am redirecting
toadmin.dashboard
//If Successful redirect to intended location
if (Auth::guard('admin')->attempt(['email' => $email, 'password' => $password], $remember)) {
return redirect()->intended(route('admin.dashboard'));
}
//If Unsuccessful redirect back to login form with form data
return redirect()->back()->withInput($request->only('email', 'remember'));
}
/**
* Log the Admin out of the application.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function logout()
{
Auth::guard('admin')->logout();
return redirect()->route('admin.login');
}
}
After logout redirect back to login page
Make sure you are using right guard for right User. Create same functionality for more user types as you want create guards for them.
In config/app.php
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
],
'admin' => [
'driver' => 'session',
'provider' => 'admins',
],
'admin-api' => [
'driver' => 'token',
'provider' => 'admins',
],
],
As admin and admin-api created here create for your user types
Add providers
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
'admins' => [
'driver' => 'eloquent',
'model' => App\Admin::class,
],
],
At last for resetting passwords use this.
'passwords' => [
'users' => [
'provider' => 'users',
'table' => 'password_resets',
'expire' => 60,
],
'admins' => [
'provider' => 'admins',
'table' => 'password_resets',
'expire' => 10,
],
],
In http/middleware/redirectIfAuthenticated.php add this to your handle function
//Check for admin login guard
switch ($guard) {
case 'admin':
if (Auth::guard($guard)->check()) {
return redirect()->route('admin.dashboard');
}
break;
default:
if (Auth::guard($guard)->check()) {
return redirect('/dashboard');
}
break;
}
You can add more cases for your user types.
This is all you want to create multi auth. As you created different table for different roles you have to follow this process.
Create LoginController for all user types or use your logic to log them in.
Add your guards for every user type in auth.php
Add your cases to RedirectIfAuthenticated
You can use the laravel-permission package.This package allows you to manage user permissions and roles in a database.
I am trying to perform multi auth in my Laravel project. Initially I put it for user, then token is generated and its working fine. When I add employee too, then token is not generated for employee. When I remove for users and now employee is working but combinly both are not working.
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
//'provider' => 'employees'
],
'api' => [
'driver' => 'token',
'provider' => 'users',
//'provider' => 'employees'
],
'employees' => [
'driver' => 'session',
'provider' => 'employees',
],
],
Can anyone please provide me help.Thanks.
In your auth.php file add providers in providers array for defined guards.
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
//'provider' => 'employees'
],
'api' => [
'driver' => 'token',
'provider' => 'users',
//'provider' => 'employees'
],
'employees' => [
'driver' => 'session',
'provider' => 'employees',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
'employees' => [
'driver' => 'eloquent',
'model' => App\Employees::class,
],
],
If your as using 2 different model for authentication do like above. If you are using the same model to authenticate based on user role give the same model for employees and user.
create Route for employees login.
Route::get('/employee/login','Auth\EmployeeLoginController#showLoginForm')->name('employee.login');
Route::post('/employee/login','Auth\EmployeeLoginController#login')->name('employee.login.submit');
create EmployeeLoginController
<?php
namespace App\Http\Controllers\Auth;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Auth;
class EmployeeLoginController extends Controller
{
public function __construct()
{
$this->middleware('guest:employee');
}
public function showLoginForm()
{
return view('auth.employee-login');
}
public function login(Request $request)
{
// Validate the form data
$this->validate($request, [
'email' => 'required|email',
'password' => 'required|min:6'
]);
// Attempt to log the user in
if (Auth::guard('employee')->attempt(['email' => $request->email, 'password' => $request->password], $request->remember)) {
// if successful, then redirect to their intended location
return redirect()->intended(route('employee.Product.list'));
}
// if unsuccessful, then redirect back to the login with the form data
return redirect()->back()->withInput($request->only('email'));
}
}
if you are using the 2 different model do like above. If you are using the same model to authenticate based on role just add the following check by role in the attempt method
attempt(['email' => $request->email, 'password' => $request->password, 'role' => 'employee'], $request->remember))
then in your app\Exception folder add the modify the unauthenticated methode in handler.php file
protected function unauthenticated($request, AuthenticationException $exception)
{
if ($request->expectsJson()) {
return response()->json(['error' => 'Unauthenticated.'], 401);
}
$guard = array_get($exception->guards(),0);
switch ($guard) {
case 'admin':
$login = 'admin.login';
break;
case 'employee':
$login = 'employee.login';
break;
default:
$login = 'login';
break;
}
return redirect()->guest(route($login));
}
here actually you are $login variable is being used to redirect to the url you want if the user is not authenticated.
and last in your app\middleware\RedirectIfAuthenticated.php file remove the handle methode and add the following.
public function handle($request, Closure $next, $guard = null)
{
switch ($guard) {
case 'admin':
if (Auth::guard($guard)->check()) {
return redirect()->route('admin.index');
}
break;
case 'employee':
if (Auth::guard($guard)->check()) {
return redirect()->route('employee.dashboard');
}
break;
default:
if (Auth::guard($guard)->check()) {
return redirect('/');
}
break;
}
return $next($request);
}
Here you are redirecting the user if they are authenticated.
for better understanding check this video.This works in both 5.3 and 5.4 It will help you to understand how all these works.
Youtube link
I'm new in Laravel. I try to use Multiple Auth in Laravel 5.3 and my auth.php file is:
<?php
return [
*/
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
],
'courier' => [
'driver' => 'session',
'provider' => 'couriers',
],
'client' => [
'driver' => 'session',
'provider' => 'clients',
]
],
'providers' => [
'couriers' => [
'driver' => 'eloquent',
'model' => App\Courier::class,
],
'clients' => [
'driver' => 'eloquent',
'model' => App\Client::class,
],
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
]
],
'passwords' => [
'couriers' => [
'provider' => 'couriers',
'table' => 'password_resets',
'expire' => 60,
],
'clients' => [
'provider' => 'clients',
'table' => 'password_resets',
'expire' => 60,
],
],
];
Then, when I store Clients or Couriers in the DB, I use bcrypt for password (Bring also use the function Hash::make() for passwords). For example, my model Courier is:
<?php
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
class Courier extends Authenticatable
{
[..]
public function setPasswordAttribute($pass){
$this->attributes['password'] = bcrypt($pass);
}
[..]
}
And when update a courier, in my controller I have:
public function update(Request $request, $id) {
$fieldsCourier = $request->all();
$courier = Courier::find($id);
if( isset($fieldsCourier['password']) )
$fieldsCourier['password'] = bcrypt($fieldsCourier['password']);
if( $courier->update($fieldsCourier) )
$courier = Courier::find($id);
}
I have a method called authenticate but the method attempt always return false (invalid_credentials). Even so send valid credentials.. This is my code:
public function authenticate(Request $request) {
$credentials = $request->only('email', 'password');
try {
if ( auth()->guard('courier')->attempt($credentials) ){
$user = Auth::guard('courier')->user();
} else {
return response()->json(['error' => 'invalid_credentials'], 401);
}
} catch (JWTException $e) {
return response()->json(['error' => 'could_not_create_token'], 500);
}
return response()->json(compact('user'));
}
I not know what I'm doing wrong. Anything am I doing wrong?
you have encrypt the password twice, on your model and controller.
just remove one of them
e.g: don't use bcrypt on your controller, because you have already use bcrypt on your model.