Laravel 8 | Not hitting policy method - php

I am trying to define some policies in Laravel 8 which I cannot get to work, however I have the same project in Laravel 7 which seemingly works perfectly.
I am using the JSON API Specification package and it comes built in with Authorizers which allow me to run a policy on different methods.
I am trying to add a policy for the 'create' on all routes no matter what.
I have the following code:
public function create($type, $request)
{
$this->authorize('create', $type);
}
In this context and example, $type = 'App\Models\User' if I do a dd before that line I can confirm that I am hitting that method.
Inside of my AuthServiceProvider I have the following:
public function boot()
{
Gate::guessPolicyNamesUsing(function ($modelClass) {
return 'App\\Policies\\' . class_basename($modelClass) . 'Policy';
});
}
Which as said earlier, works perfectly in another project.
The following is my policy, as you can see it's very basic.
<?php
namespace App\Policies;
use App\Models\User;
class UserPolicy
{
public function create(User $user)
{
return true;
}
}
If I make a constructor in the policy class I can confirm that it is getting hit and I am getting inside of the policy which is why this is confusing me so much.
I have tried changing the name of the method in case it was something clashing with the naming convention but nothing seems to agree with it.
I have tried to dump composer just as a double check but again, no luck.

The issue with this is that there wasn't currently an authenticated user and although specified in the method parameters a user it was still failing.
When providing a guest route, you still need to add the parameter to the method but make it optional.
public function create(?User $user)
{
// do logic here
}
The documentation for this can be found at the following link: https://laravel.com/docs/master/authorization#guest-users

Related

I have tried to apply a policy in my application, but it's not working properly

I'm trying to apply user policy's in laravel using the inbuilt user policy option. In the policy i have written it to check the if it's an admin and only give access to the admin. But the application applies the policy without checking the parameters anyway.
This is the User policy i'm trying to apply
use App\Models\User;
public function adminAccess(User $user)
{
return $user->user_type=== "administrator";
}
and I have applied it to the controller function using the following line of code.
$this->authorize('adminAccess');
The issue is the application applies the access restriction without checking the $user->user_type=== "administrator"
i commented out the check and add dd("ok") to see whether it runs like below. but it didn't run aswell.
use App\Models\User;
public function adminAccess(User $user)
{
dd("ok");
return $user->user_type=== "administrator";
}

Why a custom method causes the default policy methods to disable?

I'm using Laravel 5.5. All we know the resource method of Gate facade contains CRUD methods by default. By the way, I add a custom method into policy class using resource method as a third argument like this:
Registering Policy:
Gate::resource('users', 'App\Policies\UserPolicy', ['edit' => 'edit']);
Policy Class:
use HandlesAuthorization;
public function before(Admin $admin)
{
return $admin->isSuperAdmin();
}
/*public function view(Admin $admin)
{
return true;
}*/
public function edit()
{
return true;
}
But, this causes the default CRUD methods like view returns false. I use this abilities for certain routes using middleware helper.
Route::get('/view', 'UsersController#view')->middleware('admin-authorization:users.view');
Route::get('/edit/{id}', 'UsersController#edit')->middleware('admin-authorization:users.edit');
So, admin-authorization is like this:
Auth::shouldUse('web_admin');
if (Gate::denies($ability)) {
return abort(403);
}
return $next($request);
The default method and custom works fine on absence of each other. When I comment the view method, the edit method works fine and vice versa, and the before method is being called in two cases.
What should I do that the default and custom method work fine with each other? any help will be appreciated.
I know it's weird, But i found the solution!!
we must pass an array into the resource as third argument that contains both custom and default methods like below:
Gate::resource('users', 'App\Policies\UserPolicy', ['view' => 'view'/*default*/, 'edit' => 'edit'/*custom*/]);
It's done well.

Where does "auth" come from

I'm currently learning Lumen, I'm running a fresh install of Laravel 6.x .
I'm using RESTClient to stimulate my Lumen API/send http-Requests.
I want to set up some basic authentication with JWT now, and I already accomplished this.
I get a valid JWT and when I pass it through the following code, the firebase middleware (5.x) accepts the token, if valid, and rejects it if invalid.
The code doing the validation resides inside my AuthServiceProvider.php:
<?php
namespace App\Providers;
use App\User;
use Firebase\JWT\JWT;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\ServiceProvider;
//new Code
class AuthServiceProvider extends ServiceProvider
{
public function register()
{
//
}
public function boot()
{
// Here you may define how you wish users to be authenticated for your Lumen
// application. The callback which receives the incoming request instance
// should return either a User instance or null. You're free to obtain
// the User instance via an API token or any other method necessary.
$this->app['auth']->viaRequest('api', function ($request) {
$key = 'pawifjopawiejfpoaiwejfpoji';
$jwt = preg_replace('/^Bearer (.*)/', '$1', $request->header('Authorization'));
$decoded = JWT::decode($jwt, $key, ['HS256']);
//return User::where('email', $decoded->email)->first();
return "Hello From Auth!";
});
}
}
The router calling the middleware and routing its result to the controller resides in web.php and looks like this:
$router->get('myStorage', ['middleware' => 'auth', 'uses' => 'AuthController#myStorage']);
Now, my problem is this:
I've looked into all the depenencies inside providers/AuthServiceProvider.php, ServiceProvider.php insinde vendor/Illuminate/Support, Authenticate.php inside app/http/middleware and also bootstrap/app.php where the registering takes place.
The "auth" key/denominator, as it appears multiple times inside the sourcecode and also references the authentication middleware during routing, remains a mystery to me.
I don't know what object it points to.
I've tested changing it to "auth2" in all the places I found it (see above), but then I get this exception thrown by Lumen:
(2/2) BindingResolutionException
Target class [auth2] does not exist.
So somewhere, this class must have been defined.
Inside Authenticate.php, there is this line in the head of the code
use Illuminate\Contracts\Auth\Factory as Auth;
And I've manipulated it, alongside its occurrences in the whole code of authenticate.php .
But I always get the same error.
I want to know where this "auth" is coming from, because I also want to employ a middleware for AUTHORIZATION, following the AUTHENTICATION.
The routes would then look kinda like this:
$router->get('myStorage', ['middleware' => ['authenticate', 'authorize'], 'uses' => 'AuthController#myStorage']);
To do this, I think I need a better understanding of how and where this (third-party) middleware/its components are defined. Otherwise I will probably run into issues when registering this stuff for example.

