Multiple middlewares do not work as wanted - laravel

If I have 3 user roles (head, admin and moderator):
I want to allow head to all methods, admin to most methods and moderator to one method.
Inside InstitutionsController:
public function __construct() {
$this->middleware('head');
$this->middleware('admin')->only(['index', 'create']);
$this->middleware('moderator')->only(['index']);
}
By this I cannot open visit index method as moderator or admin, just as head...
How can I achieve this?
BTW my middlewares have: return !auth()->user()->isAdmin()?redirect()->home():$next($request) etc for other 2

You need to read up on middleware. They are classes that manipulate HTTP requests and responses. A request comes in, a response comes out. They’re processed one at a time. So if you have a middleware that checks a role, it’s going to check that role and throw an “Unauthorized” response if the user does not have that role.
As such, checking if a user can do something is not the job of middleware (as you have found). If you want to check a user can do something, use a policy around your resource instead.
The Authorization documentation has more information on creating policies and authorizing actions in your Laravel applications.

Related

Separate Controller for Admin Panel in REST API

I'm currently working on REST API using Spring Boot. Let's say i have product service with basic functionality in controller. There are two roles in user which are normal user and admin.
example:addProduct, getProduct, updateProduct, deleteProduct
User can only access getProduct endpoint and admin can access all endpoints.
Which one is better apporoach?
first approach:
api/v1/products/ -> do all get, post, delete, patch
second approach:
api/v1/products/admin -> get, post, delete, patch
api/v1/products -> get
I suggest using a Role-Based Access Control (RBAC) wherein each user has a role. and each role has permissions, e.g. get_post, delete_post, and so on. As your application gets bigger in scope, you can have fewer routes in this way.
Example situation: if a user posted a resource on api/v1/products, the system will check if the user has a "create_product" permission. If he has no access then your api should return 401 unauthorized

Laravel - using Google 2FA to protect all views

I'm working on my first Laravel project and have implemented 2FA according to this tutorial but unfortunately, the 2FA mechanism created is attached only to HomeController.
So if a user tries to access www.thingy.com/something from an unauthenticated state, they enter email and password as usual and then get directly to /something without the 2FA prompt appearing.
My first thought was adding the middleware bit to every __construct() function in each of my resource controllers, but they don't already have a __construct() function (can I add one anyway?) and even if that worked, it doesn't seem like the right way of doing it.
I also considered adding it to Controller itself since that's what every other controller is based on, but of course I wouldn't want 2FA required for non-authenticated views too (just register, login etc really because the site requires a login to use).
What's the correct way of doing this?
You can add the middleware to a group of routes in your routes/web.php file.
Route::middleware('2fa')->group(function () {
// All routes here will go through the "2fa" middleware
});

Laravel 5 - Authentication with Login-Form (users) and API-Request (students)

I want to authenticate normal users (users-table) with login form and laravel auth.
Additionally I want to authenticate students (students-table) with API-request like:
mylaravelsite.com/?studentkey=XXXXXXXXXXXXXXXXXX&studentname=YYYYY
How can I do this? I think with a middleware?
How can I use the Auth class to check if the logged in person is user or student or guest?
I like to build applications in the following way:
A route having a single purpose, meaning, one route is for authenticating users and another route is for authenticating students
Validating data on the middleware before performing ANY operation
Now to your question:
If you really need, you can create different routes linked to the same authentication method, and create a middleware to each where you 'manipulate' run-type which class the Auth is going to be used
auth()->getProvider()->setModel(App\Student::class);
There are other ways to do this, depending on the way you wish to authenticate. If you want a more detailed explanation, give us a scenario to work on:
How the user authenticates vs how the student authenticates
What is going to differ from these 2 authentications and how its handled
Note: You're authenticating users with a HTTP request to a certain route, which is the same as your example link, except that you're giving an HTTPGET example and default is POST on authentication

Laravel route in multiple middelwares

I want to have the same route within the auth:api middleware, and also out of it.
Right now, if I include it in both, only the one out of the auth:api is taken into consideration, even if the user is logged in.
Is there a way that if the user is logged in it goes to auth:api and if not it goes out of any middleware?
The reason to do this is that if the user is logged in, I want to access user information, and for that it needs to go through the auth:api.
As long as you're including the token in the request, you will be able to get access to the current User.
Out-of-the-box, Laravel will set the default guard to be web. When you place routes under the auth middleware it will set the default guard to be whatever is passed to the middleware i.e. when you have auth:api it will set the default guard to be api for that request.
If you want to be able to access the User without it being under the auth:api middleware, you will simply need to be explicit with what guard should be used e.g.
auth('api')->user(); // or Auth::guard('api')->user();
The same applies for check():
auth('api')->check(); // or Auth::guard('api')->check();
or if you're using the Request object:
$request->user('api'); // or request()->user('api');
It 's not possible to have multiple same routes in your application and work independently. Laravel will match the first one that it find in your routes map.
Create one route and check for authentication in your controller.
if (Auth::check()) {
// The user is logged in...
}

Check if user is authenticated in laravel API route

So I know API routes are not supposed to rely on sessions authentication, but my idea was to create some API routes, that could be used if needs be by third-party with proper authentication, but that could also be used internally, ie called to get the data I need for my web pages.
I changed the LoginController so that every time a user logs in, a Personal Access token is generated and stored in the database. When logging out, this token is deleted.
So as not to expose the token to the client side, I would like to use a middleware, that would detect, on an API call, if the request comes from a user who is already authenticated. If that's the case, I would retrieve the Personal Access token that belongs to the user, attach it to the request, and pass it onto the API.
Browser -- Query site.com/api/myRoute --> Middleware adds user's token to request if Auth::check() -- Pass-on request --> Controller
I've created a dummy API route to see if I can detect whether a user is authenticated, but that doesn't seem to work... I guess because the 'auth' middleware is not included.. however, if I do include it, I get redirected to home on every request...
Route::get('/test', function() {
if(Auth::check()) {
dd('Hello logged-in');
} else {
dd('Hello not logged-in');
}
});
Any lead on how to achieve that much appreciated!

Resources