Slim Authentication middleware for all routes except someone - php

I would like to have a Slim middleware to check authentication on all requests but some specific ones (for example login page).
I prepared the first AuthenticationMiddleware middleware to check all pages:
$app->add(new \App\Middleware\AuthenticationMiddleware($container));
Then I create another one AnonymousMiddleware that it is supposed to add a variable to set the exception to authentication checks:
$app->group('',function() use ($app){
$app->get('/','LogicController:index');
})->add(new AnonymousMiddleware($container));
The problem is that routes middleware (AnonymousMiddleware) is applied AFTER the general middleware (AuthenticationMiddleware);
I tried to use determineRouteBeforeAppMiddleware but it doesn't change the result.
I know I would set a route middleware for all authenticated routes but sounds a bit dangerous if I forget it, so, I would prefer to set which router are not under authentication then keep the check all other routes.

you need to chose different approach
you need to wrap all routes which should be "protected via Auth middleware" and exclude = not wrap routes which should not be handled by this middleware
you can add a group where all your routes will live and only login (and logout) route will be outside of this group ;)
something like
$app->group("/api/v1", function() {
// all your protected routes definitions here
})
->add(AuthenticationMiddleware::class)); // wrap by middleware
$app->post('/login', function(){});
$app->add(new MiddlewareForAllRoutes()); // middlewares for all routes

Related

Multiple middleware not working on laravel

I have a route resource group that can only be accessible by one of 2 middleware rules. I have registered them both and they both work independently if I test them both out alone, but when I have them together they don't work
I have tried running them both as either an "or" statement (which means the middleware works as intended) but this means that anyone not logged in can also access the routes for some reason. If I use a comma to separate the middleware, it's blocked for everyone. I know both middleware works ok as they do work if I try them independently. I am using the below code
Route::group(['middleware' => ['IsAdmin' or 'IsPatreon']], function(){
Route::resource('patreon', 'patreonGalleryController', ['names'=>[
'index'=>'patreonGallery.index',
'create'=>'patreonGallery.create',
'store'=>'patreonGallery.store',
'edit'=>'patreonGallery.edit',
'show'=>'patreonGallery.show',
'destroy'=>'patreonGallery.destroy',
]]);
});
How can I set it so that only either admin or patreon uses can see the paths?
Two middlewares are working separately.
IsAdmin is checking that user is admin
IsPatreon is checking that user is patreon...
You cannot merge these 2 middlewares by OR Operator
Probably you need to create new middelware, something like
IsAdminOrPatreon and do you checks inside of that middleware and assing that middleware to your Group..
Or you can try with middleware parameters, for example
Route::group(['middleware' => ['checkRoles:admin,patreon']], function(){
Route::resource('patreon', 'patreonGalleryController', ['names'=>[
'index'=>'patreonGallery.index',
'create'=>'patreonGallery.create',
'store'=>'patreonGallery.store',
'edit'=>'patreonGallery.edit',
'show'=>'patreonGallery.show',
'destroy'=>'patreonGallery.destroy',
]]);
});
And in you checkRoles middleware get the admin and patreaon roles like this:
public function handle($request, Closure $next) {
// will contain ['role1', 'role2']
$allowedRoles = array_slice(func_get_args(), 2);
// here you can loop and check your roles
}
Note! If you pass 'checkRoles:admin,patreon' you will get
array(admin,patreon)
If you pass 'checkRoles:admin' you will get
array(admin)
you can't use or condition inside middleware array. middleware array always return and condition. you can specify the user role inside your middleware.
gist sample role middleware
https://gist.github.com/ivanhoe011/931417be3e36b3f06e994bfe5cd004f9
You do something like this in your controller.
public function __construct()
{
return ($this->middleware('IsAdmin')) || $this->middleware('IsPatreon');
}
Each route on this controller will be authenticated by any one of middleware.

Laravel API Routing Middleware

I am running Laravel 5.4 and have my API routes setup with an API middleware that verifies an authentication token sent in the headers.
However, I want to avoid, or prevent the api/Login (route that generates the auth token) from being subject to the middleware.
Currently, in my API middleware, before any logic happens I have:
if(strpos($request->getUri(), 'Login')):
return $next($request);
endif;
I would like to remove checking if the route is the Login route before proceeding with the middleware logic. Is there a native way in Laravel to accomplish the above?
Note: all API routes are protected via an API middleware group which I have created in the Http/Kernel, then added the in the RouteServiceProvider.
You could add an except property in your middleware
Route::group(['middleware' => ['api'], 'except' => 'Login'], function () {
// Your Routes
});

