Laravel Multi Auth - Admin Guard - php

I have two guards in laravel
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
//Our Admin custom driver
'web_admin' => [
'driver' => 'session',
'provider' => 'admins',
],
],
and providers
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
//Admin user provider
'admins' => [
'driver' => 'eloquent', //We are using eloquent model
'model' => App\Admin::class,
],
],
The default is
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
When i log in as admin and try to access the user profile it asks me to login as user which is normal. But what im looking for is, admin should be able to access whole site as admin login.
The reason i choose multi auth over rbac is because i have 5 types of users and each have different registration fields and login. Each user have a set of tools too.
So i want admin guard to be able to access all guards too.
Business guard to be able to access only users guard.
App/Http/Controllers/AdminAuth/LoginController
<?php
//LoginController.php
namespace App\Http\Controllers\AdminAuth;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
//Class needed for login and Logout logic
use Illuminate\Foundation\Auth\AuthenticatesUsers;
//Auth facade
use Auth;
class LoginController extends Controller
{
//Where to redirect admin after login.
protected $redirectTo = '/admin/home';
//Trait
use AuthenticatesUsers;
//Custom guard for admin
protected function guard()
{
return Auth::guard('web_admin');
}
//Shows admin login form
public function showLoginForm()
{
return view('admin.auth.login');
}
}
App/Http/Controllers/Auth/LoginController
<?php
namespace App\Http\Controllers\Auth;
use Socialite;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
class LoginController extends Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/
use AuthenticatesUsers;
/**
* Where to redirect users after login.
*
* #var string
*/
protected $redirectTo = '/home';
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest')->except('logout');
}
/**
* Redirect the user to the GitHub authentication page.
*
* #return \Illuminate\Http\Response
*/
public function redirectToProvider($social)
{
return Socialite::driver($social)->redirect();
}
/**
* Obtain the user information from GitHub.
*
* #return \Illuminate\Http\Response
*/
public function handleProviderCallback($social)
{
$user = Socialite::driver($social)->user();
// $user->token;
}
}
Similarly i have created middleware for admin too in App/Https/Middleware/AuthenticateAdmin.php
<?php
//AuthenticateAdmin.php
namespace App\Http\Middleware;
use Closure;
//Auth Facade
use Auth;
class AuthenticateAdmin
{
public function handle($request, Closure $next)
{
//If request does not comes from logged in admin
//then he shall be redirected to admin Login page
if (! Auth::guard('web_admin')->check()) {
return redirect('/admin/login');
}
return $next($request);
}
}
And RedirectIfAdminAuthenticated
<?php
//RedirectIfAdminAuthenticated.php
namespace App\Http\Middleware;
use Closure;
//Auth Facade
use Auth;
class RedirectIfAdminAuthenticated
{
public function handle($request, Closure $next)
{
//If request comes from logged in user, he will
//be redirect to home page.
if (Auth::guard()->check()) {
return redirect('/home');
}
//If request comes from logged in admin, he will
//be redirected to admin's home page.
if (Auth::guard('web_admin')->check()) {
return redirect('/admin/home');
}
return $next($request);
}
}
RedicrectIfAuthenticated
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class RedirectIfAuthenticated
{
/**
* 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 = null)
{
if (Auth::guard($guard)->check()) {
return redirect('/home');
}
return $next($request);
}
}

Further to our correspondence
1.
If you have many types of users... so i suggest you to change your logic and make the Admin as User too... remove the admins and in the users add field "type" or something like that... and work with field to check if user is admin or have permission / access to some parts of the system... and if the user "type" is "admin" so he will have access to all parts too.
so you mean remove multi auth and go for RBAC. But i have a requirement where i need to use multi auth and each guard has their own RBAC For example, admin guard roles are manager, support and so. Business guard roles are vendors, sellers and so.
yes this is what i mean. I did similar thing on one of the systems that i developed, and i added one more guard so all the "logged in" routes pass in (like auth) and there i'm checking the requested rout and action and check if the user type is allow to access this action, and if not i redirected him to somewhere else (in my case to main dashboard page).
add new middleware
php artisan make:middleware Permissions
in app\Http\Kernel.php, add to protected $routeMiddleware new middleware
'permissions' => \App\Http\Middleware\Permissions::class,
in Routes web add the desire routs for logged in and add the middleware permissions ... pay attention to the as definition
Route::group(['middleware'=>['auth', 'permissions']], function() {
// any of your routs ... for example
Route::get('/', [
'uses'=>"UserController#getUsers",
'as'=>"users"
]);
Route::get('/{id}', [
'uses'=>"UserController#getUserEdit",
'as'=>"users.edit"
]);
});
in the new middleware app\Http\Middleware\Permissions.php,
adjust the public function handle and add there the users level logic... pay attention that for the switch case checking the as ... the same as that defined in the routs web file.
add more check as you need for the logged in user "type"... Admin, Support ... and so on as you have in the system.
public function handle($request, Closure $next, $guard = null)
{
$user = $request->user();
$actions = $request->route()->getAction();
switch( $actions['as'] ) {
case "users":
if( ! $user->isAdmin() ) {
//return redirect()->route("dashboard");
}
break;
case "users.edit":
if( ! $user->isAdmin() ) {
}
break;
// add more cases as you need and check the user "type"
default:
break;
}
return $next($request);
}
if you have a lot of routs... so maybe it will be better to add few "little" middleware and for every route group / prefix ... check if user allow to access this prefix.
for example... add SupportMiddleware / SalesMiddleware ... and in every one of them you can just check the user type and if it's fit to the current group of routes.

Simply, seperate your guards with , (comma) then all of the listed guards can access those routes.
Example:
Route::group(['middleware'=>'auth:web,web_admin'], function() {
//Now this routes can be accessible by both admin as well as
});

Related

Laravel 5.4 Auth::attempt works, Cannot pass auth middleware

I'm having some trouble with laravel 5.4 authentication.
Out of the box the auth worked although I couldn't access Auth::user().
After some changes that had to be made for FrontEnd considerations, I added a new login function that uses Auth::attempt($credentials) like so:
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Support\Facades\Input;
use App\Models;
use Auth;
use Log;
class LoginController extends Controller
{
use AuthenticatesUsers;
/**
* Where to redirect users after login.
*
* #var string
*/
protected $redirectTo = '/home-page';
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest')->except('logout');
}
public function login(){
if(Auth::guest()){
if (Auth::attempt(['email' => Input::get('email'), 'password' => Input::get('password')])) {
Log::debug(Auth::user());
return redirect('/home-page');
}
}
return 'cannot log in';
}
}
The login passes, the redirect works, and Auth::user() is accessible.
The problem is that after the redirect ,all routes guarded by 'auth' middleware are not accessible.
Route::group(['middleware' => 'auth'], function(){
Route::get('some-route', function(){
return view('some-view');
}
});
Moreover, I tried to see if I can access the user there but Auth::user() returns null.
Notes:
1. User table is the one that was created by the Laravel user table migration.
2. Registering users via RegisterController (got from php artisan make:auth)
3. Only change in auth.php is this:
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
],
Would love to hear new suggestions, I can't figure what's wrong here.

