I have been having problems with my site in Laravel for some time. I have an Angular frontend and I'm using an api to query the specific user's data so that a specific user can change his data in his profile page. With that said, I obviously don't want unauthorized people to be able to go to other profile pages to change their data as well.
For example:
On my page, with the URL .../user/1
the user can query his data. The problem with this is: If you change the 1
in .../user/1
to .../user/2
for example, the person can access to the data of the person with id 2
.
I tried following:
In my api.php
:
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
// Get Specific User
Route::get('user/{id}' ,'App\Http\Controllers\UserController@getUserById')->middleware('auth');
Unauthorized users can no longer access the profile page, but all Authorized users can access all other users and change their data.
I also tried: $id = Auth::id()
, but this returns me Attempt to read property "id" on null
The problem seems to me to be quite complicated, as I somehow need the id of the users currently logged in and make sure they can't access other users id. Do you have any idea how I could best do this?
I am using Laravel 8
Thanks a lot!
CodePudding user response:
Authorization can be challenging but fortunately, Laravel comes with serveral tools to help you.
One of them is policies which allows you to control who can view/store/update/delete resources (like your users).
The full documentation about authorization covers this topic very well: https://laravel.com/docs/8.x/authorization
That being said, for this specific case - the user - you could do something like auth/me
that show the profile of the authenticated user (without passing the id
as a parameter).
As always, there are many ways to do the same thing and in the end it all depends of your project, your experience, your goals...
CodePudding user response:
IMO, you should use /users
routes in regards to users' CRUD and a /profile
route for editing the user's data.
Anyway, there is a simple way to achieve what you need with middlewares.
Let's say that you want to allow to use a route ONLY if the {id}
parameter is the same as the authenticated user.
You can create a very basic middleware IE ResourceOwner
<?php
namespace App\Http\Middleware;
use Closure;
class ResourceOwner
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if ($request->id !== auth('api')->user->id) {
abort(403);
}
return $next($request);
}
}
The middleware will check if the incoming id
parameter is the same as the user logged in, if not, abort throwing a 403
error response.
In order to use this middleware, you can add it to your route
use App\Http\Middleware\ResourceOwner;
Route::get('user/{id}' ,'App\Http\Controllers\UserController@getUserById')->middleware(['auth', 'ResourceOwner']);
Please note that auth('api')->user->id
will depend on how you are authenticating your users