Archive
This post is archived and may contain outdated information. It has been set to 'noindex' and should stop showing up in search results.
This post is archived and may contain outdated information. It has been set to 'noindex' and should stop showing up in search results.
Magento HTTPS Redirect Loop with Cloudflare Flexible SSL
Jan 9, 2015Web DevelopmentComments (8)
If your Magento store uses CloudFlare's free Flexible SSL to encrypt the visitor-to-CloudFlare connection, you may run into a redirect loop problem on any Magento page that forces https, such as log in, account, and checkout. You may also run into an issue where Magento serves http assets on https pages, causing the browser to block them.
Server Variable
These problems are likely caused by the server variables not reflecting https. The specific server variable that Magento looks for is called HTTPS (upper-case) and it must be set to on (lower-case) when on an https page, or else Magento may enter a redirect loop. The reason it is not being set is because of how CloudFlare's Flexible SSL works.
How Flexible SSL Works
With CloudFlare Flexible SSL, the connection is encrypted from the visitor to CloudFlare (https), and unencrypted from CloudFlare to your server (http).
What happens is that the server thinks the connection is over http, and sets the server variables accordingly. It is doing the right thing, since the connection from CloudFlare to the server is indeed over http, despite the visitor-to-CloudFlare connection being over https.
When the Magento store gets the request to an https-only page, it sees port 80 with protocol http, and not port 443 with protocol https, so it redirects the user to https. Since the visitor is already on https, the redirect loop continues endlessly.
How to Fix It
CloudFlare injects some server variables that can be used to determine if the visitor-to-CloudFlare connection was made over https. You need to edit Magento so that it looks for these variables, and if they exist and are set to their https values, set HTTPS to on.
One way to do this is to create a small PHP patch file and include it into your Magento store. Here is PHP code that will do the trick:
What this does is check each of three possible server variables to see if they exist and are set to their respective https values. It does this without polluting the namespace of Magento, which is why the array declaration is inside the foreach loop.
Server Variable
These problems are likely caused by the server variables not reflecting https. The specific server variable that Magento looks for is called HTTPS (upper-case) and it must be set to on (lower-case) when on an https page, or else Magento may enter a redirect loop. The reason it is not being set is because of how CloudFlare's Flexible SSL works.
How Flexible SSL Works
With CloudFlare Flexible SSL, the connection is encrypted from the visitor to CloudFlare (https), and unencrypted from CloudFlare to your server (http).
What happens is that the server thinks the connection is over http, and sets the server variables accordingly. It is doing the right thing, since the connection from CloudFlare to the server is indeed over http, despite the visitor-to-CloudFlare connection being over https.
When the Magento store gets the request to an https-only page, it sees port 80 with protocol http, and not port 443 with protocol https, so it redirects the user to https. Since the visitor is already on https, the redirect loop continues endlessly.
How to Fix It
CloudFlare injects some server variables that can be used to determine if the visitor-to-CloudFlare connection was made over https. You need to edit Magento so that it looks for these variables, and if they exist and are set to their https values, set HTTPS to on.
One way to do this is to create a small PHP patch file and include it into your Magento store. Here is PHP code that will do the trick:
foreach (array(
'SERVER_PORT' => 443,
'HTTP_X_FORWARDED_PROTO' => 'https',
'HTTP_CF_VISITOR' => '{"scheme":"https"}'
) as $key => $value) {
if (isset($_SERVER[$key]) && $_SERVER[$key] == $value) {
$_SERVER['HTTPS'] = 'on';
break;
}
}
What this does is check each of three possible server variables to see if they exist and are set to their respective https values. It does this without polluting the namespace of Magento, which is why the array declaration is inside the foreach loop.