Laravel 8: Middleware Roles - php

When someone signs up they can register as a profile or business in a drop select. From my code below, how do I create middleware so the profile user can't access the business dashboard and the business user can't access the profile dashboard? How do I protect those pages?
2014_10_12_000000_create_users_table.php
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('account_type');
$table->string('first_name');
$table->string('last_name');
$table->string('username')->unique();
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('phone');
$table->string('address', 50);
$table->string('city', 25);
$table->char('state', 2);
$table->char('zip', 10);
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
RegisterController.php
<?php
namespace App\Http\Controllers\Auth;
use App\Models\User;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
class RegisterController extends Controller
{
public function index()
{
return view('auth.register');
}
public function store(Request $request)
{
$this->validate($request, [
'account_type' => 'required|not_in:0',
'first_name' => 'required|max:255',
'last_name' => 'required|max:255',
'username' => 'required|max:15|unique:users',
'email' => 'required|email|unique:users',
'phone' => 'required|max:255|digits:10',
'address' => 'required|max:255',
'city' => 'required|max:20',
'state' => 'required|not_in:0',
'zip' => 'required|regex:/\b\d{5}\b/',
'password' => 'required|string|confirmed|min:8',
]);
User::create([
'account_type' => $request->account_type,
'first_name' => $request->first_name,
'last_name' => $request->last_name,
'username' => $request->username,
'email' => $request->email,
'phone' => $request->phone,
'address' => $request->address,
'city' => $request->city,
'state' => $request->state,
'zip' => $request->zip,
'password' => Hash::make($request->password),
]);
Auth::attempt([
'email' => $request->email,
'password' => $request->password,
]);
// Redirect to dashboards based on registers account type
if(Auth::user()->account_type == 'profile'){
return redirect()->route('dashboard_profile');
} else {
return redirect()->route('dashboard_business');
}
}
}
BusinessDashboardController.php
class BusinessDashboardController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
public function index()
{
return view('auth.dashboard_business');
}
}
ProfileDashboardController.php
class ProfileDashboardController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
public function index()
{
return view('auth.dashboard_profile');
}
}
I want to learn to do this without using packages.

In addition to the solution given by #nagidi, you can update the middleware handle condition to check either account_type is profile or business.
public function handle($request, Closure $next, $type)
{
if (Auth::user() && Auth::user()->account_type == $type) {
return $next($request);
}
abort(403, 'Unauthorized action.');
}
Route::get('/business-profile', ['middleware' => 'accType:business', function () {
//
}]);
Route::get('/profile', ['middleware' => 'accType:profile', function () {
//
}]);

1- run :
php artisan make:middleware AccountType
2- Add it to the routeMiddleware array in your kernel file by opening app/Http/Kernel.php:
'accType' => \App\Http\Middleware\AccountType::class,
3- Edit AccountType file:
public function handle($request, Closure $next)
{
// If user account type is profile allow to next or else block the request
if (Auth::user() && Auth::user()->account_type == 'profile') {
return $next($request);
}else{
abort(403, 'Unauthorized action.');
}
}
4- Apply the middleware to your route:
Route::get('/profile', ['middleware' => 'accType', function () {
//
}]);

If your want to have a multi authenticate system, whit different logics, its better to implement multiple guard and define them in your desire models :
[...]
'guards' => [
[...]
'admin' => [
'driver' => 'session',
'provider' => 'admins',
],
'writer' => [
'driver' => 'session',
'provider' => 'writers',
],
],
[...]
[...]
'providers' => [
[...]
'admins' => [
'driver' => 'eloquent',
'model' => App\BusinessDashboard::class,
],
'writers' => [
'driver' => 'eloquent',
'model' => App\ProfileDashboard::class,
],
],
[...]
you can find a complete guide article in bellow code :
enter link description here