Slim 3 group routes name for middleware

According to the docs I can't set a name for group of routes in Slim 3.
In auth middleware I want to split routes for needed authentication and not. Like:
# These routes will return 302 redirect on auth false
$app->group('', function () use ($app) {
$app->get('/first', 'HomeCtrl:first')->setName('first');
$app->get('/second', 'HomeCtrl:second')->setName('second');
})->add(new \Lib\Middlewares\CheckSession());
# These routes will return 403 on auth false
$app->group('api/', function () use ($app) {
$app->get('users', 'UsersCtrl:getUsers')->setName('users');
$app->get('pages', 'PagesCtrl:getPages')->setName('pages');
})->add(new \Lib\Middlewares\CheckSession());
In the second group I want the auth middleware to return 403 for ajax calls instead of redirecting in the first.
I don't want to manage an array with names of all routes like suggested in this great answer. It should be a name of the group and based on it to decide what kind of response code to return.
I don't want to manage two middlewares either. I'm looking for an elegant solution for managing current routes group.
Slim 3 groups do not have names - they are essentially syntactic sugar that does two things:
Prepend an optional URL segment to a set of route definitions.
Apply middleware to a set of route definitions.
To do what you want to do, your CheckSession middleware needs to check the request's path to work out if it starts with api/ and do send a 403 in that case. Alternatively, CheckSession could look for the X-Requested-With header which is usually sent with ajax requests.

Protect routes in Laravel 5.1

I am using Laravel 5.1 for my project. I am trying to secure Routes and make sure only logged in user can access certain routes. I am aware about middlewares but I am wondering if anyone post an example or a link explaining about middleware and how to protect a page using middleware.
Thanks
To build on the answer given by Joe Rose, you can also specify the middleware in your controller rather than in your routes.php file.
E.g you could have your routes set out like
Route::get('/example', 'ExampleController#index');
Route::post('/example/post', 'ExampleController#post');
Route::resource('blog', 'BlogController');
And then inside your controller reference it like so:
class ExampleController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
//....
If you're looking for more info, check out the link to the docs Joe gave, and also this blog post which explains what middleware is really well and how to create your own if you need to.
You are correct about using middleware. The included Auth middleware is what you should use, as long as you are also using the included Auth controller to authenticate users. You would write your route like this:
Route::get('/page', array(
'uses' => 'Controller#method',
'middleware'=>'auth'
));
(The above example is using a GET request, but it could other request types, like POST for example).
This will use the default behavior of the middleware which checks to see if the user is logged in (authenticated). You can also extend or overwrite the built-in functions to allow you to direct the application on where to send the user if they are or are not logged in, etc. Laravel's official documentation is a good starting point: link

Laravel4 route pattern error

I´m using laravel 4 for a cms project, and i´m having some problems with my routes...
These are my current routes
Route::get('/', 'IndexController#showNews');
Route::get('/logout', 'UserController#logout');
Route::resource('/login', 'UserController');
Route::resource('/user', 'UserController#index');
Route::resource('/user/{route}', 'UserController');
// Routes that shows us the pages...
Route::get('/{page}', 'IndexController#showPage');
Route::get('/{page}/{id}', 'IndexController#showPage');
To my user routes i have a custom router that routes the user information around, not really a problem. But all of that works great, but when i try to navigate to "/test" Wich would link to a test page, it gives me this error.
Route pattern "/user/{route}/{{route}}" cannot reference variable name "route" more than once.
It comes up to router logic, and i´m fairly new to laravel. Is there a way for me to work around this problem? It´s a collision between the user/route and the /route wildcards.
Route::resource('/user', 'UserController#index');
Route::resource('/user/{route}', 'UserController');
The problem is that you are using Route::resource to declare the routes, while by using Route::resource you are actually declaring a RESTful controller with a table of actions to be handled by Laravel automatically. You are using it incorrectly.
See the docs to see which routes are handled in the background (and hence the source of the conflict):
Take a look at the table called Actions Handled By Resource Controller
For any route handler that is not within the table you will have to declare separate routes. Something like:
Route::get('foo/filter/{filterName}/{filterValue}',
array('as'=>'filteredroute','uses'=>'FooController#filter'))
As a summary, Route::resource enables you quick CRUD RESTful access.

Categories