Multiple auth in middleware. Laravel 5.4 - php

Im new in PHP and Laravel. I try to search online but i cant get the right answer for my problem. I want my specific page accessible only by admin and user that already been authenticated. So basically, all the user need to login first. Heres my code. Thanks in advance.
HomeController.php
class HomeController extends Controller
{
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth:web, auth:admin');
}
/**
* Show the application dashboard.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
return view('accounts.user.user_dashboard');
}
}
auth.php
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
],
'admin' => [
'driver' => 'session',
'provider' => 'admins',
],
'admin-api' => [
'driver' => 'token',
'provider' => 'admins',
],
],

i used this, in route file
Route::group(['middleware' => ['auth']], function (){
Route::get('/dashboard', 'HomeController#index');
}

You can create a middleware to check if the user has certain permission or not. Here is how I am used to doing it.
I create a middleware say for example SuperAccess and write my logic for super admin there.
class SuperAccess
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$response = $next($request);
if(Auth::check() && Auth::user()->role->permission == 1000){
return redirect('web/dashboard');
}
return $response;
}
}
Then i use the middleware where I need to have superAccess checked for example say in DeviceController
class DevicesController extends Controller
{
public function __construct(){
$this->middleware('auth');
$this->middleware('super');
}
Note: In the example above I have a role table which has a relation with user table.

Related

Can't get authenticated data

I have this global middleware that updates user's last activity
<?php
namespace App\Http\Middleware;
use Illuminate\Http\Request;
use Closure;
class HandleLastActivity
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle(Request $request, Closure $next)
{
if (auth()->user()) {
$user = auth()->user();
$user->lastActivity = now();
$user->save();
}
return $next($request);
}
}
but auth()->user() is always null. I'm using sanctum and it works in routes under auth middleware.
env
SESSION_DRIVER=cookie
SESSION_LIFETIME=120
SESSION_DOMAIN=.mydomain.com
SANCTUM_STATEFUL_DOMAINS=mydomain.com,www.mydomain.com,api.mydomain.com
config/auth.php
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'sanctum',
'provider' => 'users',
],
],

Laravel Passport- Protect routes for different user types

I am using passport in laravel for authenticating my users in APIs. I am able to authenticate different types of users from different tables and generating different token for them but the routes are not protected. For example.
A user can access the routes like this
Route::group(['middleware' => 'auth:api'], function () {
Route::group(['prefix' => 'v1'], function () {
Route::get('get-seller-list','API\v1\SellersController#index');
});
});
and a seller can access the routes like
Route::group(['middleware' => 'auth:sellers'], function () {
Route::group(['prefix' => 'v1'], function () {
Route::get('get-seller-detail','API\v1\TestController#getDetails');
});
});
but this middleware check doesn't seem to be working as I can access all the routes for sellers even if I have passed the token generated for api in Bearer header.
My config/auth.php looks like
'guards' => [
'user' => [
'driver' => 'session',
'provider' => 'users',
],
'seller' => [
'driver' => 'passport',
'provider' => 'sellers',
],
'admin' => [
'driver' => 'session',
'provider' => 'admins',
],
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'passport',
'provider' => 'users',
],
],
The auth:api middleware will handle the passport token authentication and the sellers middleware will check if users are sellers. I think you are getting mixed up with the way the middleware is set up.
This sort of depends on how you have your user types set up but in your sellers middleware you can check for User types / roles:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Contracts\Auth\Guard;
class Sellers
{
/**
* The Guard implementation.
*
* #var Guard
*/
protected $auth;
/**
* Create a new filter instance.
*
* #param Guard $auth
* #return void
*/
public function __construct(Guard $auth)
{
$this->auth = $auth;
}
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if ($this->auth->user()->is_seller) {
return $next($request);
}
return response()->view('errors.401', [], 401);
}
}
Then you can set your route up to use both auth:api and sellers middleware:
Route::group(['middleware' => ['auth:api', 'sellers']], function () {
Route::group(['prefix' => 'v1'], function () {
Route::get('get-seller-detail','API\v1\TestController#getDetails');
});
});
So now if a normal user tries to access the get-seller-detail route it will return a 401 unauthorized error and if a seller tries to access this route it will proceed to the code for that route as normal.

