Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

cornelmventech's avatar

Discrepencies between web and api auth in multi-tenant app

I've got a Laravel / Inertia / Vue monolith that is using Spatie's laravel-multitenancy package. When I run the application locally, the migrations ensure that a default tenant is created with my locally hosted URL (<app_name>.test in my case as I'm using Herd). When I then create users and assign them to this first tenant, I can access the web routes normally and call functions such as Auth::user() without issue.

However, I can't do the same for my api routes, and I don't know why. I get 401 errors when trying to access API routes from the frontend using axios:

function getData(): Promise<null | IChart> {
    return axios.get(props.url).then(response => {
        emit('response', response.data);

        return Charts.create(response.data)
    });
}

Additionally, I can't call something like Auth::user() in my API controllers, I just get null.

I'm using Tenant middleware on both web and api:

    protected $middlewareGroups = [
        'web' => [
            EncryptCookies::class,
            AddQueuedCookiesToResponse::class,
            StartSession::class,
            ShareErrorsFromSession::class,
            VerifyCsrfToken::class,
            SubstituteBindings::class,
            HandleInertiaRequests::class,
            AddLinkHeadersForPreloadedAssets::class,
            NeedsTenant::class,
        ],

        'api' => [
            EnsureFrontendRequestsAreStateful::class,
            ThrottleRequests::class . ':api',
            SubstituteBindings::class,
            NeedsTenant::class,
        ],
    ];

Also, I have the following set for middleware on the api routes:

Route::middleware(['auth:sanctum', 'verified', 'can:access'])->group(function () {
...
}

When I remove these and just make middleware [], then I can actually access the routes (I don't get a 401, but I still can't use Auth::user() in my api contollers.

I don't really know what is going wrong or how to fix it. For some reason this is not happening on the production or UAT servers, but just locally.

0 likes
2 replies
LaryAI's avatar
Level 58

It sounds like you're facing issues with authentication and tenant resolution in your API routes. Here are a few steps to troubleshoot and potentially resolve the issue:

  1. Ensure Sanctum Configuration: Make sure that Sanctum is properly configured to handle stateful authentication. In your sanctum.php configuration file, ensure that your local domain is listed under stateful domains:

    'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', 'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1,<app_name>.test')),
    
  2. Check CSRF Token: Ensure that your frontend is sending the CSRF token with the API requests. This is necessary for stateful authentication. You can include the CSRF token in your Axios requests like this:

    import axios from 'axios';
    import { Inertia } from '@inertiajs/inertia';
    
    axios.defaults.withCredentials = true;
    
    function getData(): Promise<null | IChart> {
        return axios.get(props.url).then(response => {
            emit('response', response.data);
    
            return Charts.create(response.data);
        });
    }
    
  3. Verify Middleware Order: Ensure that the middleware order is correct. The EnsureFrontendRequestsAreStateful middleware should be placed before auth:sanctum in your api middleware group:

    protected $middlewareGroups = [
        'api' => [
            \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
            'throttle:api',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
            \App\Http\Middleware\NeedsTenant::class,
        ],
    ];
    
  4. Check Session Configuration: Ensure that your session configuration is correctly set up for your local environment. In your .env file, make sure the session driver is set to cookie or file:

    SESSION_DRIVER=cookie
    
  5. Debugging Auth Issues: Add some debugging to your API controller to check if the request is authenticated and if the tenant is correctly resolved:

    public function someApiMethod(Request $request)
    {
        // Check if the request is authenticated
        if (Auth::check()) {
            $user = Auth::user();
            // Log the authenticated user
            \Log::info('Authenticated user:', ['user' => $user]);
        } else {
            \Log::info('User not authenticated');
        }
    
        // Check if the tenant is resolved
        $tenant = app(\Spatie\Multitenancy\Models\Tenant::class);
        \Log::info('Current tenant:', ['tenant' => $tenant]);
    
        // Your existing logic
    }
    
  6. Check for CORS Issues: Ensure that your CORS configuration allows requests from your local domain. In your cors.php configuration file, make sure your local domain is allowed:

    'paths' => ['api/*', 'sanctum/csrf-cookie'],
    
    'allowed_methods' => ['*'],
    
    'allowed_origins' => ['http://<app_name>.test'],
    
    'allowed_headers' => ['*'],
    
    'exposed_headers' => [],
    
    'max_age' => 0,
    
    'supports_credentials' => true,
    

By following these steps, you should be able to identify and resolve the discrepancies between your web and API authentication in your multi-tenant application. If the issue persists, consider checking the logs for any additional clues or errors that might help in diagnosing the problem.

1 like

Please or to participate in this conversation.