8

I have testet laravel Horizon on my local environment and everything is working as expected. When I am switching to production domain/horizon throws a 403 error. I have set the gate in HorizonServiceProvider as stated in the documentation - First step is just to get access without auth. My gate now looks like this:

{
    Gate::define('viewHorizon', function ($user = null) {
        return true;
    });
}

Can anyone suggest what I am missing?

link to 403 error link to 401 error - Dashboard without data

Der Heidi
  • 81
  • 1
  • 1
  • 3

5 Answers5

13

Check this GitHub comment: https://github.com/laravel/horizon/issues/563#issuecomment-480882947

You may have to register Horizon's service provider.

In config/app.php:

'providers' => [
        /*
         * Application Service Providers...
         */
        App\Providers\AppServiceProvider::class,
    ...
        App\Providers\TelescopeServiceProvider::class,
        App\Providers\HorizonServiceProvider::class,
    ],
LobsterBaz
  • 1,752
  • 11
  • 20
8

The error it's because horizon it's first go to the boot method, so i recommended you in your HorizonServiceProvider.php edit the boot method to allow your request like this:

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        parent::boot();

        Horizon::auth(function ($request) {
            if ($request->ajax()){
                return true;
            }
            else if (isset($request->let_me_go) && $request->let_me_go == 'ok'){
                return true;
            }else{
                throw new UnauthorizedHttpException('Unauthorized');
            }
        });
    }

So when you will go to your production server need to pass the parameter like this:

my-production-site.com/horizon/dashboard?let_me_go=ok

Itamar Garcia
  • 882
  • 10
  • 17
  • It got me a step further! It now loads the dashboard but it can't get the data. the stats, master and workload call is returning a 401 - See link in original post – Der Heidi Apr 18 '20 at 11:39
  • For testing - and moving forward I just changed the else statement to also returning true. Guess I will run without Auth for now :) – Der Heidi Apr 19 '20 at 19:38
5

You need to add the following method to App\Providers\HorizonServiceProvider class:

class HorizonServiceProvider extends ServiceProvider {
    
    // ...

    protected function authorization()
    {
        Horizon::auth(function () {
            return true;
        });
    }
}

This method overrides the parent method that authenticates HTTP requests.

Milad Rahimi
  • 3,464
  • 3
  • 27
  • 39
3

For me, the problem was that I'd set in app\Providers\HorizonServiceProvider.php:

/**
 * Register the Horizon gate.
 *
 * This gate determines who can access Horizon in non-local environments.
 *
 * @return void
 */
protected function gate() {
    Gate::define('viewHorizon', function ($user) {//https://laravel.com/docs/7.x/horizon#dashboard-authorization            
        return $user->id === \App\Constants\Permissions::ADMIN_USER_ID;
    });
}

And then I'd forgotten that I'd therefore need to log in at example.com/login before I'd be allowed to visit example.com/horizon.

See https://github.com/laravel/horizon/issues/563#issuecomment-500821983 and https://laravel.com/docs/8.x/horizon#dashboard-authorization

Ryan
  • 22,332
  • 31
  • 176
  • 357
0

Removing the second parameter [$request->user()] in the authorization() method allowed the Gate check() to execute. Otherwise, it was always returning false no matter what was inside the define() function

/**
 * Configure the Horizon authorization services.
 *
 * @return void
 */
protected function authorization()
{
    $this->gate();

    Horizon::auth(function ($request) {
        return Gate::check('viewHorizon', []) ||
            app()->environment('local');
    });
}

/**
 * Register the Horizon gate.
 *
 * This gate determines who can access Horizon in non-local environments.
 *
 * @return void
 */
protected function gate()
{
    Gate::define('viewHorizon', function ($user = null) {
        return $user->isAdmin();
    });
}
Syclone
  • 1,235
  • 13
  • 14