0

I have a laravel app on a parent domain. SESSION_DOMAIN is set to .domain.com because I want the cookies to be shared with another subdomain first.domain.com.

I now want to publish another app at second.domain.com which is separate from domain.com and first.domain.com.

The SESSION_DOMAIN for this second app is correctly set to second.domain.com.

Everytime I try to login via sanctum I get an error CSRF token mismatch.

I'm pretty certain this is due to the multiple cookies on multiple domains since if I clear my cookies for the parent domain.com or use incognito mode or another browser then the issue goes away.

The issue only exists when both .domain.com and second.domain.com have a XSRF-TOKEN cookie token set.

Everything else seems to work fine, presumably because the other cookie Laravel uses called _session is prefixed by the app name and therefore unique.

Where as the XSRF-TOKEN is always called XSRF-TOKEN.

How can I set it up so that my parent domain can share cookies with first.domain.com but doesn't interfere with second.domain.com?

3
  • Cookies set for a domain are always accessible on subdomains as well. Only way to prevent that, would be to leave the domain portion out of the Set-Cookie header to begin with (developer.mozilla.org/en-US/docs/Web/HTTP/Headers/…: "If omitted, this attribute defaults to the host of the current document URL, not including subdomains.") - but I am not sure if Laravel allows for that via the configuration, plus you would have to explicitly set a second cookie valid for first.domain.com as well here then. Commented Jun 7, 2023 at 7:11
  • The other alternative would be that you configure your app under second.domain.com to use a different session name. Commented Jun 7, 2023 at 7:11
  • 1
    I don't think the session name has anything to do with it, it's already using a different session name. The name used for the XSRF-TOKEN is the issue. Commented Jun 8, 2023 at 1:22

2 Answers 2

1

I figured out a work around that seems to work.

By adding the following to my blade template that is rendering the SPA.

<meta name="csrf-token" content="{{ csrf_token() }}">

And then when initialising Axios (this is in bootstrap.js in the default Laravel setup) add the crsf-token as a default header.

window.axios.defaults.headers.common['X-CSRF-TOKEN'] = document.querySelector('meta[name="csrf-token"]').getAttribute('content');

This bypasses the cookie, you can see in Laravel's VerifyCsrfToken that it checks for this header first (actually second you could also send _token as a GET or POST param).

https://github.com/laravel/framework/blob/4ffac6f71467562dbe670f893af787bf5c610103/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php#L151

The one gotcha i've found is that when you logout of Sanctum you usually want to reset the token.

The best bet would be to return csrf_token() in the Logout response and then update the header similar to above.

e.g:

/**
     * @param \Illuminate\Http\Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function logout(Request $request): JsonResponse
    {
        Auth::guard('web')->logout();
        $request->session()->invalidate();
        $request->session()->regenerateToken();
        return response()->json([
            'message' => 'You have been logged out.',
            'csrf_token' => csrf_token()
        ]);
    }
axios.post('/api/auth/logout').then(response => {
    window.axios.defaults.headers.common['X-CSRF-TOKEN'] = response.data.csrf_token
})

I hope this helps someone else with the same problem!

Sign up to request clarification or add additional context in comments.

Comments

0

Setting SESSION_DOMAIN=domain.com does not help either because for some reason, it still appears as .domain.com in the browser making the cookies accessible to all subdomains.

Here is what worked for me:

First step, set SESSION_DOMAIN=null (makes the session domain to be set to domain.com instead of .domain.com if accessed via domain.com and first.domain.com instead of .first.domain.com if accessed via first.domain.com) in the .env file of the first project (the one accessed via both domain.com and first.domain.com).

This causes a problem whereby session is not shared between the two domains. To solve this, the next step is to redirect (301) http and https request made via first.domain.com to domain.com in your web server configuration for the project.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.