Checking Authority without a Model Instance throws error - laravel

I have a policy defined in AuthServiceProvider and in blade file, I access it using #can and it throws following error.
Undefined property: Illuminate\Auth\Access\Gate::$check
Unfortunately, googling this sentence doesn't report anything so looks like it's just me facing this issue.
I'm on Laravel 5.4.
Policy Check in Blade File
#can("use-some-module", null)
You have access
#elsecan
You DO NOT have access
#endcan
Policy Defined in AuthServiceProvider
Gate::define('use-some-module', function ($loggedInUser) {
return <can access or not>
});

Related

Laravel Spatie MultiTenanct noCurrentTenant Exception Handle

I'm making a multitenancy system and I'm facing problem when trying to handle the NoCurrentTenant Exception..
I'm using spatie multitenancy
I'm expecting that when there is NoCurrentTenant exception is thrown , it should redirect to login route. But that is not happening.
Below is my Exception Hander register method.
public function register() {
$this->reportable(function (NoCurrentTenant $e) {
return redirect('/saml2/laraveltestidp/login');
});
}
But even after multiple tries it still shows below error only
Spatie\Multitenancy\Exceptions\NoCurrentTenant
The request expected a current tenant but none was set.

Laravel policy always returns 403

so I made a policy and whatever I do the Web page returns 403. im very new to laravel so most likely im missing something :)
I made a model by
php artisan make:model exercise | (I know I'm supposed to capitalize models but it was a typo)
Controller:
php artisan make:controller ExercisesController
Policy:
php artisan make:policy ExercisePolicy -m exercise
I registered policy in AuthServiceProvider.php (Also tried as 'App\Models\exercise'=>'App\Policies\ExercisePolicy'):
protected $policies = [
// 'App\Models\Model' => 'App\Policies\ModelPolicy',
exercise::class => ExercisePolicy::class,
];
In ExercisesController.php this is the function in which I use authentication:
public function create(\App\Models\User $user)
{
$this->authorize('create', $user);
return view('exercises/create');
}
And in policy this is how my create function looks like
public function create(User $user)
{
return $user->admin == true;
}
The route:
Route::get('/exercises/create', [App\Http\Controllers\ExercisesController::class, 'create']);
I tried putting die("Policy is called); and trying to just return true from the policy create function to check if it gets to that but it still returned 403 , at this point I'm pretty sure that the policy itself is not being called as it also returns 403 on default
If anyone could help thanks in advance!
The call to authorize is using the second argument to figure out what Policy to use. Since the second argument is $user it would be looking for a Policy for the User model which you have not defined. To use the Policy for the exercise model you would have to pass the class name so it would know what Policy to use:
$this->authorize('create', exercise::class);
Though you should correct your typo and rename the exercise.php file to Exercise.php and the classname to Exercise.
Laravel 8.x Docs - Authorization - Writing Policies - Methods without Models
Laravel 8.x Docs - Authorization - Authorization Actions using Policies - Via Controller Helpers - Actions That Don't Require Models
I had this same issue and what I learnt was that Policies would work only on authenticated route.
Make sure your request is authenticated while implementing policies.

Testing Laravel Sanctum acting as results in bad method call

I'm trying to test an authenticated API route which only an authenticated user can post to a specific route.
Looking at the Laravel Sanctum docs, I can use the code below to create and authenticate a user:
Sanctum::actingAs(
factory(User::class)->create(),
['*']
);
When I try replicate this, I get an error running the test
BadMethodCallException: Call to undefined method App\User::withAccessToken()
My test code is as follows:
public function an_authenticated_user_can_add_a_client()
{
$user = Sanctum::actingAs(
factory(User::class)->create(),
['*']
);
dd($user);
// $this->post('/api/clients', $this->data());
}
api.php
Route::middleware('auth:sanctum')->group(function () {
//Clients
Route::get('/clients/{client}','ContactsController#show');
Route::post('/clients','ContactsController#store');
Route::patch('/clients/{client}','ContactsController#update');
Route::delete('/clients/{client}','ContactsController#destroy');
});
I don't have the method withAccessToken() in my User class and can't see where this method is coming from or specified anywhere.
Any help would be greatly appreciated.
Laravel Sanctum for SPA uses normal session authentication so the default actingAs method works fine. The actingAs method in Sanctum is meant to use for api tokens. Hope it helps.
Your User model is missing the HasApiTokens trait, that gives the function you are missing to the User model. Also described in the documentation, under the section Issuing API Tokens.
use Laravel\Sanctum\HasApiTokens;
class User {
use HasApiTokens;
}

How to authorize user owns resource using API through middleware in Laravel?

I need to check if user is permitted to view resource. Request is sent by API and passes through auth:api middleware. I'm using Laravel 5.8
I tried to use middleware in route declaration like this:
Route::get('/user/{id}', 'UserController#get')->middleware('can:view,user')
or in method's controller code like this:
$user = Auth::guard('api')->user();
$this->authorize('view', $user, $anotherUserModel);
Each of these methods either lets user pass policy even it's hardcoded to stops user form achieving this or throws error:
{
"message": "This action is unauthorized.",
"exception": "Symfony\\Component\\HttpKernel\\Exception\\AccessDeniedHttpException",
"file": "C:\\xampp\\htdocs\\laravelapitest\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Exceptions\\Handler.php",
"line": 202,
[...]
}
but I'm expecting that user should be stopped and response code should be 403
Can you please give this a try and let me know if it fixes your problem.
Go to App\Exceptions folder and add the following at the top of the Handler.php file:
use Illuminate\Auth\Access\AuthorizationException;
add the following to $dontReport array in the same file:
\Illuminate\Auth\Access\AuthorizationException::class,
and the last step is to customize error response by adding the following code in the render function:
if ($exception instanceof AuthorizationException) {
return response()->json('unauthorized',403);
}

Controller Authorization not working in laravel 5.2

I want to authorize my delete action using the Controller Authorization. Instead of using DELETE, I am sending the delete directly to the controller. Student can be deleted by instructor.
I followed the approach as explained at -
Controller Authorization
Below is my function -
public function deleteProfile(Student $student)
{
//authorize the request
$this->authorize('deleteProfile',$student); //$student is valid Student object
$student->delete();
}
When I try to delete it gives me exception -
HttpException in Handler.php line 104: This action is unauthorized.
I found this approach simple so, tried to implement it. Is there anything which I am missing ?
Correct this file with your xxxPolicy.php
Add the intval() in case. And it`s work.
ProjectPolicy.php :
public function destroy(User $user, Project $project)
{
return $user->id === intval($project->user_id;
}
Register a gate policy where you put the logic of who can delete the request. If by that logic the current user can delete, it will be deleted else it will throw a not authorized exception like you did.
Or else you can manually give authorization on your controller method for the user
$this->authorizeForUser($user, 'deleteProfile',$student);
as per documentation "The Gate will automatically return false for all abilities when there is not an authenticated user". So before doing any authorization, please check Auth::user() if it returns a currently authenticated user."

Resources