Two different models for authentication in laravel 5.4

Suppose I have two different models and tables named user and company.
As you know laravel uses User model to manage Authentication. but beacause I have two different model I want can manage them separately.
I'm using laravel 5.4 and I do not know how can do that.
If you are talking about multiple authentication system, then you have to create multiple guards to achieve that.
There is nice answer to the same question.
Can anyone explain Laravel 5.2 Multi Auth with example
It's on Laravel 5.2, but it can be easily implemented on Laravel 5.4.
Create a model App\Company which extends Authenticatable Class. This model will work as user model which will company guard (in the next step)
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class Company extends Authenticatable
{
use Notifiable;
/**
* 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',
];
}
Create an guard and a provider for model App\Company.
// Authenticating guards and providers
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
],
'company' => [
'driver' => 'session',
'provider' => 'company',
],
],
// Providers
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
'company' => [
'driver' => 'eloquent',
'model' => App\Company::class,
]
],
Now you can find user according to the different guards.
$user = Auth::guard('company')->user();
// Or...
$user = auth()->guard('company')->user();
dd($user);
Now create Auth controller for Company App\Http\Controllers\Auth\CompanyLoginController same as Auth\LoginController.
Specify $redirectTo and guard
//Auth\ComapnyLoginController.php
protected $redirectTo = '/comapany';
protected $guard = 'comapany';
public function showLoginForm()
{
if (view()->exists('auth.authenticate')) {
return view('auth.authenticate');
}
return view('comapany.auth.login');
}
now create login form for user - company.auth.login view same as user's login form.
Now create routes
//Login Routes...
Route::group(['prefix'=>'company', 'middleware'=>'company'], function(){
Route::get('/login','Auth\CompanyLoginController#showLoginForm');
Route::post('/login','Auth\CompanyLoginController#login');
// ...
// rest of the company dashboard and other links
// ...
Route::get('/logout','Auth\CompanyLoginController#logout');
});
Create a middleware for company
class RedirectIfNotCompany
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string|null $guard
* #return mixed
*/
public function handle($request, Closure $next, $guard = 'company')
{
if (!Auth::guard($guard)->check()) {
return redirect('/');
}
return $next($request);
}
}
and register it to kernal.php
protected $routeMiddleware = [
'company' => \App\Http\Middleware\RedirectIfNotCompany::class,
];
And thats all you need.
Access user by the name of guard
Auth::guard('company')->user()

How to use different Auth for different controller in Laravel

