opcodesio / log-viewer

Fast and beautiful Log Viewer for Laravel
https://log-viewer.opcodes.io
MIT License
3.49k stars 249 forks source link

This action is unauthorized #218

Closed foRsxs closed 1 year ago

foRsxs commented 1 year ago

Hi!

if I added to AuthServiceProvider

Gate::define('viewLogViewer', function (User $user) {
            return $user->isAdmin();
        });

LogViewer is load and I can see page, but on left side i got message Request failed with status code 403: This action is unauthorized. No log files were found. It seems like can't load log files

"message": "This action is unauthorized.",
    "exception": "Symfony\\Component\\HttpKernel\\Exception\\AccessDeniedHttpException",

In another project with version 1.8 all working is good

arukompas commented 1 year ago

Hey @foRsxs , what does your api_middleware configuration option look?

    /*
    |--------------------------------------------------------------------------
    | Log Viewer API middleware.
    |--------------------------------------------------------------------------
    | Optional middleware to use on every API request. The same API is also
    | used from within the Log Viewer user interface.
    |
    */

    'api_middleware' => [
        \Opcodes\LogViewer\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
        \Opcodes\LogViewer\Http\Middleware\AuthorizeLogViewer::class,
    ],

Make sure that the \Opcodes\LogViewer\Http\Middleware\EnsureFrontendRequestsAreStateful::class middleware is there because otherwise the frontend will be unauthenticated.

foRsxs commented 1 year ago

I'm not used config for log-viewer, but now I did publish vendor and config cache (with remove all cache files)

` /* -------------------------------------------------------------------------- Log Viewer route middleware.
Optional middleware to use when loading the initial Log Viewer page.
*/

'middleware' => [
    'web',
    \Opcodes\LogViewer\Http\Middleware\AuthorizeLogViewer::class,
],

/*
|--------------------------------------------------------------------------
| Log Viewer API middleware.
|--------------------------------------------------------------------------
| Optional middleware to use on every API request. The same API is also
| used from within the Log Viewer user interface.
|
*/

'api_middleware' => [
    \Opcodes\LogViewer\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
    \Opcodes\LogViewer\Http\Middleware\AuthorizeLogViewer::class,
],`

But it's not help (

If I remove Gate from auth provider - everything works fine. I don't know why api log-viewer not working with gate

arukompas commented 1 year ago

@foRsxs check the network tab in the browser for the files/logs request. Make sure the cookies are sent over and not blocked for any reason. Maybe you can share the screenshot of the Network tab and the frontend request made? With the headers and stuff.

foRsxs commented 1 year ago

Issue was in cookie. If local env without https u have to do this

'secure' => env('SESSION_SECURE_COOKIE', false)

in your config/session.php or in .env file, don't forget config:cache

trbsi commented 1 year ago

I would like to reopen this because I have the same problem on production server

arukompas commented 1 year ago

Hey @trbsi , same question applies here. Check the Network tab in the browser and make sure the cookies are sent with the XHR requests and not blocked for any reason. You'll see a yellow triangle next to the set-cookie header if there's problems sending it. It might be blocked due to incorrect config/session.php configuration in Laravel.

Let me know how it works out.

trbsi commented 1 year ago

It looks fine for me

Screenshot_1 Screenshot_2

arukompas commented 1 year ago

Hey @trbsi sorry, but the images are all cropped :/ can't see the end of the cookie where the warnings usually appear.

Either way, are you viewing the Log Viewer through an iframe maybe?

I can also see the the XHR request is HTTPS. Is the original page also loaded over HTTPS?

And lastly, what's the value of config('session.secure')?

trbsi commented 1 year ago

Thanks for responding. I installed another solution. Usually I would debug this, but right now I don't have a time for it

RenoLooijmans commented 1 year ago

I am experiencing the same issue.

Tried debugging it using the snippet below, but I can't wrap my head around it why it is not working... I installed a recent and clean install of Log Viewer. Api middleware is present in the log viewer config.

Gate::define('viewLogViewer', static function (?User $user) { if(request()->is('*api*')) { dd(request()->user()); } return ! is_null($user) && $user->isAdministrator(); });

returns the following: image

config('session.secure') returns false.

Request headers are:

image

image

Doesn't work on https either.

Any idea?

arukompas commented 1 year ago

Hey @RenoLooijmans , I know Laravel can be very sensitive to how you define and type-hint the params in Gate callbacks.

  1. What Laravel version is this? So I can test using that version as well.
  2. Can you try changing the ?User type-hint to just mixed ?
Gate::define('viewLogViewer', static function (mixed $user) {
    if(request()->is('*api*')) {
        dd(request()->user());
    }

    return ! is_null($user) && true;
});
  1. If above doesn't help, can you also dump some debug data like this:
use Illuminate\Support\Facades\Route;

//...

Gate::define('viewLogViewer', static function (mixed $user) {
    if(request()->is('*api*')) {
        $route = Route::getCurrentRoute();
        dd([
            'url' => $route->uri(),
            'session_id' => session()->getId(), // let's make sure the session ID is the same as the one from the initial page load
            'middleware' => $route->middleware(),
            'user_id' => request()->user()?->id,
            'user_id_from_gate_callback_params' => $user?->id,
        ]);
    }

    dump(['session_id' => session()->getId()]);

    return ! is_null($user) && true;
});

