Page MenuHomePhabricator

Add protocol parameter to mw.Api.
Closed, DeclinedPublic

Description

Add an option to use HTTPS as the protocol in an API request through JavaScript.


Version: unspecified
Severity: enhancement

Details

Reference
bz40968

Event Timeline

bzimport raised the priority of this task from to Medium.Nov 22 2014, 12:44 AM
bzimport set Reference to bz40968.
bzimport added a subscriber: Unknown Object (MLST).

Why?

It uses whatever the server configuration tells it to use. If the wiki is not configured to indicate HTTPS support, it will not force an HTTPS request.

There should be no reason to make an exception for mw.Api, there are 100s of other usages of server configuration.

e.g.

$wgServer = ' //example.org';

Then article links, load.php, api.php etc. etc. will all use HTTP on HTTP and HTTPS when the visitor is from HTTPS.

If $wgServer = 'http://example.org';

Then everything will be http. If your server also supports HTTPS, and you want mw.Api to also use HTTPS, then please fix the server configuration as mw.Api is not the only thing going insecure, there are at least 99 other things going over http that shouldn't.

Say you're using an extension like Extension:Persona. It does login through an AJAX API request. However, if you have $wgSecureLogin enabled, it cannot (or rather should not) use HTTP for transmission of the login request. Right now AFAIK there is no way to tell mw.Api to use HTTPS instead.

(In reply to comment #2)

Say you're using an extension like Extension:Persona. It does login through an
AJAX API request. However, if you have $wgSecureLogin enabled, it cannot (or
rather should not) use HTTP for transmission of the login request. Right now
AFAIK there is no way to tell mw.Api to use HTTPS instead.

Even though the script in question handling the login on the wiki could be malicious since it was delivered with http?

Yes, but that is irrelevant. If the script is compromised in a MITM attack, the security of the login process does not matter because the attacker will have already taken the user's authentication token (the equivalent of a one-time password).

However, consider the case where the script is not compromised. In this case, the authentication data is then sent over plaintext to the API, which opens up another attack vector. While the best thing to do would be to force HTTPS everywhere, that is not always possible or wanted behavior, so at the very least I can have my extension respect $wgSecureLogin by putting authentication data over a secure connection.

It's like the question of whether $wgSecureLogin is worthwhile even though the cookies for the session will be sent over HTTP, allowing session hijacking.

Lets translate it to non-ajax:

When enabling $wgSecureLogin the login link outputted by the server points to https, so the login procedure goes entirely over https. The login form and login page are not transferred over http and then submitted to https. No, instead the links pointing to the login page are influenced by wgSecureLogin.

The form itself is neutral, and will naturally submit over https as the page it is submitted from is also on https.

In general it seems like a fragile approach to try and submit things over https when in an http environment. Any other module that doesn't allow hardcoding of the protocol will still submit over http.

Instead (like the non-ajax implementation) one should ensure that this script will execute in an https environment to begin with. There are lots of ways to accomplish that.

Anyway, if you must, it is totally possible as-is. Also, I believe the below method is superior to implementing an "https" option, as that would imply that it always goes over https, whereas the below is explicit in what it does, expects and intends:

  • Export your toggle (e.g. wgSecureLogin) to js
  • Get mw.util.wikiScript( 'api' )
  • If toggle is true, and api-path is https:// or //, proceed (convert // to https:// if needed). If not, abort and continue with error state (this means the wiki is misconfigured and will be consistently reproducible)
  • Instantiate your api interface:

    var api = new mw.Api({ ajax: { url: myApiPath } });

Rest follows as expected.

The only problem is that I do not want to fail when not over HTTPS. There needs to be some way for the user to be forwarded to HTTPS when they try to log in. However, simply redirecting to HTTPS would not work since the JS hook for login would need to be re-triggered.

Firstly, it is strongly discouraged to run login-related code when on an HTTP page. Submitting the data to HTTPS is insufficient and has no meaningful security whatsoever given that any MITM attack could've modified the form or the script to submit the data elsewhere.

However, if you do want to expand or set the protocol of a url, you can do so in the code making the API call using mw.Uri.

Here's a brief example that would work on any wiki (e.g. doesn't assume wgSecureLogin, or whether server supports HTTP, HTTPS or both). If you need to support a subset of this, the code could be even simpler.

// If wgServer is protocol-relative, expand urls to HTTPS.
// If not, use whichever of HTTP or HTTP is configured.
var MaybeSecureUri = mw.UriRelative( mw.config.get( 'wgServer' ).replace( '^//', 'https://' ) );
var url= new MaybeSecureUri( '/w/api.php' );

var api = new mw.Api({ ajax: { url: url } });

api.post( .. );