I am creating a project in laravel. My problem is, Since this is a shopping cart I am using different tables for customer and admins. So if request is admin then i want to authenticate from admin table and if it is from store i want to use customer table for authentication. Is is it possible to set auth table for controllers or is it possible to use create multiple authenticator other than the default?
Multi Auth is a common problem that one can face in Laravel so yes it possible to create it.
You can write your own code for this or use some package for this specific functionality. They are available on github easily. Example link.
There is a very good tutorial for this here which I will use for explanation.
You will need to create two tables, customers and admin. The default user table can be used for customers (or other way too). The make:auth command will create all the routes, controllers and views for the users table auth.
For admin auth, first create an admin table. Next controllers
app/Http/Controllers/AdminAuth/AuthController
app/Http/Controllers/AdminAuth/PasswordController
Edit config/auth.php file and do same for admin as given for user, using admin model when required instead of user.
//Authenticating guards
'guards' => [
'user' =>[
'driver' => 'session',
'provider' => 'user',
],
'admin' => [
'driver' => 'session',
'provider' => 'admin',
],
],
//User Providers
'providers' => [
'user' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
'admin' => [
'driver' => 'eloquent',
'model' => App\Admin::class,
]
],
//Resetting Password
'passwords' => [
'clients' => [
'provider' => 'client',
'email' => 'auth.emails.password',
'table' => 'password_resets',
'expire' => 60,
],
'admins' => [
'provider' => 'admin',
'email' => 'admin.auth.emails.password',
'table' => 'password_resets',
'expire' => 60,
],
],
Edit route file
Route::group(['middleware' => ['web']], function () {
//Login Routes...
Route::get('/admin/login','AdminAuth\AuthController#showLoginForm');
Route::post('/admin/login','AdminAuth\AuthController#login');
Route::get('/admin/logout','AdminAuth\AuthController#logout');
// Registration Routes...
Route::get('admin/register', 'AdminAuth\AuthController#showRegistrationForm');
Route::post('admin/register', 'AdminAuth\AuthController#register');
Route::get('/admin', 'AdminController#index');
});
Edit AdminAuth\AuthController.php file and add functions
protected $redirectTo = '/admin';
protected $guard = 'admin';
public function showLoginForm()
{
if (view()->exists('auth.authenticate')) {
return view('auth.authenticate');
}
return view('admin.auth.login');
}
public function showRegistrationForm()
{
return view('admin.auth.register');
}
Create middleware for admin
class RedirectIfNotAdmin
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string|null $guard
* #return mixed
*/
public function handle($request, Closure $next, $guard = 'admin')
{
if (!Auth::guard($guard)->check()) {
return redirect('/');
}
return $next($request);
}
}
Register middleware in kernel
protected $routeMiddleware = [
'admin' => \App\Http\Middleware\RedirectIfNotAdmin::class,
];
Use this middleware in admin controller
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
class AdminController extends Controller
{
public function __construct(){
$this->middleware('admin');
}
public function index(){
return view('admin.dashboard');
}
}
Now you can use it like
Auth::guard('admin')->user()
but not directly like
Auth::user()
because we have two auths
You Should use ENTRUST (Laravel 5 Package)
But before you need to organize your database structure.
For all type of user use your users table, have a separate customer table with foreign key user_id. Assign roles to users , When a user logged in check its role and redirect to their dashboard as per assigned role.

Laravel 5: OR operator in middleware groups

I would like to have some routes which only be available for auth:user OR auth:admin middlewares.
I tried following code :
Route::group(['middleware' => ['auth:user', 'auth:admin']], function () {
//many routes here
});
But seems like these routes are available for auth:user AND auth:admin at the same time!!!
I don't want AND. I need OR.
Any helps would be appreciated
Update 1
I decided to create new guard userOradmin in /config/auth.php file.
As you can see I have created new guard called userOradmin which points to provider usersOrAdmins (plural names) :
'guards' => [
'user' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
],
'admin' => [
'driver' => 'session',
'provider' => 'admins'
],
'userOradmin' => [
'driver' => 'session',
'provider' => 'usersOradmins'
]
]
And the provider is :
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
'admins' => [
'driver' => 'eloquent',
'model' => App\Admin::class
],
'usersOradmins' => [
'driver' => 'eloquent',
'model' => [App\Admin::class, App\User::class] // <-- Is that right?
]
The problem is here. Should I assign that two classes to model like that?!
You need to make a new middleware for this, auth:userOrAdmin. Middlewares do not interact with each other, so neither of those middlewares know that the other exists. They just get a request, check it, and send it down the line, so every middleware is inherently AND.
Swap out the Authenticate middleware with this:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class Authenticate
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string ...$guards
* #return mixed
*/
public function handle($request, Closure $next, ...$guards)
{
if ($this->check($guards)) {
return $next($request);
}
if ($request->ajax() || $request->wantsJson()) {
return response('Unauthorized.', 401);
} else {
return redirect()->guest('login');
}
}
/**
* Determine if the user is logged in to any of the given guards.
*
* #param array $guards
* #return bool
*/
protected function check(array $guards)
{
if (empty($guards)) {
return Auth::check();
}
foreach ($guards as $guard) {
if (Auth::guard($guard)->check()) {
Auth::shouldUse($guard);
return true;
}
}
return false;
}
}
Then you can use it in your routes:
Route::group(['middleware' => ['auth:user,admin']], function () {
//many routes here
});

Categories