How can we redirect a page to another if a session is not found using route in Laravel 5.3

I am using a session separately other than the default authentication sessions. If an user try to access my secured page, he should have the session set. If anyone without that session try to access means, they will be redirected to error page. I am using Laravel 5.3
The user can view the below two pages only if the session variable named 'secured_user' is set. Otherwise they will be redirect to the error page
Route::get('/secured-page1', 'ValidationController#CheckSecuredLogin_1');
Route::get('/secured-page2', 'ValidationController#CheckSecuredLogin_2');
The best option would be a policy.
You can create certain constrains and couple it with your models. Policies are especially suitable for changing your logic later on.
See here: Create Policy
Within you PagesPolicy, you can add this function:
public function before(User $user, $ability)
{
if ($user->isSuperAdmin()) {
return true;
}
}
public function seeSecurePage(User $user)
{
// Your custom Code and session handling
if(session("secured_user")) return true;
return false;
}
and in your controller.
$user->can("seeSecurePage","Pages");
If "can" fails, it will automatically redirect to error 403.
P.S.: Another possibility are Gates
You should use Laravel Middlewares to achieve this, I think middlewares are made for the work you need:
First create a new middleware by running the artisan command:
php artisan make:middleware CheckSesison
Then the CheckSession would look like this:
<?php
namespace App\Http\Middleware;
use Closure;
class CheckSession
{
public function handle($request, Closure $next)
{
if ($session_value != 'YOUR_DESIRED_VALUE') {
return redirect('home');
}
return $next($request);
}
}
Now in your routes file you can use laravel's route middleware() method to implement it like this:
Route::get('/secured-page1', 'ValidationController#CheckSecuredLogin_1')
->middleware(CheckSession::class);
Hope this helps!
In addition to the awnser above, you could also use middleware that's used on the routes and even group them if required. It is a simple, quick and clean solution. Inside the middelware you simple check if the session you require is there and depending on the result you take any action necessary.
Laravel middleware docs

How can allow the method in routes using laravel 5?

I'm trying to execute the method but it does not working. I know it is very basic and may be ask more time, but i didn't resolve.
Controller
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
class LockController extends Controller {
/**
* Show the profile for the given user.
*
* #param int $id
* #return Response
*/
public function index()
{
return view('lock');
}
public function login()
{
return view('login');
}
}
?>
Route
Route::get('/lock', 'LockController#index');
Route::get('/lock', 'LockController#login');
This Route::get('/lock', 'LockController#index'); route working fine using this http://localhost/laravelDev/public/index.php/lock url but another route does not working properly and i'm getting this error NotFoundHttpException in RouteCollection.php line 161:. For login method i'm using this url http://localhost/laravelDev/public/index.php/lock/login.
I searched about it, i follow the instruction of this accepted answer but it does not work, can any one guide me where i'm wrong.
You can mention the required methods which will be handled in controller file(s) in routes.php file.
Example:
Route::get('url/of/the/resource', 'controllername#action'); (o handle 'GET' requests).
Route::post('url/of/the/resource', 'controllername#action'); (For 'POST' requests).
Details:
Route::get('/user/register', 'UserController#showRegistrationForm');
This indicates to show a registration from when given url (When GET request is made) is given like below:.
http://localhost/your_laravel_project_folder/user/register
Route::post('/user/register', 'UserController#handleUserRegistration');
This indicates to handle the registration from data when user submits the registration form. (When POST request is made).
class UserController extends Controller
{
public function showRegistrationForm()
{
return view('User.register');
}
public function handleUserRegistration()
{
$registerInput = Input::all();
var_dump($registerInput);
}
}
You have two identicals routes for different methods? I don't think that should work.
I could work if one was get and the other post.
Also, usualy, the url is would be http://localhost/lock or http://localhost/lock/login. The public/index.php shouldn't be necessaire.
Change the second route to this, pretty sure it'll work:
Route::get('/lock/login', 'LockController#login');

Categories