How to create your own middleware for multi User Role in Laravel
Let assumed your roles array could be ["admin","student","staff"];
Create a middleware role checking for the role "admin". Repeat steps 1-4 for each role.
I found this much easier for myself, others may have their own approaches
Step 1
Run artisan command
php artisan make:middleware isAdmin
Step 2
App/Http/Middlewere/isAdmin.php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class isAdmin
{
public function handle(Request $request, Closure $next,$is_admin)
{
$role=Auth::user()->role;
//Get the role list
$role_array=explode(",",$role);
if (in_array($is_admin, $role_array)) {
return $next($request);
}
//if not allowed redirect to home page with message
$message="Unauthorized action.";
//return response($message, 401);//if you have friendly 401 page
//otherwise I think is a best to return to home page
$request->session()->flash('error', $message);
return redirect()->route('home');
}
}
Step 3
App/Http/Kernel.php
protected $routeMiddleware = [
'isAdmin' => \App\Http\Middleware\isAdmin::class,
];
Step 4
Now in your route controller add this line to only allow the user that has an admin role
public function __construct()
{
//ONLY ADMIN CAN ACCESS THIS ROUTE
$this->middleware('isAdmin:admin');
//$this->middleware('isStudent:student');
//$this->middleware('isStaff:staff');
}

Related

Why laravel 6 auth returns false after redirecting by using custom guard?

I am trying to make auth through laravel package using admins table. In the project directory I added admin guard into config/auth.php
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
'admins' => [
'driver' => 'eloquent',
'model' => App\Admin::class,
],
// 'users' => [
// 'driver' => 'database',
// 'table' => 'users',
// ],
],
And in the guard array
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
'hash' => false,
],
'admin' => [
'driver' => 'session',
'provider' => 'admins',
],
],
Following is my login controller inside pacakge
class LoginController extends Controller
{
use AuthenticatesUsers;
protected $redirectTo = '/admin/dashboard';
protected function redirectTo()
{
return '/admin/dashboard';
}
public function __construct()
{
$this->middleware('guest')->except('logout');
}
public function login(Request $request)
{
if(Auth::guard('admin')->attempt($request->only('email','password'), true)){
return redirect()
->intended(route('dashboard'))
->with('status','You are Logged in as Admin!');
}
}
}
and following is my dashboard controller
class DashboardController extends Controller
{
public function __construct()
{
/* dd(Auth::check()); */ //return false : just want to show you
$this->middleware('auth:admin');
}
public function index()
{
return view('xyz::dashboard');
}
}
And in my Admin.php Model following script is there
namespace App;
class Admin extends \ABC\xyz\App\Models\Admin
{
}
Which is extending package model
namespace ABC\xyz\App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Auth\User as Authenticatable;
class Admin extends Authenticatable
{
protected $table = 'admins';
}
And below are the routes from my package
$namespace = 'ABC\Xyz\App\Http\Controllers';
Route::group([
'namespace' => $namespace,
'middleware' => ['web'],
'prefix' => 'admin'
], function () {
Route::get('login', function(){
return view('xyz::auth.login');
})->name('login');
Route::post('/login', 'Auth\LoginController#login')->name('customLogin');
});
Route::group(['namespace' => $namespace,'prefix' => 'admin', 'middleware' => ['auth'] ], function () {
Route::get('dashboard', 'DashboardController#index')->name('dashboard');
});
When I try to login, after submitting valid details it does not redirecting me to dashboard, nothing happening. Also when I try for open forcefully /dashboard it take me to login page.
Also right after login attempt when I try Auth::check() it's returns true but same thing returning false in dashboardController.php construct function. In the same way Auth::guard('admin')->user() returns user's info while on dashboardController.php it's returns null.
Strange Result of php artisan route:list
As you can see in DashboardController.php construct I added $this->middleware('auth:admin');
So when I try to add dd(Auth::guard('admin')->user()) and then check in terminal php artisan route:list it returns null and sometime false, any idea why it is happening?
I don't know what and where I am missing something.
I would like to request you kindly guide me about it. I would appreciate.
Thank you
The problem is in your routes file:
Route::group(['namespace' => $namespace,'prefix' => 'admin', 'middleware' => ['auth'] ], function () {
Route::get('dashboard', 'DashboardController#index')->name('dashboard');
});
You are using the default guard with auth middleware. After you are logged in with admin guard you may not be logged in by your default web guard. That is why it fails and tries to redirect you to login page:
When I try to login, after submitting valid details it does not redirecting me to dashboard, nothing happening. Also when I try for open forcefully /dashboard it take me to login page.
Instead, you should specify in your group that you are using the admin guard:
Route::group(['namespace' => $namespace,'prefix' => 'admin', 'middleware' => ['auth:admin']], function () {
Route::get('dashboard', 'DashboardController#index')->name('dashboard');
});
However, you already specified in your DashboardController to use $this->middleware('auth:admin');, so there is no need to specifiy it in the route group again. The following is enough and reduces the likelihood to create an error:
Route::group(['namespace' => $namespace,'prefix' => 'admin'], function () {
Route::get('dashboard', 'DashboardController#index')->name('dashboard');
});
An extraction sample of the how you should define your admin model:
// app/Admin.php
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class Admin extends Authenticatable
{
use Notifiable;
protected $guard = 'admin';
protected $fillable = [
'name', 'email', 'password',
];
protected $hidden = [
'password', 'remember_token',
];
}
For more on multiple authentications guards see: How to use multiple authentication guards
Auth::guard('admin')->attempt($request->only('email','password') its returning true or false? If returning false then maybe toy didnt hashed your password
Try add this in your Model
public function setPasswordAttribute($password)
{
$this->attributes['password'] = Hash::make($password);
}
Please note that the Auth::check doesn't work on construct. this is because the middleware hasn't run yet, so Auth::check() should return false or null when you try to check in construct.
In your login controller, why are you using two redirectto?
protected $redirectTo = '/admin/dashboard';
protected function redirectTo()
{
return '/admin/dashboard';
}
it is better to stick with one :-)
inside your Admin.php , add this:
protected $guard = 'admin';
for your web.php routes, replace
Route::group(['namespace' => $namespace,'prefix' => 'admin', 'middleware' => ['auth'] ], function () {
Route::get('dashboard', 'DashboardController#index')->name('dashboard');
});
with
Route::group(['namespace' => $namespace,'prefix' => 'admin', 'middleware' => ['auth:admin'] ], function () {
Route::get('dashboard', 'DashboardController#index')->name('dashboard');
});
finally, in DashboardController.php
replace the
/* dd(Auth::check()); */ //return false : just want to show you
With:
$this->middleware(function ($request, $next) {
dd(Auth::check()); //return false : just want to show you
die;
});
Auth::check() should return true!

