Cloudflare and Wordpress Redirect Loop

I’m going to get straight into the nitty gritty of this. I recently set up Cloudflare to sit in front of this Wordpress blog and ran into an issue where the site ended up in a redirect loop. I’ll assume that you have Cloudflare set up (https://support.cloudflare.com/hc/en-us/categories/200275218 if not) and you’ve installed Wordpress (https://codex.wordpress.org/Installing_WordPress). Now you’re sitting there getting this:

Firefox Redirect Message

This can be especially frustrating because you think you’ve got all the bases covered:

  • you’ve forced SSL on admin by adding define(‘FORCE_SSL_ADMIN’, true); to wp-config.php
  • you’ve changed all your images and links to https from http
  • you’ve changed your site URL to https
  • you’ve added a redirect to your server via the config file or .htaccess

So what’s missing? I got the error when trying to access wp-login.php so I started my debugging there. Right at the start of the file is this block of text:

// Redirect to https login if forced to use SSL
if ( force_ssl_admin() && ! is_ssl() ) {
if ( 0 === strpos($_SERVER['REQUEST_URI'], 'http') ) {
wp_redirect( set_url_scheme( $_SERVER['REQUEST_URI'], 'https' ) );
exit();
} else {
wp_redirect( 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
exit();
}
}

The redirects that seem to be causing me a problem are here, continually redirecting when it finds that force_ssl_admin() is true and is_ssl() is false. Adding var_dump(force_ssl_admin()); var_dump(is_ssl()); die(); and refreshing gave me this:

bool true
bool false

False? What is this function doing? Looking up the function on the Wordpress codex (https://codex.wordpress.org/Function_Reference/is_ssl) gave the solution. Because Cloudflare is acting as an interim between your site and the visitor, your site doesn’t necessarily get all the headers you would expect when you have your own SSL solution in place. Dumping the value of $_SERVER[‘SERVER_PORT’] returns 80 and not 443 as expected, and so that is why is_ssl(); is returning false and getting you into a redirect loop. However other headers do give you a better indication of whether the connection is secure:

$_SERVER[‘HTTP_X_FORWARDED_PROTO’] returns ‘https’, and you can use this to set the value of $_SERVER[‘https’] to ‘on’ in your wp-config.php file.

if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')
$_SERVER['HTTPS'] = 'on';

That last line of code is courtesy of the Wordpress Codex — https://codex.wordpress.org/Function_Reference/is_ssl

Image by Ilya Pavlov via Unsplash

Originally published at mattasbury.co.uk

Like what you read? Give Matt Asbury a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.