Use multiple guard on one route in laravel - laravel

How i can use multiple guard on one route in laravel?
I have two guard: admin-api, user-api and i want to check if token for user is valid can be accessible, and if token not valid in users table, check token in admins table.
I use the following code but just second middleware Applied.
Route::middleware('auth:api')
->middleware('auth:api-admin')
->post('/user' , 'UserController#user');

It's been a while this question asked, but the other way to check multiple guards within one route without adding a custom middleware is pass several guards to auth middleware:
Route::middleware(['auth:api,api-admin'])->post('/user', 'UserController#user');

You can add an array of middlewares to your routes
Route::middleware(['auth:api', 'auth:api-admin'])->post('/user', 'UserController#user');

Related

MiddleWare vs CustomRequest for check user rights

Let's say there some users who have several posts. Every user has many posts, and every post belongs to one user.
To change post frontend uses URL like users/1/posts/3. The goal is to check, that post number 3 belongs to user number 1.
There are several ways to do it:
Check inside controller method or service(bad method IMHO)
Check inside custom request (authorize function)
Check inside middleware
I choose between the last 2, but have some doubts. The custom request should contain validation rules and do not be linked with authorization(SOLID), and I don't know if it's good to do it inside middleware.
I assume you want to check if user can modify the post.
For authorizing access https://laravel.com/docs/7.x/authorization#creating-policies is a way to go.
After defining policy you can reuse it in blade files, in controller and etc..
The policy defines rules for standard actions like create, read, update, delete.
For blades then you can:
#can('update', $post)
For methods in controllers:
$this->authorize('update', $post)
For anywhere else:
$user->can('update', $post)
You can use Policies in conjunction with custom Form Requests

Laravel middleware is "bypassed" when i submit the invalid token, but when it is a valid token, the middleware is executed

all my fellow friends, i have a question.
Route::group([
'middleware' => ['ensure.role:store', 'auth:api']
]
For simplification,
i have two roles : ADMIN and STORE
I have created a middleware that will validate user role, and if the user role is correct, then will allow the user to access the route.
It works fine.
I tried using ADMIN Jwt Token to access STORE routes, and rightfully i am kicked out, and vice versa.
But now, if i modify the token, lets say i add a string to any part of the token, and try to access any route, actually i am allowed to.
I tried var_dump and print something on the related middleware, and here are my observation.
1. If the token is VALID as one of the user role, then
the var_dump is executed, (means the middleware is executed)
2. if the token is INVALID as in i add / modify the original
token, then the var_dump is not executed, and so are the
others route middleware.
I am wondering what causes this behavior, and what could be the fix for this issue, as i need to throw 401 unauthenticated in any token invalid case.
Thank you
I figured it out.
After series of testing and reading, i found out that after laravel 5.3 and above, constructor is called before middleware. And because in my constructor i am using an user object before i am authenticated by the middleware, i encountered constructor error, because user is null.
Of course it is a bad practice to use user object in the construct, however due to the convenience of usage, i still decided to use it.
It sounds complex to use closure based middleware as alternative solution
So i use a workaround to do it.
I create a helper function that return me true if there is an user object or return abort(401); if there is no user object, then add this one line to all the constructors.
$this->checkAccess = EnsureRoleUtil::check('admin');
After that, i just do my next constructor as normally
public function __construct() {
$this->checkAccess = EnsureRoleUtil::check('admin');
$this->user = Auth::user();
$this->categoryM = new CategoryManager($this->user);
}
However, to be noted, it is not a good practice, it is just a hack / workaround.

Laravel: Automatically add parameter to urls

I have an application in which you can create a service and a service can have its own partial view.
So I created a route group with {service} prefix:
Route::group(['prefix' => '{service}', ... ], ... ).
// http://.../my-service/my-url
However, in order to know in which service the user is I need to add the service in every single route I have in my application. So I have done a middleware that shares $service to every view:
view()->share(['service' => $service])
But I don't know how to add $service prefix to every route without explicitly adding it. I would like doing something like
route()->prefix(['service' => $service])
and then every route have the prefix $service:
url("myurl") // -> url("$service/my-url") or
route('my-route')
Any idea?
EDIT:
Finally I decided to create a ServiceType model, create a middleware with a parameter and set to my route groups. Then in view I offer the user to switch between services of the same type.
Not is what I was looking but it's OK for now.
Question is still open if anyone knows the answer.
Put all your routes you want prefixed in a group and then add the prefix
Laravel docs on route prefixes

Whats the point of composing middleware in Koa?

I am diving into Koa2 and I see koa-compose. I get that I give it middlewares and it returns one, but why? What is the benefit of having multiple middleware wrapped as one instead of just adding them separately?
app.use(compose(m1, m2))
vs:
app.use(m1)
app.use(m2)
KoaJS uses koa-compose underneath (here), so app.use(compoase([m1,m2])); and app.use(m1); app.use(m2); are the same. Using koa-compose explicitly can give more power for customization. Following is one such case:
Adding middlewares through app.use(middleware), will cause all of the middlewares to be executed upon each request in the specified order. But if you want to selectively run different set of middlewares for each route (or in a different order), you can use explicitly use koa-compose to create specialized middleware stacks for each route.
var app = require('koa')();
var router = require('koa-router')();
var compose = require('koa-compose');
var allMiddlewares = compose([m1,m2,m3]);
router.get('/', allMiddlewares);
// selectively enable logging middleware for this route
router.get('/test', compose(logger, allMiddlewares));
app
.use(router.routes())
.use(router.allowedMethods());
I had the same questions of why we need to use koa-compose, since koa itself can handle multiple middlewares. But recently I have been working on the authentication part of my koa server.
I have to check if user is authenticated and sometimes I need to check if user role meets the requirement. In that case, I have two middlewares one is called isAuthenticated, another is hasRoles
Some routes expose to any user that is authenticated, so I can do
.get('/', auth.isAuthenticated, handler())
But for routes need to check if user role meets the requirement, I need to do
.get('/', auth.isAuthenticated, auth.hasRole('admin'), handler())
When I have other authentication middlewares, the middlewares I put in the route becomes pretty long.
I am benefited by using koa-compose, since in my case I can chain the isAuthenticated and hasRoles middlewares together.
requiresRole(role) {
return compose([isAuthenticated, hasRole(role)])
}
.get('/', auth.requiresRole('admin'), handler())
It's neat and less errors.

Why my routes are not ordered?

in my routes file I use a route group with segment like:
Route::group(['prefix' => request()->segment(1) ], function(){
//routes
});
Normally, my routes are in the order they were written at, but when using the group with request()->segment(1) routes just get disarranged (not just inside the group itself, but all of them), I need to use segment so every customer will have their own slug as the first segment in the URL.
so how can I fix this issue?
Use middleware to validate the user and allow them based on their slug
Please Make own middleware like jwt.auth
I developed my own middleware to filter slug based

Resources