how to auto login after successfully registered in laravel 5.4.12?

i want to make an auto login after successful registration and redirect to Edit Profile page.. I tried the following code but not working as i want
class RegisterController extends Controller
{
use RegistersUsers;
protected $redirectTo = '/edit_profile';
public function __construct()
{
$this->middleware('guest');
}
public function createUser(Request $request)
{
$this->validate($request , [
'firstName' => 'required',
'lastName' => 'required',
'displayName' => 'required',
'email' => 'required |email',
'password' =>'required ',
'gender' =>'required',
'day' =>'required|max:2',
'month' =>'required|max:2',
'year' =>'required|max:4',
]);
$email=$request->input('email');
$password=$request->input('paasword');
$dob=$request->input('day').'-'.$request->input('month').'-'.$request->input('year');
$request->request->add(['dob'=>$dob]);
$request->request->add(['password'=>bcrypt($request->input('password'))]);
$data = User::create($request->except(['_token', 'submit', 'day','month','year', 'confirm_password' ,'dayInWeek']));
Auth::login($data);
}
}
Routes
Route::get('/', 'PageController#login');
Route::get('/home', 'HomeController#index');
Route::group( ['middleware' => 'auth' ], function()
{
Route::get('main', 'PageController#main');
Route::get('browse', 'PageController#browse');
Route::get('pickngo', 'PageController#pickngo');
Route::get('edit_profile', 'PageController#profile');
}
Use Laravel loginUsingId($id) function by passing the user id.
$data = User::create($request->except(['_token', 'submit', 'day','month','year', 'confirm_password' ,'dayInWeek']));
Auth::loginUsingId($data->id);
just modify your auth login just like
if(Auth::login($data)) {
return redirect('/edit_profile');
}
else
{
return redirect()->back();
}
Scren from documentation.
You just need to add after login redirectTo property or method inside your LoginController.
P.S.it will work if you're using laravel's make:auth.

How to make custom auth in laravel 5.3

I'm facing problem in my Laravel 5.3 custom auth want to use my own functions or pages when I check Auth::check() it returns false.
Here is User controller:
namespace App\Http\Controllers;
use App\User;
use Illuminate\Support\Facades\Session;
use validatior;
use Auth;
use Illuminate\Http\Request;
class UserController extends Controller
{
public function postSignUp(Request $request)
{
$validation = \Validator::make($request->all(), [
'email' => 'email|required|unique:users',
'password' => 'required|min:4'
]);
if ($validation->fails()) {
return redirect()->back()->withErrors($validation->errors());
} else {
$user = new User();
$user->email = $request->get("email");
$user->password = bcrypt($request->get['password']);
$user->save();
}
return redirect('signupPage');
}
public function postSignIn(Request $request)
{
$this->validate($request, [
'email' => 'required',
'password' => 'required',
]);
if (Auth::attempt(['email' => $request['email'], 'password' => $request['password']])) {
return redirect('users/profile');
}
dd(Auth::check());
exit;
}
}
After sign in I want to redirect at profile page but my condition is not working. My routes are:
Route::group(['prefix' => 'users'], function(){
Route::group(['middleware' => 'guest'], function(){
Route::get('/signupPage','UserController#getSignUp');
Route::post('/register',array ('as'=>'signup', 'uses' =>'UserController#postSignUp', ));
Route::get('signInPage', array('as' => 'signInPage', 'uses' => 'UserController#getSignIn'));
Route::post('/postLogin', array('as' => 'postLogin', 'uses' => 'UserController#postSignIn'));
});
Route::group(['middleware' => 'auth'], function(){
Route::get('/profile', array('as' => 'profile', 'uses' => 'UserController#getProfile'));
Route::get('/logout', array('as'=>'logout', 'uses'=> 'UserController#logout'));
});
});
Here are some Modifications of your code
public function postSignUp(Request $request)
{
$email = $request->input('email');
$pass = $request->input('password');
$validation = \Validator::make($request->all(), [
'email' => 'email|required|unique:users',
'password' => 'required|min:4'
]);
if ($validation->fails()) {
return redirect()->back()->withErrors($validation->errors());
} else {
$pas = bcrypt($pass);
$user = new User();
$user->email = $email;
$user->password = $pas;
$user->save();
}
return redirect('users/signInPage');
}
Do use bcrypt while registering your User as this function is by default used by Auth Attempt function
public function postSignIn(Request $request)
{
$this->validate($request, [
'email' => 'required',
'password' => 'required',
]);
$email= $request->input['email'];
$password= $request->input['password'];
if (Auth::attempt(['email'=>$email,'password'=>$password']))
{
return redirect('users/profile');
}
return redirect('users/signInPage')->withErrors(['failure' => 'The credentials you entered did not match our records. Try again!',]);
}
finally this will give you too many redirects error as you using default middlewares, because your logic is now differ from the default one that's why you have to write your custom middleware, for this run this command
php artisan make:middleware CutomAuth
this will create your custom middleware now write code in it by your logic and after registering in app/Http/Kernel.php as \n
'customauth' => \Illuminate\Auth\Middleware\CutomAuth::class, you are good to go

laravel 5.2 - Auth::user()->username is empty

If I use Auth::user()->username in a Blade file laravel returns me an empty String but Auth::user()->email is filled. I use my own AuthController and my Login,Register and Logout work perfectly but I can't get the username.
Routes.php
<?php
Route::group(['middleware' => ['web']] , function () {
Route::get('/', function () {
return view('welcome');
})->name('home');
});
Route::group(['middleware' => ['web','guest']], function () {
Route::auth();
#Sign up Routes
Route::get('/signup', function () {
return view('auth.signup');
})->name('auth.signup');
Route::post('/signup', 'AuthController#signup');
#Sign in Routes
Route::get('/signin', function () {
return view('auth.signin');
})->name('auth.signin');
Route::post('/signin', 'AuthController#signin');
});
Route::group(['middleware' => ['web','auth']], function () {
Route::auth();
#Sign out Routes
Route::get('/signout', 'AuthController#signout')->name('auth.signout');
});
And my custom Auth Controller is:
<?php
namespace App\Http\Controllers;
use Auth;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\User;
class AuthController extends Controller
{
public function signup(Request $request) {
$this->validate($request, [
'email' => 'required|unique:users|email|max:255',
'username' => 'required|unique:users|alpha_dash|min:2|max:20',
'password' => 'required|min:6'
]);
User::create([
'email' => $request->input('email'),
'username' => $request->input('username'),
'password' => bcrypt($request->input('password')),
]);
return redirect()->route('home');
}
public function signin(Request $request) {
$this->validate($request, [
'email' => 'required',
'password' => 'required'
]);
if(!Auth::attempt($request->only(['email', 'password']), $request->has('remember'))) {
return redirect()->back()->with('flash-message','We can not sign you in with this data!');
}
return redirect()->route('home');
}
public function signout() {
Auth::logout();
return redirect()->route('home');
}
}
Maybe someone can help me
.
Note:
I added the username into User.php under the filled array.
Most likely you are missing username in $fillable of your User model.
The create method only accept fields coming from $fillable.
Please edit your User model like this:
protected $fillable = [
'email', 'username', 'password',
];
Only $fillable fields insert by Create method.

Access control to different users - Laravel 5.2

In my app I have two types of users - admin and teacher. In my AuthController I have this :
public function getLogin() {
return view('auth.login');
}
public function postLogin(\Illuminate\Http\Request $request) {
if(Auth::attempt([
'username' => $request->input('username'),
'password' => $request->input('password'),
'type' => 'admin'
])) {
return redirect ('admin');
}
if(Auth::attempt([
'username' => $request->input('username'),
'password' => $request->input('password'),
'type' => 'teacher'
])) {
return redirect ('educator/account');
}
return redirect('login')->with('message', [
'type' => 'danger',
'message' => 'Грешно потребителско име или парола!'
]);
}
public function getLogout() {
Auth::logout();
return redirect('login');
}
But when I'm logged in as a user with type teacher if i go to http://localhost/school_system/public/admin I automatically go to the admin panel without asking for username and password. I want if I want to go to the admin panel from the teacher account this to happen with asking for username and password, how can I make this?
My routes:
Route::group(['middleware' => ['auth']
], function () {
Route::group([
'prefix' => 'admin',
'namespace' => 'Admin'
], function () {
Route::controller('student', 'StudentsController');
Route::controller('profile', 'ProfilesController');
Route::controller('class', 'ClassesController');
Route::controller('subjects', 'SubjectsController');
Route::controller('teacher', 'TeachersController');
Route::controller('marktype', 'MarkTypeController');
Route::controller('rules', 'RuleController');
Route::get('{slug?}', 'PageController#getView');
});
});
Route::group(['middleware' => ['auth']
], function () {
Route::group([
'prefix' => 'educator',
'namespace' => 'Educator'
], function () {
Route::controller('account', 'AccountController');
Route::get('{slug?}', 'EducatorController#getView');
});
});
Thanks ^^
You can create an "adminmiddleware" : php artisan make:middleware AdminMiddleware
Example of code you can use
if ($request->user()->type != 'admin')
{
return redirect('home');
}
and in the route:
Route::group(['middleware' => ['admin']...
Finished ;)

Categories