I am working on a self-hosted wiki on the root of a subdomain. I use Apache (and I don't use any kind of load balancer or cloud service), and my website uses HTTPS entirely (using a Let's Encrypt certificate, its https-only function, and preloaded HSTS), and my LocalSettings.php specifies HTTPS whenever possible (including in $wgServer). However, when a user visits the login page, they can still see a "Use secure connection" link. Clicking it only appends "&error=" to the URL. I'm not sure why this is displaying.
Description
Event Timeline
The code seems to be in [/includes/specialpage/LoginSignupSpecialPage.php](https://phabricator.wikimedia.org/source/mediawiki/browse/master/includes/specialpage/LoginSignupSpecialPage.php) around the line
], $this->msg( 'userlogin-signwithsecure' )->text() );
if someone feels like investigating the logic.
What version of MediaWiki?
What is $wgSecureLogin set to on your wiki?
Are either of $wgServer or $wgCanonicalServer set to something that is http not https (or protocol relative)?
I'm using version 1.32.2.
$wgSecureLogin is set to true (though as far as I'm aware it only effects protocol-relative URLs, and I've tried setting it to false).
Both $wgServer and $wgCanonicalServer are set to HTTPS.
I have tried changing $wgServer to use a protocol-relative URL while $wgSecureLogin was true, but this did not fix the issue. When I did this, however, I did notice that &error=&fromhttp=1 was in the URL of the login page as soon as I visited it from the Main Page.
I also have this problem. PHP is executed from an nginx behind a load balancer. HTTPS is terminated on the frontend, and the connection between the frontend, load balancer and MediaWiki is plain HTTP. Because of how the logic is done in MediaWiki, there's no way to get rid of the "use secure connection" link despite all pages being served as HTTPS.
The logic is, basically:
if ( $requestProtocol !== 'https' ) { // external connection is HTTPS but MediaWiki can't see this! Hence, this is true if ( $wgSecureLogin && !$weWereRedirectedFromHTTP ) ) { // Avoid infinite redirect redirectToHTTPsUrlTellingThisIsAForcedRedirect(); return; } else { // A wiki without HTTPS login support should set $wgServer to // http://somehost, in which case the secure URL generated // above won't actually start with https:// // ^^^ WRONG STATEMENT!! if ( substr( $url, 0, 8 ) === 'https://' ) { addSecureLoginLink(); } } }
Which is similar how to the WMF have it setup, but they don't have the link appear...
Ok, after being bugged by this, and digging on the code, found that $requestProtocol is basically getting the info from WebRequest::detectProtocol(), which does this:
if ( ( !empty( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] !== 'off' ) || ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https' ) ) { return 'https'; } else { return 'http'; }
Basically, it looks for a HTTPS server variable to not be off or empty, or have a HTTP_X_FORWARDED_PROTO variable (which means an X-Forwarded-Proto request header) with the https value.
The first one can't be "on" in my case, as explained before, but I can set X-Forwarded-Proto on the load balancer... And this finally solved the problem on the frontend nginx:
proxy_set_header X-Forwarded-Proto $scheme;