Laravel redirect login, main URL

I have the Laravel auth system configured and it works. When a user logs in, he is redirected to his dashboard. But when it closes the page or revises the main URL www.xyz.com, it is not redirected to the dashboard. How can I redirect the user to his dashboard when he is logged in and he visit the main URL?
LoginController.php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Auth;
use Illuminate\Http\Request;
class LoginController extends Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/
use AuthenticatesUsers;
/**
* Where to redirect users after login.
*
* #var string
*/
protected $redirectTo = '/iboard';
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest', ['except' => ['logout', 'userLogout']]);
}
/**
* Get the needed authorization credentials from the request.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
protected function credentials(Request $request)
{
$field = filter_var($request->get($this->username()), FILTER_VALIDATE_EMAIL)
? $this->username()
: 'username';
return [
$field => $request->get($this->username()),
'password' => $request->password,
];
}
public function userLogout()
{
Auth::guard('web')->logout();
return redirect('/logout');
}
}
Heres a simple solution, when a user visits the page www.xyz.com you can check if the user is logged in by using
use Illuminate\Support\Facades\Auth;
if (Auth::check()) {
//Executes when user is logged in
return redirect('dashboard');
}
The above code checks if a user is logged in if he is then he gets redirected else he won't get redirected and still be on www.xyz.com.
Hopefully, this answer helps.
Here are some cool some cool stuff you can do with laravel auth:- https://laravel.com/docs/5.5/authentication
simply redirect the user when he access's the root for example you can add this to your web.php (or routes.php if version <= 5.2)
Route::get('/', function () {
return redirect('dashboard');
});

Redirect After Login for each role create with Shinobi Package Laravel

i have a question, i want to redirect users to diferent pages after login based in the role, if is admin redirect to admin/users if is normal redirect to admin/norma for example i have the next files
LoginController.php
<?php
namespace App\Admin\Http\Controllers\Auth;
use App\Admin\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
class LoginController extends Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/
use AuthenticatesUsers;
/**
* Where to redirect users after login.
*
* #var string
*/
protected $redirectTo = 'admin/users';
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest', ['except' => 'logout']);
}
/**
* Validate the user login request.
*
* #param \Illuminate\Http\Request $request
* #return void
*/
protected function validateLogin(Request $request)
{
$this->validate($request, [
$this->username() => 'required', 'password' => 'required', //'g-recaptcha-response' => 'required|recaptcha',
]);
}
}
And i use Laravel 5.3 and the Shinobi Package for roles and permissions https://github.com/caffeinated/shinobi
I already create 4 roles in the system database table roles - Administrador/Free/Gold/Diamond
I thinks is something how this
if($user->rol = 'Administrador){
protected $redirectTo = 'admin/users';
}else{
protected $redirectTo = 'admin/normal';
}
But i dont know how exactly make to work, thanks for all.
What you're looking for is the authenticated method override. Larvel calls this method after successful login to perform additional checks. You even get the user object and request object. You can perform the user role check and set the redirect path accordingly.
Add this to your LoginController
protected function authenticated(Request $request, $user)
{
if ($user->role == 'admin') {
$this->redirectTo = 'admin/dashboard';
} else {
$this->redirectTo = 'user/dashboard';
}
}
Edit : Since you're using the shinobi package. You need to do the role check like so
if ($user->isRole('admin')) {
}
I already solve my question in base to shinobi roles and the help of Sandeesh
I add this to my loginController.php
use Caffeinated\Shinobi\Models\Role;
use Caffeinated\Shinobi\Models\Permission;
and the function authenticated is now
protected function authenticated(Request $request, $user)
{
if( $user->isRole( 'administrador' ) ) {
$this->redirectTo = 'admin/dashboard';
} else {
$this->redirectTo = 'user/dashboard';
}
}
And now is working thanks for all :D

