Laravel 5.8 - Auth::user() with different guards - laravel

Lets say I have the following guards:
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'admin' => [
'driver' => 'session',
'provider' => 'users',
],
],
I login to my app as a normal user using the default 'web' guard and to access the authenticated user I can use the following: $user = Auth::user();
public function __construct()
{
$this->middleware('auth');
}
public function edit()
{
$user = Auth::user();
}
At the same time I also login to the same app as an admin using the 'admin' guard and in admin controllers I have the following middleware and to access the authenticated admin I do the following: Auth::guard('admin')->user()
public function __construct()
{
$this->middleware('auth:admin');
}
public function edit()
{
$user = Auth::guard('admin')->user();
}
The question is do I need to specify the guard each time to access the admin user - I've noticed once I've authenticated in constructor using $this->middleware('auth:admin') I no longer need to specify the guard to access the authenticated user inside other controller methods? Is this correct behaviour

As far as I can see, your admin guard isn't doing anything different to the web guard. It's using the same driver and the same provider. So there is absolutely no difference between using Auth::user() and Auth::guard('admin')->user().
If you do decide to implement a custom driver (different to the session driver) for your admin guard, you'll need to use Auth::guard('admin')->user() (or set your guard as default) when accessing the authenticated user. Otherwise, Auth::user() will look for user details in the session.
As a side note, the default session driver caches the user instance on first retrieval which in your case is when the request hits the auth middleware. Subsequent calls to Auth::user() or Auth::guard('admin')->user() are handled by returning the user instance from cache.

Related

How to create separate login views and redirects with one User model in Laravel

I've been trying forever to figure out how to create separate login views for different types of users in Laravel. I have one User model and then a roles table and role_users table. I do need to have users pick how they would like to login (i.e. as an Advisor, HR Admin, Employee). For example, one user can have both the Employee and HR Admin Role.
Here is what I attempted, using Laravel 7:
Install the Auth scaffolding
Create view called advisor-login by copying the login view that comes with basic Laravel Auth
Create AdvisorLoginController by copying the LoginController that comes with basic Laravel Auth
Create advisor-login route that directs to the AdvisorLoginController. Update the action in the advisor-login view to go to this route
In the AdvisorLoginController, we have:
use AuthenticatesUsers;
/**
* Where to redirect users after login.
*
* #var string
*/
protected $redirectTo = RouteServiceProvider::HOME;
The "protected $redirectTo = RouteServiceProvider::HOME;" part is relatively straightforward as I could modify this to go to the Advisor Dashboard after logged in.
But the AuthenticatedUsers trait presents a problem. I went down this rabbit hole and couldn't get out. I tried to copy the AuthenticateUsers files from with the Laravel/UI package and create an AuthenticateAdvisors trait, but this became a mess.
Am I missing an easy fix here?
It can be done by providing multiple guards, for instance, one guard for admin and another for the user or customer, Then you should create a separate login controller in a different namespaces(it is recommened to be in different namespaces).
First, create a different guard for each in config/auth.php like below(you might want to use differnt driver in guard)
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'admins' => [
'driver' => 'passport',
'provider' => 'users',
],
'api' => [
'driver' => 'passport',
'provider' => 'users',
],
],
you should group your routes by providing namespaces for different user types
Route::group(['prefix' => 'admin', 'namespace' => 'Admin'], function () {
//your route goes here!
});
by grouping routes you can have multiple logins form.
for authenticating the different user types you can create a different middleware for each type like admin for instance and
<?php
namespace App\Http\Middleware;
use Closure;
class Admin
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if (!auth()->user()->isAdmin()) {
return response()->json(['message' => 'You have no rights'], 403);
}
return $next($request);
}
}
then add the admin middleware to your routes for validatiating the roles and other stuff. like below
Route::group(['prefix' => 'admin', 'namespace' => 'Admin'], function () {
//your route goes here!
Route::group(['prefix' => 'dashboard', 'middleware' => ['auth','admin']], function () {
//your route goes here!
});
});
In my opinion wanting to create a specific login page for each user profile is not very optimal. there can be only one page but the access to functionality is managed by ACL. There may be an administration area where you can define and assign roles

Laravel API response Unauthenticated even when Authentication is passed

