Laravel 5.1 Passing Parameters to Middleware with Route Groups - laravel

I am trying to implement a JWT library for an API I am working on and I want to be able to wrap my entire API route group in token checks with a small number of exceptions. The problem I am having is not specific to JWT.
In a controller constructor, when I apply the middleware, I am able to use this syntax to apply jwt.auth to the entire controller and exclude the 'authenticate' endpoint.
public function __construct()
{
// Apply the jwt.auth middleware to all methods in this controller
// except for the authenticate method. We don't want to prevent
// the user from retrieving their token if they don't already have it
$this->middleware('jwt.auth', ['except' => ['authenticate']]);
}
When I attempt to do the same thing in my route group I cannot get the 'exception' array to pass correctly. This causes the authenticate method to require a token (which it can't require because it is the endpoint to RETRIEVE the token).
Route::group(['prefix' => 'api', 'middleware' => 'jwt.auth', 'except' => ['authenticate']], function()
{
Route::resource('authenticate', 'AuthenticateController', ['only' => ['index']]);
Route::post('authenticate', 'AuthenticateController#authenticate');
});
I have a feeling this is a syntax issue, but I cannot find anyone else asking this question and the parser doesn't choke on it, it just doesn't work. Any help would be much appreciated!

I took a brief look in laravel/framework and I didn't see support for this. I would suggest using nested Route::group's something like the following.
Route::group(['prefix' => 'api'], function() {
// Not explicitly behind a middleware
// However a controller could still have a middleware injected.
Route::controller('Auth/AuthController');
// Authenticated Routes
Route::group(['middleware' => 'auth'], function() {
Route::get('secret', 'SecretsController#index');
});
});

Related

Laravel passport public api routes

I am trying to code a login function for my api that takes a username and password then give you a password grant token to make api requests. The login route when called gives you
{
"message": "Unauthenticated."
}
I am using passport on laravel to do secure the api. Why am I getting a 401 when the route does not have the auth:api middleware? I tried using a clousure to see if I get could get a response and the closure did not give me an error.
Route::group(['prefix' => '/v1', 'middleware' => ['auth:api'], 'namespace' => 'Api\V1', 'as' => 'api.'], function () {
Route::post('/post/like','PostLikeController#store');
});
Route::group(['prefix' => '/v1', 'namespace' => 'Api\V1', 'as' => 'api.'], function () {
Route::post('login', 'Auth\LoginController#login');
});
Does your login controller have a constructor? sometimes middleware is set in there?
Otherwise I've also had issues with having the middleware routes above the public ones.
Try putting the public routes in the file first and also checking the LoginController.php for a constructor which might be setting a middleware
It possibly due to the same prefixes, as it does not overriding but instead stacking on top of each other.
I suggest for your login route, possibly, you can use this
Route::post('login', 'Auth\LoginController#login')->withoutMiddleware([FooMiddleware::class]);
If it's still does not help try putting your login route above the middlewared route.

Laravel multi auth protecting route multple middleware not working

I have created an extra middleware admin and I want to protect my routes. Adding one single middleware 'auth' or 'auth:admin' is working.
Route::get('/calendar', function () {
return view('app', ['data' => []);
})->middleware('auth');
But I want that as an admin you can also access the user routes but this is not working. If I try the following, and I log in as an admin I get redirected to the login page all the time.
Route::get('/information', ['middleware' => ['auth', 'auth:admin'], function () {
return view('app', ['data' => ['auth' => Auth::check()]]);
}]);
But if I change ['auth', 'auth:admin'] to ['auth:admin','auth'] it is working for admin but not for user. So it seems that only the first element of my middleware in array is being recognized. Does anybody have any idea why my multiple middlewares are working seperate but not together? Any help is appreciated
If you are trying to allow multiple 'guards' to be checked for a route you can pass multiple guards as parameters to the Authenticate middleware, auth.
auth:web,admin (assuming web is your default guard).
This will try to resolve a user (Authenticatable) from each guard passed in. If any guard returns a user (Authenticatable) you pass through authenticated. If not you are a guest.
If you set the middleware auth and auth:admin those are 2 separate 'middleware' in the stack that are unrelated.
Route::get('/information', ['middleware' => ['auth', 'auth:admin'],function () {
return view('app', ['data' => ['auth' => Auth::check()]]);
}]);
in this code. ['auth', 'auth:admin'] that's mean you need to login default guard and admin guard. if you need only login admin guard, ['auth:admin']

Return additional column if user is authorized - API

I have an Laravel-base API which handles both client and admin endpoints (there are two sites like domain.com and admin.domain.com).
My auth is based on cookie, which domain is <.domain.com>. As you can see, this cookie is acceptable for both domains.
I use Eloquent Api Resources for transformation data layer. Is my when() route check here safe and right?
public function toArray($request)
{
return [
'name' => $this->name,
'created_at' => (string)$this->created_at,
'status' => $this->when($request->route()->getName() === 'api.admin.users.index', $this->status)
];
}
Before I used $this->when(Auth::check(), ...), but because my auth cookie is acceptable for client site too, unneeded data might be fetched.
My route:
Route::group(['prefix' => 'admin', 'as' => 'api.admin.', 'middleware' => 'auth:api'], function () {
Route::resource('users', ...);
});
If user is not authorized, he wouldn't get data because of middleware. At the same time, authorized used (who has non-expired cookie) wouldn't get unneded data while being on client site.
Thank you!
I think your approach is fine. The route name is something internal and the user cannot tinker with it. You could improve it by using \Route::is('api.admin.*') though. It would then work for all of your admin API routes.

Laravel grouping routes what is best prefix or middleware

When I start thinking grouping my routes and check the documentation. I lost there. There are too many things like prefix, middleware etc.
What is the best way to group routes?
Route::group(['middleware' => 'admin'], function () {});
Route::group(['prefix' => 'admin'], function () {});
Route::group(['namespace' => 'admin'], function () {})
Which approach is best? And why? When to use what approach?
Wait. Prefix and middleware are two different things
prefix is a way to Prefix your routes and avoid unnecessary typing e.g:
Route::get('post/all','Controller#post');
Route::get('post/user','Controller#post');
This can be grouped using prefix post
Route::group(['prefix' => 'post'], function(){
Route::get('all','Controller#post');
Route::get('user','Controller#post');
})
In the other hand, Middleware :
Middleware provide a convenient mechanism for filtering HTTP requests entering your application. For example, Laravel includes a middleware that verifies the user of your application is authenticated. If the user is not authenticated, the middleware will redirect the user to the login screen. However, if the user is authenticated, the middleware will allow the request to proceed further into the application.
For example using last example now i want the users to be authenticated in my post routes. I can apply a middleware to this group like this:
Route::group(['prefix' => 'post', 'middleware' => ['auth']], function(){
Route::get('all','Controller#post');
Route::get('user','Controller#post');
})
You should check the docs to get more informed.
https://laravel.com/docs/5.5/middleware
https://laravel.com/docs/5.5/routing#route-groups
Both are different But to use both at the same time Best technique for grouping route middleware and prefix your route avoid unnecessary typing
Route::group(['prefix' => 'admin','middleware' => ['auth:admin']], function() {
Route::get('dashboard','AdminController#dashboard');
});
It may not be related to the current question, but if anyone is wondering how to use grouping prefix and middleware as well as controller in a scenario where you need auth check and then need a prefix to avoid repeat typing for the specific controller group, you may try the following way.
Route::middleware(['auth', 'verified'])
->controller(\App\Http\Controllers\AdminController::class)
->prefix('dashboard')->group(function() {
Route::get('/', 'adminIndex')->name('admin.index');
});
Or,
Route::group(['middleware' => ['auth', 'verified'], 'prefix' => 'dashboard'], function () {
Route::controller(\App\Http\Controllers\AdminController::class)->group(function (){
Route::get('/', 'adminIndex')->name('admin.index');
});
});

LARAVEL: How to use middleware on named routes

I've been working on an app that initially didn't use middleware. Later on, I decided to add middleware and had to change my routes from something like:
Route::get('admin/poems', array('as' => 'poems', 'uses' => 'PoemsController#poem'));
to
Route::get('admin/poem', ['middleware' => 'auth', 'uses' => 'PoemsController#poem']);
Now the disadvantage is that I had been redirecting to this route (poems) several times and adding middleware as indicated will require me to go through all my code and change the name of the route in the redirect.
How do i solve this problem?
Thanks for any help.
You don't need to lose the name of your route, the array will still accept it along with your middleware.
Just add it in to look like so:
Route::get('admin/poem', ['middleware' => 'auth', 'as' => 'poems', 'uses' => 'PoemsController#poem']);
This way you don't need to go through and rename your routes anywhere and can still protect it with auth middleware.
try put middleware to a group route
Route::group(['middleware' => 'auth'], function () {
Route::get('/', function () {
// Uses Auth Middleware
});
Route::get('user/profile', function () {
// Uses Auth Middleware
});
});

Resources