I am using laravel auth for redirecting my users according to their type . But there i get stuck. I could not redirect user according to their type

Here is my routes.php file
<?php
/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| Here is where you can register all of the routes for an application.
| It's a breeze. Simply tell Laravel the URIs it should respond to
| and give it the controller to call when that URI is requested.
|
*/
Route::get('/', function () {
return view('welcome');
});
Route::get('/login', function(){
return view('auth.login');
});
Route::post('/login', 'Auth\AuthController#authenticate');
Route::get('/home', 'HomeController#index');
Here is my AuthController.php file
<?php
namespace App\Http\Controllers\Auth;
use App\User;
use Validator;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;
use Auth;
class AuthController extends Controller
{
/*
|--------------------------------------------------------------------------
| Registration & Login Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users, as well as the
| authentication of existing users. By default, this controller uses
| a simple trait to add these behaviors. Why don't you explore it?
|
*/
use AuthenticatesAndRegistersUsers, ThrottlesLogins;
/**
* Where to redirect users after login / registration.
*
* #var string
*/
protected $redirectTo = '/';
/**
* Create a new authentication controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware($this->guestMiddleware(), ['except' => 'logout']);
}
/**
* Get a validator for an incoming registration request.
*
* #param array $data
* #return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
return Validator::make($data, [
'user_name' => 'required|max:255|unique:users',
'full_name' => 'required|max:255',
'password' => 'required|min:6|confirmed',
]);
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return User
*/
protected function create(array $data)
{
return User::create([
'user_name' => $data['user_name'],
'full_name' => $data['full_name'],
//'password' => bcrypt($data['password']),
'password' => $data['password'],
]);
}
//Auth::attempt(['user_name' => $user_name, 'password' => $password])
public function authenticate()
{
if (Auth::attempt($request->all()) {
var_dump(Auth::user())
if(Auth::user()->type == 'admin') {
return "Welcome company admin let's create some user for your company";
# code...
} elseif(Auth::user()->type == manager) {
return "Welcome manager let's manage your coaches";
}elseif(Auth::user()->type == 'counterman'){
return "Welcome counter person let's sell some ticket's";
}else
{
return "Welcome online user let's make a relationship with me";
}
return "Gonnnaaa";
//return redirect()->intended('dashboard');
}else
{
return "you are fucked";
}
}
}
In my project I want redirect my user to different pages according to there type . I tried to implement this in different ways . At last I tried to use authenticate method inside AuthController as suggested in laravel doc's but I am getting AuthController not exist error . What wrong I am doing and what can be better approach in my case ? thanks in advance . I have not edited anything except AuthController and routes.
If you don't want to implement something new by yourself, you could create a new TypeBasedAuthController that extends the AuthController.
Then, you would decorate its parent by implementing a postLogin method that calls the parent postLogin. After the login logic, you could change the $redirectTo property as you wish.
It should make sense... :)
EDIT: take a look to this link if you want to know something more about the decorator pattern in PHP :)
EDIT2 - Important: after another deeper search, I have found a better solution. All you have to do is to overwrite this method in your new TypeBasedAuthController.
protected function handleUserWasAuthenticated(Request $request, $throttles)
{
if ($throttles) {
$this->clearLoginAttempts($request);
}
if (method_exists($this, 'authenticated')) {
return $this->authenticated($request, Auth::guard($this->getGuard())->user());
}
// HERE: control the user that has logged in and change the value
// of $this-redirectTo property accordingly.
return redirect()->intended($this->redirectPath());
}
It should be quite clear now.

