I am using laravel 5.2 and I am trying to log in with more than one auth guard but only the default is working.
This is my code.
Guards
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
],
'admin' => [
'driver' => 'session',
'provider' => 'admins'
]
],
Providers
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
'admins' => [
'driver' => 'eloquent',
'model' => App\Admin::class,
],
],
Authenticate Middleware
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->guest()) {
if ($request->ajax() || $request->wantsJson()) {
return response('Unauthorized.', 401);
} else {
return redirect()->guest('login');
}
}
return $next($request);
}
Routes
Route::get('/foo', function(){
if (Auth::guard('web')->attempt(['email' => 'bale#mail.com', 'password' => 'gareth'])){
return redirect('/');
}else{
return 'No!';
}
});
Route::get('/bar', function(){
if (Auth::guard('admin')->attempt(['email' => 'lionel#mail.com', 'password' => 'password'])){
return redirect('/');
}else{
return 'No!';
}
});
Both routes return true when the attempt method is called but only the web guard actually logs a user in but if i switch the default guard to admin, the admin guard works and the web guard doesn't.
Can someone help me in solving this?
I found a github repo that solved my problem.
https://github.com/gregoryduckworth/laravel-multi-auth
Related
Problem:
On my index page, authenticated users and guests should be able to view and use the page unless they want to save something. I tried to log in so that I could save the data and was redirected to an authenticated page which is a profile page. I tried dumping Auth::user() on the profile page, it returns the user logged in data, tried dumping it again on the index page then it returns null.
I'm using the latest version of Laravel.
I've googled some of the same problems I have and the closest one is this Auth::user() returns null. I tried following the answer provided but still, it returns null.
web.php
Route::group(['middleware' => 'web'], function () {
Route::get('/', [IndexController::class, 'index'])->name('index.page');
Auth::routes();
Route::group(['middleware' => ['auth:user']], function() {
Route::get('/user/profile', [UserController::class, 'profile'])->name('user.profile');
});
Route::group(['prefix' => 'admin', 'middleware' => ['auth:admin']], function() {
Route::get('dashboard',[DashboardController::class, 'index'])->name('admin.dashboard');
});
})
auth.php
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'user' => [
'driver' => 'session',
'provider' => 'users',
],
'admin' => [
'driver' => 'session',
'provider' => 'admins',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
'admins' => [
'driver' => 'eloquent',
'model' => App\Models\Admin::class,
],
],
'passwords' => [
'users' => [
'provider' => 'users',
'table' => 'password_resets',
'expire' => 60,
'throttle' => 60,
],
'admins' => [
'provider' => 'admins',
'table' => 'password_resets',
'expire' => 15,
],
],
This is the only modification I did from the middleware.
RedirectIfAuthenticated.php
foreach ($guards as $guard) {
if ($guard === "admin" && Auth::guard($guard)->check()) {
return redirect('/admin/dashboard');
}
if ($guard === "user" && Auth::guard($guard)->check()) {
return redirect('/user/profile');
}
if (Auth::guard($guard)->check()) {
return redirect('/');
}
}
I added $guard for the User and Admin model
User.php
protected $guard = 'user';
Admin.php
protected $guard = 'admin';
If you have any questions, feel free to ask and thanks for the help!
But i guess the customized Auth.php has a problem
foreach ($guards as $guard) {
if ($guard === "admin" && Auth::guard($guard)->check()) {
return redirect('/admin/dashboard');
}else{
if ($guard === "user" && Auth::guard($guard)->check()) {
return redirect('/user/profile');
}else{
return redirect('/');
}
}
}
I can share the solution that worked for me. I switched from Passport to Sanctum.
I use laravel 6, I make multiple logins, my multi logins are running, but after logging out, I get an error like this on my welcome page
Argument 2 passed to Illuminate\Auth\SessionGuard::__construct()
must implement interface Illuminate\Contracts\Auth\UserProvider, null
given, called in
D:\xampp2\htdocs\alkit\vendor\laravel\framework\src\Illuminate\Auth\AuthManager.php
on line 125
auth.php
<?php
return [
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
// Guard
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
],
'admin' => [
'driver' => 'session',
'provider' => 'admin',
],
'admin-api' => [
'driver' => 'token',
'provider' => 'admin',
],
'camp' => [
'driver' => 'session',
'provider' => 'camp',
],
'camp-api' => [
'driver' => 'token',
'provider' => 'camp',
],
'user' => [
'driver' => 'session',
'provider' => 'user',
],
'user-api' => [
'driver' => 'token',
'provider' => 'user',
],
],
// Providers
'providers' => [
'user' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
'admin' => [
'driver' => 'eloquent',
'model' => App\Admin::class,
],
'camp' => [
'driver' => 'eloquent',
'model' => App\Camp::class,
],
],
// Password
'passwords' => [
'users' => [
'provider' => 'users',
'table' => 'password_resets',
'expire' => 60,
],
],
];
web.php
<?php
Route::get('/home', function () {
return view('index');
});
// hanya untuk tamu yg belum auth
Route::get('/login', 'LoginController#getLogin')->name('login')->middleware('guest');
Route::post('/login', 'LoginController#postLogin');
Route::get('/logout', 'LoginController#logout');;
Route::get('/admin', function() {
return view('admin');
})->middleware('auth:admin');
Route::get('/user', function() {
return view('user');
})->middleware('auth:user');
Route::get('/camp', function() {
return view('camp');
})->middleware('auth:camp');
LoginCobtroller.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Admin;
use App\User;
use App\Camp;
use Auth;
class LoginController extends Controller
{
public function getLogin()
{
return view('login');
}
public function postLogin(Request $request)
{
// Validate the form data
$this->validate($request, [
'email' => 'required|email',
'password' => 'required'
]);
// Attempt to log the user in
// Passwordnya pake bcrypt
if (Auth::guard('admin')->attempt(['email' => $request->email, 'password' => $request->password])) {
// if successful, then redirect to their intended location
return redirect()->intended('/admin');
} else if (Auth::guard('user')->attempt(['email' => $request->email, 'password' => $request->password])) {
return redirect()->intended('/user');
} else if (Auth::guard('camp')->attempt(['email' => $request->email, 'password' => $request->password])) {
return redirect()->intended('/camp');
}
return redirect()->route('login');
}
public function logout()
{
if (Auth::guard('admin')->check()) {
Auth::guard('admin')->logout();
} else if (Auth::guard('user')->check()) {
Auth::guard('user')->logout();
} else if (Auth::guard('camp')->check()) {
Auth::guard('camp')->logout();
}
return redirect('/home');
}
}
The provider is named wrong. You should use like this
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
'admins' => [
'driver' => 'eloquent',
'model' => App\Admin::class,
],
'camps' => [
'driver' => 'eloquent',
'model' => App\Camp::class,
],
],
Change the web guards configuration to use your adjusted user provider ... by default it wants to use a provider named users which you do not have.
'web' => [
'driver' => 'session',
'provider' => 'user',
],
If you are not going to be using the web guard, you should not have it set as the default. The passwords section is an issue since the only configuration you have there is set to use the users provider, which you do not have.
Similarly: https://stackoverflow.com/a/58896116/2109233
Also:
Route::get('/login', 'LoginController#getLogin')->name('login')->middleware('guest');
Since you have not specified a guard to guest it will use the default guard which is web. So everyone who isn't logged in via the web guard can reach this route.
Having said all of that ... it is probably easier to just change the user provider to be named users and adjust your user and user-api guards to use the users provider.
I had implemented custom auth in L5.2. I had followed those same steps but, I am not able to login/signup with custom auth. Following is the setup:
in auth.php i added customers custom auth:
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
],
'customers' => [
'driver' => 'jwt',
'provider' => 'customers',
],
],
// Providers Section
providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
'customers' => [
'driver' => 'eloquent',
'model' => App\Customer::class,
],
],
Then in routes/api.php I added following code after removing middleware from RouteServiceProvider.php
Route::group(['middleware' => 'customers'], function() {
Route::post('login', 'JwtAuth\LoginController#login'); //Had made new auth for JWT
}
When I hit this login, instead of Customer table, Auth is done from User table!!
I also tried with following code inside Controller\JwtAuth\LoginController.php :
public function login(Request $request)
{
$credentials = $request->only('email', 'password');
$customer = Auth::guard('customers')->attempt($credentials);
try {
// attempt to verify the credentials and create a token for the user
if (!$token = JWTAuth::attempt($credentials)) {
return response()->json(['error' => 'invalid_credentials'], 401);
}
} catch (JWTException $e) {
// something went wrong whilst attempting to encode the token
return response()->json(['error' => 'could_not_create_token'], 500);
}
// all good so return the token
return response()->json(compact('token'), Response::HTTP_OK);
}
This code throws error as:
Auth guard driver [customers] is not defined.
In my \App\Http\Kernel.php under protected $middlewareGroups i had added:
'api' => [
'throttle:60,1',
'bindings'
],
'customers' => [
'throttle:60:1',
'bindings'
]
Is there any change in token driver or custom driver. Or how to define custom Auth driver?
Any help/guidance would b much appreciated. Thanks in advance.
Auth Guard driver is defined in config/auth.php
Like below
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'jwt',
'provider' => 'users',
],
'customers' => [
'driver' => 'jwt',
'provider' => 'customers',
],
],
and also add in providers like
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
'customers' => [
'driver' => 'eloquent',
'model' => App\Models\Customer::class,
],
// 'users' => [
// 'driver' => 'database',
// 'table' => 'users',
// ],
],
Try to clear the config cache php artisan config:clear or rebuild it php artisan config:cache
You will have to also extend your authentication by adding this to the boot() method of your app's AuthServiceProvider:
public function boot()
{
$this->registerPolicies();
Auth::extend('customers', function ($app, $name, array $config) {
return new CustomersGuard();
});
}
See the documentation for adding custom guards
I am trying to login from two different model using same login form. I have defined admin guard in config/Auth.php. But when I define admin guard in Foundation/AuthenticateUsers it checks the database table to validate the user but redirects back to same login form.
config/auth.php
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'admin' => [
'driver' => 'session',
'provider' => 'admins',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
'admins' => [
'driver' => 'eloquent',
'model' => App\Admin::class,
],
Foundation/AuthenticatUsers
protected function guard()
{
return Auth::guard('admin');
}
public function login(Request $request)
{
$credentials = $this->credentials($request);
if (Auth::guard('web')->attempt($credentials, $request- >has('remember'))) {
return $this->sendLoginResponse($request);
}
elseif(Auth::guard('admin')->attempt($credentials, $request->has('remember')))
{
return $this->sendLoginResponse($request);
}
}
Admin guard redirects to login page because of middleware auth, i think you need to do something like this
public function __construct()
{
$this->middleware('auth:admin');
}
Read this Protecting Routes, part "Specifying A Guard"
I'm trying to set up a custom auth guard and everything is mostly working. I'm able to log the Model in, but once I redirect the visitor to a new page the authentication is lost. I can dd() the Auth::guard('client')->user() just fine before the controller does the redirect, but comes up as null in the AuthenticateClient middleware.
I'm using the default guard for authenticating users and everything is working fine with that. I've made sure the routes are under the web middleware which enables sessions.
I've searched for similar issues, but I'm unable to find a solution that works. Any ideas how to fix this?
Side note: I know that I'm using token in the code examples below, but I'm doing more than just validating against that token. So this is a different system than authenticating a token for an api.
Routes:
Route::group(['middleware' => 'web'], function () {
// other routes...
Route::get('client/login/{token}', ['as' => 'client.token', 'uses' => 'Auth\ClientController#attemptTokenLogin']);
Route::group(['prefix' => 'client', 'middleware' => 'auth.client'], function () {
Route::get('dashboard', ['as' => 'client.dashboard', 'uses' => 'ClientController#dashboard']);
});
});
auth.php
return [
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
],
// new auth guard
'client' => [
'driver' => 'session',
'provider' => 'clients',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
// new guard provider
'clients' => [
'driver' => 'eloquent',
'model' => App\Client::class,
],
],
];
Http/Kernel.php
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
// new...
'auth.client' => \App\Http\Middleware\AuthenticateClient::class,
];
ClientController#attemptTokenLogin
$client = // get the client in a custom way...
Auth::guard('client')->login($client);
// dd(Auth::guard('client')->user()); // this works here
return redirect()->route('client.dashboard');
AuthenticateClient
public function handle($request, Closure $next)
{
// dd(Auth::guard('client')->user()); // this does not work here
if (!Auth::guard('client')->check()) {
return redirect()->route('client.login');
}
return $next($request);
}
When implementing Illuminate\Contracts\Auth\Authenticatable I was not returning getAuthIdentifierName() or getAuthIdentifier()
so...
public function getAuthIdentifierName()
{
$this->getKeyName();
}
public function getAuthIdentifier()
{
$this->getKey();
}
was supposed to be...
public function getAuthIdentifierName()
{
return $this->getKeyName();
}
public function getAuthIdentifier()
{
return $this->getKey();
}