This gives me a result like this:

Screenshot 2023-04-05 at 08 39 27

Note how the session ID is the same on both requests, meaning it's persisted correctly. And that's the job of the middleware which should also show up for you as well.

Let me know what your result looks like!

RenoLooijmans commented 1 year ago

Hi Arunas,

Thanks for your quick reply.

Hereby my answers.

  1. Laravel Framework 9.52.5
  2. Also returns null, unfortunately..
  3. Session ID for the initial load is different than the one from the API, which is strange...! image

On each refresh, the session ID for the initial load remains the same, but the session ID from the API keeps changing on each load.

Any idea what I could be missing?

RenoLooijmans commented 1 year ago

Okay so I spend some time debugging my setup, and finally I got around fixing it. In the end, apparently my sanctum stateful domain was incorrect... Since I have not used stateful requests before, I was not aware this would be the issue. I have changed this accordingly and now it works.

arukompas commented 1 year ago

@RenoLooijmans hey, that's good news that you've resolved it! Sorry I wasn't responsive before, holiday weekend.

Do you mean your domain was not configured in the config('sanctum.stateful') ? https://laravel.com/docs/10.x/sanctum#configuring-your-first-party-domains

RenoLooijmans commented 1 year ago

You're all right ;-)

And I totally missed that part... I do use Sanctum, but not with stateful requests (API Tokens), so didn't really know about this. Apologies.

Looks like this is solved - thanks!

arukompas commented 1 year ago

@RenoLooijmans that's something that would be very useful to add in Log Viewer docs as well! I'll do that, thanks for finding the issue 💪

foRsxs commented 1 year ago

@arukompas I found new problem) If we use in config url like (https://example.com), but in browser open url with www (https://www.example.com/log-viewer) all requests in API will be with error 403

hamza094 commented 11 months ago

I've tried everything mentioned above but still encounter the following error: 'Request failed with a status code of 403: This action is unauthorized. I'm using Laravel 10 with the following packages:

laravel/sanctum version 3.2 opcodesio/log-viewer version 3.0"

If you have a moment, could someone please provide guidance on how to resolve this issue? Your help would be greatly appreciated.

,

arukompas commented 11 months ago

@hamza094 hey, it's usually due to middleware or gate policies being set up incorrectly.

Could you please share:

Hopefully I'll be able to help after that :)

hamza094 commented 11 months ago

in AppServiceProvider boot method

LogViewer::auth(function ($request) { return $request->user() && in_array($request->user()->email, [ 'ressie03@example.net', ]); });

in config/log-viewer.php

 'middleware' => [
        'web',
        /*\Opcodes\LogViewer\Http\Middleware\AuthorizeLogViewer::class,*/
    ],

     'api_middleware' => [
        \Opcodes\LogViewer\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
        \Opcodes\LogViewer\Http\Middleware\AuthorizeLogViewer::class,
    ],

in Kernel.php

 'api' => [
             'throttle:60,10',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
            \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
        ],    

I'm experiencing an issue where the authentication user is null in LogViewer, even though the authentication works fine throughout the rest of my application

arukompas commented 11 months ago

@hamza094 , I just had a similar issue myself, and the solution was to correctly define the Sanctum stateful domains (see here).

www.example.com is different from example.com, and in my case I had the wrong one defined, which is why my Log Viewer API calls were not authenticated. Sanctum refuses to authenticate API requests if they come from a different domain.

Try changing the app.url or sanctum.stateful configuration to see if it works.

yoeriboven commented 10 months ago

For now my issue was solved by removing www from APP_URL.

cambur commented 6 months ago

For now my issue was solved by removing www from APP_URL.

Exactly the same for me

stephenstack commented 5 months ago

Same here it seems, APP_URL must match the URL being called to open log viewer.

N3OGeorgy commented 5 months ago

There is a solution if the APP_URL in .env does not match the URL /log-viewer is being called? I see a back_to_system_url in config, but nothing that could set the correct APP_URL in this case.

LE: The answer is yes.

If your real website url is something like https://mysubdomain.domain.com and your APP_URL is something like https://myothersubdomain.domain.com then you need to add in .env SANCTUM_STATEFUL_DOMAINS = mysubdomain.domain.com

arukompas commented 5 months ago

@N3OGeorgy correct, although you can also use the more-recently-added Log Viewer-specific environment variable:

comma-separated list of domains allowed to communicate with the Log Viewer:

LOG_VIEWER_API_STATEFUL_DOMAINS=mysubdomain.domain.com,otherdomain.com
N3OGeorgy commented 5 months ago

@arukompas Good to know, thank you. It's easy to miss it actually. I didn't find any information about it in the docs. In config file is also not documented. Maybe something could be added like the info found on https://github.com/laravel/sanctum/blob/4.x/config/sanctum.php

arukompas commented 4 months ago

Added docs here: https://log-viewer.opcodes.io/docs/3.x/configuration/route-and-domain#production-domains