How to chose guard for session driver - laravel

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.

Related

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

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.

Laravel multi auth protecting route multple middleware not working

I have created an extra middleware admin and I want to protect my routes. Adding one single middleware 'auth' or 'auth:admin' is working.
Route::get('/calendar', function () {
return view('app', ['data' => []);
})->middleware('auth');
But I want that as an admin you can also access the user routes but this is not working. If I try the following, and I log in as an admin I get redirected to the login page all the time.
Route::get('/information', ['middleware' => ['auth', 'auth:admin'], function () {
return view('app', ['data' => ['auth' => Auth::check()]]);
}]);
But if I change ['auth', 'auth:admin'] to ['auth:admin','auth'] it is working for admin but not for user. So it seems that only the first element of my middleware in array is being recognized. Does anybody have any idea why my multiple middlewares are working seperate but not together? Any help is appreciated
If you are trying to allow multiple 'guards' to be checked for a route you can pass multiple guards as parameters to the Authenticate middleware, auth.
auth:web,admin (assuming web is your default guard).
This will try to resolve a user (Authenticatable) from each guard passed in. If any guard returns a user (Authenticatable) you pass through authenticated. If not you are a guest.
If you set the middleware auth and auth:admin those are 2 separate 'middleware' in the stack that are unrelated.
Route::get('/information', ['middleware' => ['auth', 'auth:admin'],function () {
return view('app', ['data' => ['auth' => Auth::check()]]);
}]);
in this code. ['auth', 'auth:admin'] that's mean you need to login default guard and admin guard. if you need only login admin guard, ['auth:admin']

Return additional column if user is authorized - API

I have an Laravel-base API which handles both client and admin endpoints (there are two sites like domain.com and admin.domain.com).
My auth is based on cookie, which domain is <.domain.com>. As you can see, this cookie is acceptable for both domains.
I use Eloquent Api Resources for transformation data layer. Is my when() route check here safe and right?
public function toArray($request)
{
return [
'name' => $this->name,
'created_at' => (string)$this->created_at,
'status' => $this->when($request->route()->getName() === 'api.admin.users.index', $this->status)
];
}
Before I used $this->when(Auth::check(), ...), but because my auth cookie is acceptable for client site too, unneeded data might be fetched.
My route:
Route::group(['prefix' => 'admin', 'as' => 'api.admin.', 'middleware' => 'auth:api'], function () {
Route::resource('users', ...);
});
If user is not authorized, he wouldn't get data because of middleware. At the same time, authorized used (who has non-expired cookie) wouldn't get unneded data while being on client site.
Thank you!
I think your approach is fine. The route name is something internal and the user cannot tinker with it. You could improve it by using \Route::is('api.admin.*') though. It would then work for all of your admin API routes.

Protecting routes with LDAP

I am slightly confused by something. For Authentication, I am using LDAP, more specifically this https://github.com/SaschaDens/ldap-connector
That LDAP library I am using essentially works on top of Laravels Authentication Facade.
Everything is fine, I can log in and out now using LDAP. When logged in however, I have an update users buttons. This essentially uses LDAP to get
all the groups a user is apart off. So I have three tables,
users
groups
users_groups
When the button is pushed, I add all users to the users table. I then add all unique groups to the groups table. The last table users_groups is essentially a pivot table which links a users_id to a groups_id.
By the end of this, I can see that I am for instance apart of 3 groups, one of which is the admin group. I can also see all members of this group by doing this
$group = Group::where('groupName', 'admin')->first();
$users = $group->user;
Now there are some routes I only want to make available to admin users. I can see in Kernel.php there is the following
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
];
At the moment I am only using auth to make sure the user is logged in. Obviously I do not have an admin one set up yet, and I think the way I am doing it there could be a problem because I am creating my own groups table.
How would I go about blocking access to a particular route to only users who are apart of the admin group?
Thanks
You can do this by creating a new route middleware.
1) create middleware class
php artisan make:middleware AdminMiddleware
2) Add authentication logic to you AdminMiddleware class
if(Auth::user()->inGroup('GROUPNAME'))
{
return $next($request);
}
else
{
return view('auth.login')->withErrors('You are not logged in');
}
3) Add the new middleware to your $routeMiddleware
'admin' => 'App\Http\Middleware\AdminMiddleware',
4) Add the middleware alias to the routes you wish to protect
Route::get('admin', [
'as' => 'admin',
'middleware' => 'admin',
'uses' => 'AdminController#getAdminPage'
]);

Laravel 5.2 Auth::login($user) not working

I am writing a Laravel 5.2 application. I need to manually login the user for which I am using \Auth::login($user). I am doing it in following way.
if ($user = User::where('phone',session('phone'))->first())
{
\Auth::login($user);
// \Auth::loginUsingId($user->id);
// Auth::attempt(['email' => $user->email, 'password' => 'password']);
$data = \Auth::user(); //returning correct results
}
I have tried all the options namely Auth::login($user), Authh:loginUsingId($user->id) and attempt method. These methods are working fine as the $data variable is storing the object of correct user. But the problem is when I move to other route say '/home' the user remain no more authenticated.
What might be the wrong here? How could I do it correctly?
Since Laravel 5.2, you have to attach all your routes that need session with the 'web' middleware. See your app/Http/Kernel.php, the 'web' middleware contains the \Illuminate\Session\Middleware\StartSession.
In routes you have to use web in laravel 5.2
Route::group(['middleware' => ['web', 'auth']], function () {
Route::get('/', 'HomeController#index');
Route::get('/profile', 'HomeController#profile');
});

Resources