I have a Route group in laravel which has middleware of auth
Route::group(['middleware'=>'auth', function()
{
//Routes
});
Now these routes are only available to logged in users. I have a situation that logged in users have privileges. I have some routes that are only to be visited by logged in users AND if they have privilege of OWNER
In function I have started a session and stored privilege value.
I did something like this
Route::group(['middleware'=>'auth', function()
{
//Routes
if(session::get('privilege')
{
//Routes
}
});
This isn't working neither it's appropriate method. Can anyone tell me how add middleware inside a middleware?
There should be no logic inside your routes file(s) - these should simply define routes and nothing else. What you should do is define middleware which verifies privileges/roles your user has, you can specify parameters which are passed to the middleware like this:
Route::group(['middleware' => 'auth', function() {
Route::get('/my-route', 'Controller#method')->middleware('role:some_role');
Route::get('/my-other-route', 'Controller#otherMethod')->middleware('role:some_other_role');
});
Then in your middleware, you can access that parameter via a third argument in the handle method. With that value, you could verify the privileged/role the user has and then decide if the user should access that route:
public function handle($request, Closure $next, $role)
{
// Do something with $role
return $next($request);
}
If you're unsure about defining your own custom middleware, check out the docs here: https://laravel.com/docs/middleware
You will need to create a custom middleware called OWNER
php artisan make:middleware Owner
Will create a middleware file for you.
Then in the public function called handle u can do something like
if (Auth::user()->privilege == "OWNER") {
return $next($request);
}
return redirect('home');
So at the end your custom middleware will look something like this:
<?php
namespace App\Http\Middleware;
use Closure;
class Owner
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if (Auth::user()->privilege == "OWNER") {
return $next($request);
}
return redirect('home');
}
}
More about Laravel Middelware here
Related
I am building a Laravel site for personal use and I would like to make the first user to register on the site be the only user. So with a fresh Laravel install with the ui installed, migration sorted and no users registered, I would like the register route to be reachable. But if there is a registered user, block the register route and only allow the login route to be reachable.
I could do something like this in the web.php
Route:get('/register', function () {...})->auth();
But I would have to do that after I first create a user. I'd rather do it in a more controllable fashion.
Edit
I don't doubt that #yves-kipondo's answer is the more correct option if I were to create this for someone else.
The solution I went with is a simple one. In my register controller I just add a check in the constructor, if there already is a user return a 404.
public function __construct() {
if (!User::all()) {
$this->middleware('guest');
} else {
abort(404);
}
}
You can create a Middleware which will be register on the register route
<?php
namespace App\Http\Middleware;
use Closure;
class RegisterOnce
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if (User::count() !== 0) {
// you can redirect wherever you want
return redirect('home');
}
return $next($request);
}
}
After that you can register the middleware in the app/Http/Kernel.php by adding this line after all registered routes middleware like this
protected $routeMiddleware = [
\\ ... previous registered middleware
'once' => App\Http\Middleware\RegisterOnce::class,
];
and you can customize the register route like this in the routes/web.php file
which wille replace the default set by Auth::routes();
Route::get('register', [App\Controllers\Auth\RegisterController::class, 'showRegistrationForm'])
->name('register')
->middleware('once');
I am having a tutorial on how to restrict pages to admins. In my RedirectIfAuthenticated.php, this is how my code looks like
public function handle($request, Closure $next, $guard = null)
{
if (!Auth::guard($guard)->check()) {
// return redirect('/login');
} else {
$user = Auth::user();
if($user->hasRole('manager')) {
return redirect('admin/home');
} else {
return redirect('/home');
}
}
return $next($request);
}
After i login, i am routed to the respective pages but the issue is, i can still route to the admin page even tho i login as a member and not manager. When i place localhost/admin/home, i am still routed to that page although i am not a manager. What am i missing out?
You are able to access the manager url after login because your code only redirects each user to their appropriate url's but does'nt do any other check after the users are logged in. You can accomplish this by creating a middleware to check for each user type and redirect them to their appropriate pages and attach this middleware to your desired routes.
In your terminal, run php artisan make:middleware AdminMiddleware to create a middleware Note: the AdminMiddleware is a name of my choosing and can be changed.
This creates a middleware in the app\Middlewares directory. edit the contents to look like this..
<?php
namespace App\Http\Middleware;
use Closure;
class AdminMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$user = Auth::user();
if(!$user->hasRole('manager'))
{
//you can throw a 401 unauthorized error here instead of redirecting back
return redirect()->back(); //this redirects all non-admins back to their previous url's
}
return $next($request);
}
}
Then go to the app/Http/Kernel.php file and add the following to the $routeMiddleware array.
'admin' => \App\Http\Middleware\AdminMiddleware::class,
Now you can attach the admin middleware to any route which you would like only managers to access.
Hello in my project I am using the auto generated password from the admin side.And when the user try to login I am checking that user changed the password or not if password is not changes I want to redirect the user at the changepassword screen. I set changepasword middleware for it but middleware do not call the changepassword redirection Link.
changepasword middleware
use Closure;
use Auth;
class ChangePassword
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if ( Auth::check() && Auth::user()->isAutoPasswordChanged() )
{
return redirect('/change_password');
}
else
{
return redirect('/tests');
}
}
}
web.php
Route::group(['middleware' => 'auth', 'changepassword'], function () {
Route::resource('/tests', 'TestController');
Route::resource('/clients', 'ClientController');
});
Go to app\Http\Kernel.php
and add this to $routeMiddleware
'change_password' => \App\Http\Middleware\ChangePassword::class,
Then in your routes, replace the middle ware line with
Route::group(['middleware' => ['auth', 'changepassword']], function () {
And I also believe the logic written in ChangePassword is wrong...
It should be
if (!auth()->user()->isAutoPasswordChanged()) {
return redirect(route('auth.change.password.get'));
}
return $next($request);
First, please use the route() function instead of simple string... You will not have to change the url here, if you ever change the route from your web.php
Since you are already using the auth middleware, there is no need for you to do auth()->check().
Secondly, there should be a NOT in the condition. Because if the AutoPassword is NOT changed, only then redirect to the route, otherwise the use should be returned the next request and NOT redirected to /tests
Check registration of middleware app/Http/Kernel.php Doc
If you have a route middleware, compare the name provided in app/Http/Kernel.php
but my guess is:
'middleware' => 'auth', 'changepassword' should maybe changed in 'middleware' => ['auth', 'changepassword']
Debug if middleware itself is called
I want to create my app ( I dont want to use laravel default login system)
I want to use a middleware to be run during every HTTP request in my application except one
in laravel 5.1 documention syas I can use Global Middleware but I want to not use middleware for just login page.
what should I do ?
this is my middleware :
<?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( ! session()->has('Login' ) )
{
return redirect('login');
}
return $next($request);
}
}
You can use routes group and assign your middleware to it:
Route::group(['middleware' => 'Admin'], function () {
// All of your routes goes here
});
// Special routes which you dont want going thorugh the this middleware goes here
Don't do anything to your middleware. you have the free to take that route outside the route group. so it becomes a standalone route. Or you can create a new route group and put only that one route in without that middleware. eg.
Route::group(['prefix' => 'v1'], function () {
Route::post('login','AuthenticationController');
});
Route::group(['prefix' => 'v1', 'middleware' => 'web'], function () {
Route::resource('deparments','AuthenticationController');
Route::resource("permission_roles","PermissionRolesController");
});
with this the middleware affect only the second route group
There are a couple of ways to tackle this, one is to address this in your middleware and exclude the route there, and two is to group all the routes you want to have covered by the middleware in your routes.php and then have the ones you want excluded outside of the grouping.
Tackling this in middleware
Just amend the handle function to include an if statement checking the URI requested
public function handle($request, Closure $next)
{
if ($request->is("route/you/want/to/exclude"))
{
return $next($request);
}
if( ! session()->has('Login' ) )
{
return redirect('login');
}
else
{
return redirect('login');
}
}
This method allows you to set the middleware up as global middleware and you can make multiple exclusions by extending the if statement with or $request->is().
Tackling this in routes
//Place all the routes you don't want protected here
Route::group(['middleware' => 'admin'], function () {
//Place all the routes you want protected in here
});
I am currently developing and application that has an API which I want to be accessible through middleware that will check if the user is authenticated using either Laravel's default Auth middleware and Tymone's JWT.Auth token based middleware so requests can be authenticated either of the ways.
I can work out how to have one or the other but not both, how could I do this? I'm thinking I need to create a custom middleware that uses these existing middlewares?
I am using Laravel 5.1
Thanks
Turns out I did need to make my own middleware which was easier than I thought:
<?php
namespace App\Http\Middleware;
use Auth;
use JWTAuth;
use Closure;
class APIMiddleware {
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next) {
try {
$jwt = JWTAuth::parseToken()->authenticate();
} catch (\Tymon\JWTAuth\Exceptions\JWTException $e) {
$jwt = false;
}
if (Auth::check() || $jwt) {
return $next($request);
} else {
return response('Unauthorized.', 401);
}
}
}
Then I use this middleware on my api route group like so after registering in the kernel:
Route::group(['prefix' => 'api', 'middleware' => ['api.auth']], function() {
I think you can use Route::group in your routes.php file and define the middlewares you want to use in an array.
Route::group(['middleware' => ['auth', 'someOtherMiddleware']], function()
{
Route::get('api/somethinglist', function(){
return App\Something::all();
});
});
If I'm not mistaken all routes defined within that route group is checked against the middleware(s) you specify in the array.