Fix broken styles when using .htpasswd with WordPress Gutenberg

Gutenberg is awesome. Once setup, it allows any non-technical person to add new pages to their website and to do so in a visual drag-and-drop fashion.

As much as I enjoy working with Gutenberg, I sometimes run into strange issues like the one I'm going to talk about below.

Password protecting a Gutenberg site without breaking the admin styles

You just finished developing your client's site locally, you're now ready to deploy it to pre-production. Given that their site is not ready for prime time yet, you strap your usual .htaccess on top of it to password protect the entire website.

AuthUserFile /var/www/www.my-client-site.com/.htpasswd
AuthType Basic
AuthName "Restricted Area"
Require valid-user

# BEGIN WordPress
# Les directives (lignes) entre « BEGIN WordPress » et « END WordPress » sont générées
# dynamiquement, et doivent être modifiées uniquement via les filtres WordPress.
# Toute modification des directives situées entre ces marqueurs sera surchargée.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

# END WordPress

Problem, password protection works fine on the frontend but every page in the administrator area seems to ignore styles completely.

Solution

Gutenberg is asynchronous by design. One thing I love about it is that while editing a page locally, I can still make changes to any block template and they'll show up instantly. While this feature is a must-have for any page-builder worth its salt, it also means that the website has to make http requests to himself for external ressources like stylesheets and script files.

As we've enabled password protection and WordPress doesn't natively handle this case yet, we have to use a little htaccess trickery to re-enable styles :

SetEnvIf Referer www.my-client-site.com noauth=1AuthUserFile /var/www/www.my-client-site.com/.htpasswd
AuthType Basic
AuthName "Restricted Area"
Require valid-user
Require env noauth
# BEGIN WordPress
# Les directives (lignes) entre « BEGIN WordPress » et « END WordPress » sont générées
# dynamiquement, et doivent être modifiées uniquement via les filtres WordPress.
# Toute modification des directives situées entre ces marqueurs sera surchargée.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

# END WordPress

In essence, these two lines means :

  • If the request comes from www.my-client-site.com, then set the env variable noauth to be true.
  • If the request comes from an authenticated user or the env variable noauth is true, authorize the request.

And with that, our meticulously crafted styles are back and visible on the frontend as well as in the admin area of the client's website.

Obligatory security warning

It may be possible to spoof the HTTP Referer Header and thus bypass the auth process completely.

In the case presented above I found that the risk was worth taking as the password protection is mainly put in place to block undesired users and to take an extra step in preventing search engines from crawling the website.

Use your own judgement and generally don't copy paste code from a random blog on the interwebs 😬.

A better, long-term solution would be to disable password protection for frontend assets only in the shape of a FilesMatch ".(css|jpg|js|...)" directive.