Using Laravel & Statamic without Cookies

Everybody knows them, nobody likes them: cookie banners. They are only required if technically unnecessary cookies are to be used. However, opinions differ when cookies are necessary. Obviously, the safest way to go is without cookies at all. How to disable cookies in Laravel and what to look out for, is explained in this article.

Which cookies does Laravel use at all?

When you set up a fresh Laravel application, two different cookies are used by default. On the one hand there is the session cookie. This cookie stores for example form entries, error messages and everything else you want to keep in the user session. The second cookie is the XSRF token. This is used in forms to prevent (as the name suggests) Cross Site Request Forgery.

Are the Laravel cookies technically necessary?

Here I would like to point out that I am not a lawyer. This is not legal advice. I can only report here what I have read and heard elsewhere. In case of doubt, please contact a competent lawyer.

But back to the actual topic. First of all, the question here could be confirmed in general. After all, both cookies are used to make certain areas of your application work. On the other hand, this is the crux of the matter. Certain areas.

Some authorities believe that just because you have a form somewhere on the site, for example, you can't just register a session cookie for form input across the board. The decisive factor could be whether the visitor also wants to use the form. The case is different again, if you don't offer a form on your site at all. Why then store an XSRF token? Who could then speak of technical necessity?

Yeah, you will say. But I need it for the login form. That's what my editors use. Well, but not all regular users of the site. So it is not necessary for them. As you can see, you quickly get into ambivalent situations. So why not disable cookies altogether?

Can I just disable cookies altogether?

It all depends. If you don't need cookies, for example you don't use login and there are no forms in use anywhere on the site, then you can simply disable cookies. Cookies are defined in middlewares in Laravel. So you can basically just disable those middlewares.

All middlewares are defined in the Kernel.php. You can usually find it here: app/Http/Kernel.php. There you have to comment out the following middlewares:

  • App\Http\Middleware\VerifyCsrfToken

  • Illuminate\Session\Middleware\StartSession

That's it. After that you have to clear your cookies once, if you have already visited the site. If you visit your site again, no more cookies should be set.

What if I can't disable the cookies?

If you need cookies in general, you can simply leave them enabled. However, if you need them only in certain areas and want to be on the safe side, the case becomes a bit more complicated. Here we have to interfere with the two middlewares mentioned above.

There are two methods in VerifyCsrfToken and StartSession that we can take advantage of. First of all, let's start with VerifyCsrfToken. This class is already created by Laravel itself within our application and can be easily customized.

Here we have the inherited method shouldAddXsrfTokenCookie(). We can override this in our own class. There we can check, for example, whether the user has accessed a certain path. Ideally, of course, one would rather use a regular expression here, but for the sake of understanding I'll keep it simple at this point.

It may then look like this:

class VerifyCsrfToken extends Middleware
{
    public function shouldAddXsrfTokenCookie(): bool
    {
        if (request()->path() === 'login') {
            // Let the parent class do its magic.
            return parent::shouldAddXsrfTokenCookie();
        }
        
        // We only want Cookies for the login path.
        return false;
    }
}

Now we have to adjust StartSession. This is a bit more elaborate, but it is not too difficult. First, we need to create our own StartSession class. By default, Laravel simply uses the class from a package. Our class StartSession then inherits from the original class. Of course, you can name the class something else.

It will look like this:

namespace App\Http\Middleware;

class StartSession extends \Illuminate\Session\Middleware\StartSession
{

}

Afterwards we have to register our class in the Kernel.php. So we replace Illuminate\Session\Middleware\StartSession with App\Http\Middleware\StartSession. Now we can change the middleware here as well. This is where we can override and customize the inherited sessionIsPersistent() method. For demonstration purposes, we again simply check whether the called path is login.

class StartSession extends \Illuminate\Session\Middleware\StartSession
{
    protected function sessionIsPersistent(array $config = null): bool
    {
        if (request()->path() === 'login') {
            // Let the parent class do its magic.
            return parent::sessionIsPersistent($config);
        }

        // We only want Cookies for the login path.
        return false;
    }
}

And that's it. Cookies are now only set for our example path. Of course you can check everything you want there. Common is for example to define an Allow List with different paths and then check these.

And what do I need to consider with Statamic?

With Statamic, the whole thing actually works quite similarly. I have solved the problem here, for example, so that all forms end up in their own collection and all paths follow the pattern form/xyz. Statamic itself sends all forms to a path !/forms/xyz and processes the input there. In addition, there is of course the control panel, which also requires cookies. The route to the control panel can be freely defined in the configuration.

For the sake of simplicity, I have put all this together in one trait:

trait CookieAllowed
{
    private function isCookieAllowed(string $path): bool
    {
        $pattern = '/^(!\/forms\/|form|' . config('statamic.cp.route') . ')/i';
        if (!preg_match($pattern, $path, $matches)) {
            return false;
        }

        return true;
    }
}

I then use this trait in the two middlewares. So in VerifyCsrfToken:

class VerifyCsrfToken extends Middleware
{
    use CookieAllowed;

    public function shouldAddXsrfTokenCookie(): bool
    {
        if ($this->isCookieAllowed(request()->path())) {
            return parent::shouldAddXsrfTokenCookie();
        }

        return false;
    }
}

And of course once again in StartSession:

class StartSession extends \Illuminate\Session\Middleware\StartSession
{
    use CookieAllowed;

    protected function sessionIsPersistent(array $config = null): bool
    {
        if ($this->isCookieAllowed(request()->path())) {
            return parent::sessionIsPersistent($config);
        }

        return false;
    }
}

Cookies are now only set if it is absolutely necessary for Statamic. You can then (in my opinion) do without a cookie banner without any problems.

I hope I could bring a little light into the darkness of Laravel cookies. If you have any questions or suggestions, please let me know in the comments. Otherwise you can of course use the contact form. I say goodbye at this point. Until then, farewell.

There are no comments yet.