protecting admin and user routes laravel 5

I have a common login for both admin and user. But I have created a roles in my table which looks like:
user_id role_id
1 2
2 1
3 2
where role_id 1 refers to the admin and role_id 2 refers to the user. I can attach roles to the different user as well. Now what I want is, I want to protect all admin routes and user routes.
For example, I don't want user to get any access that is meant for admin. For now, I can check whether the user is admin or user like if (Auth::user()->hasRole('admin')) or if (Auth::user()->hasRole('user')).
How should I separate my user routes from admin routes in this case? Should I make my own middleware and implement? If so, how to implement it correctly?
Create two middleware, for admin you can do:
<?php namespace App\Http\Middleware;
use Auth;
use Illuminate\Contracts\Routing\Middleware;
class CheckAdmin implements Middleware {
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if (Auth::user()->hasRole('admin'))
{
return $next($request);
}
throw new \Exception("Unauthorized");
}
}
Then enable this middleware in App\Http\Kernel
protected $routeMiddleware = [
'auth' = 'App\Http\Middleware\Authenticate',
'auth.basic' => 'Illuminate\Auth\Middleware\AuthenticateWithBasicAuth',
'checkAdmin' => 'App\Http\Middleware\CheckAdmin',
];
You can use your CheckAdmin middlware in the routes.php file or in the constructor of your Controller
In routes.php you can do:
Route::group(['middleware' => 'checkAdmin'], function () {
Route::get('admin/profile', function () {
// Uses CheckAdmin Middleware
});
});

Categories