October: Invalid security token and Service Workers

Created on 19 Aug 2018  路  14Comments  路  Source: octobercms/october

I have read all the past issues with regards to the error message "Invalid security token" however none talk about Service Workers causing this issue.

When you add a Service Worker to October CMS you will get the following issues:

(Please note: In Firefox and Google Chrome you can turn off the Service Worker however you will still get issues)

  1. Login to backend wont work first time and you have to login 2 or 3 times.
  2. Saving files, you get constant problems trying to save files in the backend.
  3. Having two or more tabs opened at same time while working on the same website will cause issues!

Solution:

I'm using Google's Workbox - Service Worker Library and I have spoken to some Googler's about this issue. There is a solution to actually turn off the Service Worker's for the admin section. However, there is a security issue that needs to be taken into consideration! If you have setup the backend URL to a custom one to add an extra layer of security, you would not want to list that URL in Javascript and show people. So I would recommend using PHP to block Service Worker from caching the backend URL's.

So I open this issue for a feature request to be coded in php (hiding the backend custom URL) to make October CMS fully supportive of Service Workers and PWA websites by automatically turning off the Service Worker for admin webpages. (Hopefully I make sense?!)

So that's:
Type: Bug
Type: Conceptual Enhancement

Further information can be found here:

https://github.com/GoogleChrome/workbox/issues/1164
https://github.com/w3c/ServiceWorker/issues/1257

Completed Maintenance

All 14 comments

Hi, @ayumihamsaki ,

Had the same problem while testing jQuery 3.x, it was a minor bug in the octobercms.min.js file (Pull: jQuery from V2 to V3.3.1).
Maybe you had an error in console?

If not, might give it a try at the end of the week, and post my 'workflow'.

@ayumihamsaki , Hi, didn't have time to play with a fully PWA ready solution (or close to a workable copy), but I did small testing, and thought about an idea. Haven't yet digged in the Workbox docs, so this might sounds silly, but Isn't that easier to just specify "white listed routes" ?

@w20k

Isn't that easier to just specify "white listed routes"

Yes and no, because you dont want to write the URL route of your custom October CMS Admin in a Javascript File which hackers can read, if you are saying just to add the route in the service worker code. But if you are saying create a white list via php then I say yes, because then it would be hidden.

@ayumihamsaki , That was not exactly my idea :)

Just use approach that firewalls uses under the hood: specify only those route, that are public, and for all others - deny usage of SW. By default, if route is not specified, just don't use service worker. Hackers won't see your private routes anyhow (only by sniffing ports/routes, in this case), if you really need to use admin/private routes with Services workers, which might sounds strange for me, than - yeah, you have to do it in 'Engine' - php.

@w20k Cool idea, will create that for the backend and see if it will fix the issue.

@ayumihamsaki , you're welcome ;) Hope it helps!

@w20k Have tested it out, only half works. You also need to delete the pre-cache as well, so if the Service Worker is already cached or you open both the Admin and websites in different tabs in the same browser, you would still get the issue and need to clear the cache as well.

Doing both things I think will sort out the issue - still coding and testing...

I think the following three things should be added to October CMS to fix the issue, these are as follows:

  1. As w20k has said, give an option in the backend Settings to be able to block the Service Worker Route.

  2. OctoberCMS should Clear the Cache on the Admin Login Page, this would cover two main things, the first is clearing the Service Worker Cache or any other Cache that has been installed by the website beforehand. The second would be a security issue such as Web Cache Poisoning. To fix both issues October CMS should use the "Clear Site Data" Header on the admin login screen. For more information can be found here: https://www.w3.org/TR/clear-site-data/

A basic coding example of the header would be like this, for the admin login screen:

Clear-Site-Data: "cache", "cookies"

The above Code will remove all the cache and cookies before the User starts the login process - thus giving a clean screen!

  1. The third thing follows on from the second point with regards to security and that October CMS when a User Signs out of the Backend, the CMS should really be using the Clear Site Data Header. For this I would suggest using the following setup creating a Signing Out method that would fully secure the Webmaster / Admin, see Code:

Clear-Site-Data: "cache", "cookies", "storage", "executionContexts"

The above Code will remove all data and fully protect October CMS admin Users from leaking any information. Please note to see this working Live you can look at Github, because I know they are doing this process right now with their logins!

This is my conclusion from running some experiments. Maybe a feature enhacement and/or some more discussion on this issue. I hope this comment is useful.

@w20k @LukeTowers

@ayumihamsaki if you can submit a separate PR for each of those issues so that we can discuss them further from there that would be appreciated!

@LukeTowers Is it possible to request help on this, as it seems not as straight forward to add the headers using HTTP Responses as their are redirects setup and this Stack Overflow Q&A, is suggesting that it cant be done in Laravel and you need to use Javascript instead.

The only way for a site to instruct a browser to issue an HTTP request with a custom header is to use Javascript and the XMLHttpRequest object. And it needs CORS implemented on the target server to allow such ajax requests.

The file location I was looking at for Parts 2 and 3 is found here: https://github.com/octobercms/october/blob/master/modules/backend/controllers/Auth.php

@ayumihamsaki you can attach headers to the controller by setting up a middleware and attaching that to the controller.

Ideas (placement positions):

  • public function __construct() (Add the Javascript code to turn off Service Workers)

  • public function index() (Add middleware header: Clear-Site-Data: "cache", "cookies")

  • public function signout() (Add middleware header: Clear-Site-Data: "cache", "cookies", "storage", "executionContexts")

Please, can we try to fix this issue with a proper solution? This code made me cry for about an hour ;-). I don't think we should add middleware like such in the constructor of a framework Base class.

    /**
     * Constructor.
     */
    public function __construct()
    {
        parent::__construct();

        $this->middleware(function ($request, $response) {
            // Clear Cache and any previous data to fix Invalid security token issue, see github: #3707
            $response->headers->set('Cache-Control', 'no-cache, no-store, must-revalidate');
        })->only('signin');

        // Only run on HTTPS connections
        if (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] === "on") {
            $this->middleware(function ($request, $response) {
                // Add HTTP Header 'Clear Site Data' to remove all Sensitive Data when signout, see github issue: #3707
                $response->headers->set('Clear-Site-Data', 'cache, cookies, storage, executionContexts');
            })->only('signout');
        }

        // Add JS File to un-install SW to avoid Cookie Cache Issues when Signin, see github issue: #3707
        $this->addJs(url("/modules/backend/assets/js/auth/uninstall-sw.js"));
        $this->layout = 'auth';
    }

Also this causes an error in my projects which are extending the base Auth controller:

Closure object cannot have properties
at modules/backend/Controllers/Auth.php line 38


How to reproduce the "Invalid security token" issue? I can look into it to find a different way to solve this.

@adrenth why shouldn't middleware go in the constructor? Isn't that where it's supposed to live? How is this causing issues for you?

Was this page helpful?
0 / 5 - 0 ratings