I'm trying to make a custom login but Auth::attempt returns false.
This my controller:
<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Http\Controllers\Controller;
class MyUserController extends Controller
{
public function authenticate(Request $request)
{
$credentials = $request->only('email', 'password');
if (Auth::attempt($credentials)) {
return redirect()->intended('/');
}
}
}
This is auth.php
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'usuarios',
],
'api' => [
'driver' => 'token',
'provider' => 'usuarios',
],
],
'providers' => [
'usuarios' => [
'driver' => 'eloquent',
'model' => Usuario::class,
],
The error I'm getting is
Class '\Usuario' not found {"exception":"[object] (Error(code: 0): Class '\Usuario' not found at /var/www/laravel-boilerplate/vendor/laravel/framework/src/Illuminate/Auth/EloquentUserProvider.php:183)
You're not passing password. Specify the field names
$credentials = $request->only('mail', 'password_laravel');
if (Auth::attempt(['mail'=>$credentials->mail, 'password'=>$credentials->password])) {
$request->session()->regenerate();
return redirect()->intended('/');
} else {
Log::info('Authentication failed.');
}
Notice: Regenerate the session after attempt function. As said here.
Related
I am trying to authenticate admin in Laravel project. my auth.php as shown below:
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'admin' => [
'driver' => 'session',
'provider' => 'admins',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
'hash' => false,
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
'admins' => [
'driver' => 'eloquent',
'model' => App\Admin::class,
],
AdminController.php
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class AdminController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function adminLogin(){
return view('auth.adminLogin');
}
public function cheackAdminLogin(Request $request){
$this->validate($request, [
'email' => 'required|email',
'password' => 'required|min:6'
]);
if (Auth::guard('admin')->attempt(['email' => $request->email,
'password' => $request->password])) {
return redirect()->intended('/admin');
}
return back()->withInput($request->only('email')); */
}
}
AdminDashboardController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class AdminDasboardController extends Controller
{
public function adminPanel()
{
return view('adminPanel');
}
}
The problem that I encountered that when I want to check the admin login, the attempt() function when I wrote it, I get an error message in the editor "Undefined Method".
I tried to using auth()->guard('admin')->attempt() instead of Auth::guard('admin')->attempt but the problem is same.
please help
It may be a problem of type hint
use Illuminate\Auth\SessionGuard;
/** #var SessionGuard $adminGuard */
$adminGuard = Auth::guard("admin");
if ($adminGuard->attempt($credentials)) {
...
I use JWT for API authentication in Laravel 8.
When I use auth()-> in my controller , for factory() or attemp() or anything, Laravel does not know it and says:
Undefined method 'attempt'.intelephense(1013)
I don't know what I forgot to include
my AuthController :
namespace App\Http\Controllers\Api\Admin;
use App\Models\User;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Validator;
class AuthController extends Controller
{
public function __construct() {
$this->middleware('auth:api', ['except' => ['login', 'register']]);
}
public function login(Request $request){
$validator = Validator::make($request->all(), [
'email' => 'required|email',
'password' => 'required|string|min:6',
]);
if ($validator->fails()) {
return response()->json($validator->errors(), 422);
}
if (! $token = auth()->attempt($validator->validated())) {
return response()->json(['error' => 'Unauthorized'], 401);
}
return $this->createNewToken($token);
}
.
.
.
.
.
and my config/auth.php file :
return [
'defaults' => [
'guard' => 'api',
'passwords' => 'users',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'jwt',
'provider' => 'users',
'hash' => false,
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
// Following array is newly added to config
'otp-user' => [
'driver' => 'otp-based-auth-provider'
],
'passwords' => [
'users' => [
'provider' => 'users',
'table' => 'password_resets',
'expire' => 60,
'throttle' => 60,
],
],
'password_timeout' => 10800,
];
Intelephense has some trouble dealing with some methods in Laravel. You can either ignore it, as it should work or you can call it by:
JWTAuth::attempt($validator->validated)
It should make the error go away.
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 use Lavarel 5.2 framework with jwt for authorization
jwt takes user info form token just with one model,
now how can i parse user token with jwt on multiple model?
For sample when i use customer token in a api jwt parse that token from customer model , default guard should be customer
auth.php :
'defaults' => [
'guard' => 'operator',
'passwords' => 'operators',
],
'guards' => [
'operator' => [
'driver' => 'session',
'provider' => 'operators',
],
'customer' => [
'driver' => 'session',
'provider' => 'customers',
],
'biker' => [
'driver' => 'session',
'provider' => 'bikers',
]
],
'providers' => [
'operators' => [
'driver' => 'eloquent',
'model' => App\Http\Services\Auth\Model\User::class,
],
'customers' => [
'driver' => 'eloquent',
'model' => App\Http\Aggregate\Customer\Model\Customer::class,
],
'bikers' => [
'driver' => 'eloquent',
'model' => App\Http\Aggregate\Biker\Model\Biker::class,
]
],
You can create a separate middleware like AuthModel. In that you can set the config to take which providers like the below,
Config::set('auth.providers.users.model',\App\Models\Customer::class);
If you want to use multiple models, then need to use if conditions to check which url can access which models. It can be like,
if(url == '/customer/api/') {
Config::set('auth.providers.users.model',\App\Models\Customer::class);
} else if(url == '/biker/api/') {
Config::set('auth.providers.users.model',\App\Models\Biker::class);
}
In the above example, I have used url just for example, so get it from the request.
You can change the __construct function in each of your controllers as follows. So that jwt know which model to authenticate.
BikerController
function __construct()
{
Config::set('jwt.user', Biker::class);
Config::set('auth.providers', ['users' => [
'driver' => 'eloquent',
'model' => Biker::class,
]]);
}
CustomerController
function __construct()
{
Config::set('jwt.user', Customer::class);
Config::set('auth.providers', ['users' => [
'driver' => 'eloquent',
'model' => Customer::class,
]]);
}
This is my solution. Tested on Laravel 6
User Model
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\SoftDeletes;
use Tymon\JWTAuth\Contracts\JWTSubject;
class User extends Authenticatable implements JWTSubject
{
use SoftDeletes;
use Notifiable;
public $incrementing = false;
protected $keyType = 'string';
protected $fillable =
[
];
protected $hidden =
[
'password',
'created_at',
'updated_at',
'deleted_at'
];
public function getJWTIdentifier()
{
return $this->getKey();
}
public function getJWTCustomClaims()
{
}
}
Teacher Model
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\SoftDeletes;
use Tymon\JWTAuth\Contracts\JWTSubject;
class Teacher extends Authenticatable implements JWTSubject
{
use SoftDeletes;
use Notifiable;
public $incrementing = false;
protected $keyType = 'string';
protected $fillable =
[
];
protected $hidden =
[
'password',
'oldpassword',
'created_at',
'updated_at',
'deleted_at'
];
public function getJWTIdentifier()
{
return $this->getKey();
}
public function getJWTCustomClaims()
{
}
}
config/auth.php
'defaults' => [
'guard' => 'api',
'passwords' => 'users',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'jwt',
'provider' => 'users'
],
'teacher-api' => [
'driver' => 'jwt',
'provider' => 'teachers'
],
],
AuthController function :
if (
$request->getRequestUri() ===
'OTHER_AUTH_ROUTE'
) {
$credentials = $request->only('username', 'password']);
$token = Auth::shouldUse('teacher-api');
$token = Auth::attempt($credentials);
if (!$token) {
return response()->json(['error' => 'Unauthorized'], 401);
}
return $this->respondWithToken($token);
}
$credentials = $request->only([USERNAME, 'password']);
$token = Auth::attempt($credentials);
if (!$token) {
return response()->json(['error' => 'Unauthorized'], 401);
}
return $this->respondWithToken($token);
Hope this can help you all at future
Laravel 8 compatible
For others still looking for a clean solution:
I would suggest manually configure the providers and guards in config/auth.php and not programmatically change any providers.
The next thing to make sure the right JWTSubject auth model is used, is to create different Middleware (don't forget to specify it in Kernel.php under $routeMiddleware) for a group of routes that has to be only accessible by a specific guard/auth model. Then a middleware handle function could look like this for a Manager model:
public function handle(Request $request, Closure $next) {
if (!($request->user('managers'))) abort(401);
Auth::shouldUse('managers');
return $next($request);
}
Then create another middleware for, let's say an Employee model and change the 'managers' guard value to 'employees' which you configured in config/auth.php.
In your routes/api.php you can specify a route group using (e.g.):
Route::group(['middleware' => 'management'], function() { });
In order to make this all work correctly, specify the guard when the auth()->attempt() function is called, e.g. auth('managers')->attempt($credentials)).