I am using the jwt for creating the tokens while login. After I login, I try to hit the /me api pointing to the function:
public function me()
{
$user = auth()->user();
return response()->json($user);
}
I followed the JWT official documentation, initially I was able to get the response for the API. Suddenly it started throwing a
{
"message": "Unauthenticated."
}
Why is this happening?? Is there any workaround? It would be great if someone could help.
i tried documentation setup and worked fine, you might missed passing authentication header in your api call. since idk what's your setup i can only tell when you logged in, you should use received token in api calls with authentication.
PostMan Software: In headers tab add a key as Authorization and assign token for value with Bearer, like Breaer token......
for more help please clarify how you're trying api calls.
Edit: added an alternate way for using middleware
Another way of implementing or using middleware :
Create a Middleware with JWT name and put below code in handle function
Don't forget to import
use JWAuth;
public function handle($request, Closure $next)
{
JWTAuth::parseToken()->authenticate();
return $next($request);
}
Then in Kernel add jwt to $routeMiddleware like this :
protected $routeMiddleware = [
// you should add below code.
'jwt' => \App\Http\Middleware\JWT::class,
];
in routes/api
Route::apiResource('/posts', 'PostController');
now in PostController add your middleware to Constructor like this.
public function __construct()
{
$this->middleware('jwt', ['except' => ['index','show']]);
}
So in construct you will set your middleware base on JWT, then with except you can modify which one of your functions don't need to authentication base on JWT token. now when you use auth()->user() you can get your info or etc.
So if i had index, show, update, delete, store, create when i try to do API call if i use GET METHOD for url.com/posts or url.com/posts/23 i can get my posts without passing JWT token.
When you tried to use JWT you should realize that it's working base on token you're passing, you're getting token when you using login, but you're not getting user info because you're not passing user's token to app, before all of this you should consider to verify token then do the rest Logics. Good Luck.
Edit : added more info
auth.php
'defaults' => [
'guard' => 'api',
'passwords' => 'users',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'jwt',
'provider' => 'users',
],
],

How to chose guard for session driver

I'm trying to create a login page with laravel web route. When user login, a session record will be saved to database. But in session table, user_id always get null value.
I've found that in Illuminate\Session\DatabaseSessionHandler, function userId() always return null. It's because I set default guard for api. This is my config/auth.php:
'defaults' => [
'guard' => 'api',
'passwords' => 'users',
],
When I change default guard to web, column user_id in database has value is authorized user id. I don't want to change my default guard to web.
How can I set guard driver for session? Is there something like Auth, we can use Auth::guard('web').
Thanks
Typically, API's are not associated with keeping session state between requests.
You can always add additional groups with seperate guards to the same routes and use them according to your needs. E.g.
Route::group(['middleware' => 'auth:api'], function () {
Route::post('/user', 'UserController#apiUser');
}
Route::group(['middleware' => 'auth'], function () {
Route::post('/user', 'UserController#index');
}
and then seperately reference
$user = auth('web')->user();
or
$user = auth('api')->user();
Read here for a Laravel API implementation using Passport. You may also want to consider Laravel Sanctum which offers support for API token generation for your users.

want to login in laravel passport multiauth

here how i can pass my new guard name is trainer
if (auth()->attempt($credentials)) {
$token = auth()->user()->createToken('TutsForWeb')->accessToken;
return response()->json(['token' => $token], 200);
} else {
return response()->json(['error' => 'UnAuthorised'], 401);
}
here I am using
'Auth::guard('trainer')->attempt($credentials)'
but it show Method Illuminate\Auth\RequestGuard::attempt does not exist.
i am using this code
https://github.com/tusharkhan/Laravel-Passport-MultiAuth/blob/master/app/Http/Controllers/PassportController.php
Actually,
The attempt method is part of the SessionGuard you cannot use Passport, and attempt to log in a user, Passport is used for API authentication, and APIs typically use tokens to authenticate users and do not maintain session state between requests.
To make it work change your driver for the trainer guard to session like this
'trainer' => [
'driver' => 'session',
'provider' => 'trainers',// Your trainer table name here
],

Laravel: Successful login redirects to the login page due to auth middleware on even when correct credentials provided

I am creating an application for a pre-existing web application with pre-designed schema. This application will use the admins table to authenticate users (only admins can access this application). I cannot use users table because it has data of the clients of the application and do not necessarily need authentication because the application is used by admins only.
I have created the User model with the field protected $table = 'admins'. In order to user Laravel's inbuilt authentication libraries, I created required columns in the admin table by migrating the required fields for authentication such as email, password and remember_token. My User models is as follows:
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable, HasRoles;
protected $table = "admin";
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
}
I also have a route as follows:
Route::get('/dashboard' , 'DashboardController#index')->name('dashboard.index')->middleware('auth');
The default LoginController redirects to route /dashboard when user is successfully authenticated. But there seems to be some problem with the auth middleware which does not seem to authenticate the currently logged in user to enter into /dashboard.
Also, I want to tell you that I have made no changes to the config/auth file in the guards key as the User model points to the admins table which has all the necessary fields for authentication which is as follows:
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
],
Now each time that I tried to access the /dashboard or any other routes with auth middleware, the application sends me to the login page. Since the login page will redirect to the dashboard ( which has auth middleware), I get redirected to the login page even when I pass correct credentials i.e. email and password.
Note that I checked the authentication of provided credentials through debugging and the controller successfully authenticated the provided credentials.(I checked this in the authenticated() method in the AuthenticatesUsers trait that Laravel's LoginController users. Notify me if this method is not appropriate to check whether the user was authenticated).
Is there some problem with the auth middleware or do I need to modify my guards configuration in the auth config file ?
Or, do I need to remigrate my migration files for admin table?
Please suggest best alternatives. Thank you..
Maybe if you change the provider on the 'web' guard to 'admins' since the default is 'users'

Resources