jenkins-bot has submitted this change and it was merged.

Change subject: API: Allow anonymous CORS from anywhere, when specifically 
requested
......................................................................


API: Allow anonymous CORS from anywhere, when specifically requested

This allows any external site to do with CORS what they can already do
with jsonp: submit a request that will be processed as if logged out.

This is done by accepting '*' as a value for the existing 'origin' URL
parameter that is currently required in order to do any CORS requests
against MediaWiki.

The response to such a request will specifically include
"Access-Control-Allow-Credentials: false" to instruct the browser not to
send cookies or other authentication data, and further the API will
apply all the same restrictions (forcing an anonymous user and
forbidding certain actions such as token fetch) that it currently does
for jsonp requests.

Bug: T62835
Change-Id: I30e359fb23f0511242dfb4bff68718668947aaf5
---
M includes/api/ApiMain.php
1 file changed, 56 insertions(+), 27 deletions(-)

Approvals:
  Brian Wolff: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/includes/api/ApiMain.php b/includes/api/ApiMain.php
index ce9587f..d9bbbcb 100644
--- a/includes/api/ApiMain.php
+++ b/includes/api/ApiMain.php
@@ -265,6 +265,12 @@
                        return true;
                }
 
+               // Anonymous CORS
+               if ( $request->getVal( 'origin' ) === '*' ) {
+                       $this->lacksSameOriginSecurity = true;
+                       return true;
+               }
+
                // Header to be used from XMLHTTPRequest when the request might
                // otherwise be used for XSS.
                if ( $request->getHeader( 'Treat-as-Untrusted' ) !== false ) {
@@ -611,31 +617,49 @@
                $request = $this->getRequest();
                $response = $request->response();
 
-               // Origin: header is a space-separated list of origins, check 
all of them
-               $originHeader = $request->getHeader( 'Origin' );
-               if ( $originHeader === false ) {
-                       $origins = [];
+               $matchOrigin = false;
+               $allowTiming = false;
+               $varyOrigin = true;
+
+               if ( $originParam === '*' ) {
+                       // Request for anonymous CORS
+                       $matchOrigin = true;
+                       $allowOrigin = '*';
+                       $allowCredentials = 'false';
+                       $varyOrigin = false; // No need to vary
                } else {
-                       $originHeader = trim( $originHeader );
-                       $origins = preg_split( '/\s+/', $originHeader );
+                       // Non-anonymous CORS, check we allow the domain
+
+                       // Origin: header is a space-separated list of origins, 
check all of them
+                       $originHeader = $request->getHeader( 'Origin' );
+                       if ( $originHeader === false ) {
+                               $origins = [];
+                       } else {
+                               $originHeader = trim( $originHeader );
+                               $origins = preg_split( '/\s+/', $originHeader );
+                       }
+
+                       if ( !in_array( $originParam, $origins ) ) {
+                               // origin parameter set but incorrect
+                               // Send a 403 response
+                               $response->statusHeader( 403 );
+                               $response->header( 'Cache-Control: no-cache' );
+                               echo "'origin' parameter does not match Origin 
header\n";
+
+                               return false;
+                       }
+
+                       $config = $this->getConfig();
+                       $matchOrigin = count( $origins ) === 1 && 
self::matchOrigin(
+                               $originParam,
+                               $config->get( 'CrossSiteAJAXdomains' ),
+                               $config->get( 'CrossSiteAJAXdomainExceptions' )
+                       );
+
+                       $allowOrigin = $originHeader;
+                       $allowCredentials = 'true';
+                       $allowTiming = $originHeader;
                }
-
-               if ( !in_array( $originParam, $origins ) ) {
-                       // origin parameter set but incorrect
-                       // Send a 403 response
-                       $response->statusHeader( 403 );
-                       $response->header( 'Cache-Control: no-cache' );
-                       echo "'origin' parameter does not match Origin 
header\n";
-
-                       return false;
-               }
-
-               $config = $this->getConfig();
-               $matchOrigin = count( $origins ) === 1 && self::matchOrigin(
-                       $originParam,
-                       $config->get( 'CrossSiteAJAXdomains' ),
-                       $config->get( 'CrossSiteAJAXdomainExceptions' )
-               );
 
                if ( $matchOrigin ) {
                        $requestedMethod = $request->getHeader( 
'Access-Control-Request-Method' );
@@ -659,10 +683,12 @@
                                $response->header( 
'Access-Control-Allow-Methods: POST, GET' );
                        }
 
-                       $response->header( "Access-Control-Allow-Origin: 
$originHeader" );
-                       $response->header( 'Access-Control-Allow-Credentials: 
true' );
+                       $response->header( "Access-Control-Allow-Origin: 
$allowOrigin" );
+                       $response->header( "Access-Control-Allow-Credentials: 
$allowCredentials" );
                        // 
http://www.w3.org/TR/resource-timing/#timing-allow-origin
-                       $response->header( "Timing-Allow-Origin: $originHeader" 
);
+                       if ( $allowTiming !== false ) {
+                               $response->header( "Timing-Allow-Origin: 
$allowTiming" );
+                       }
 
                        if ( !$preflight ) {
                                $response->header(
@@ -671,7 +697,10 @@
                        }
                }
 
-               $this->getOutput()->addVaryHeader( 'Origin' );
+               if ( $varyOrigin ) {
+                       $this->getOutput()->addVaryHeader( 'Origin' );
+               }
+
                return true;
        }
 

-- 
To view, visit https://gerrit.wikimedia.org/r/282391
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I30e359fb23f0511242dfb4bff68718668947aaf5
Gerrit-PatchSet: 2
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Anomie <[email protected]>
Gerrit-Reviewer: Addshore <[email protected]>
Gerrit-Reviewer: Anomie <[email protected]>
Gerrit-Reviewer: Brian Wolff <[email protected]>
Gerrit-Reviewer: Brion VIBBER <[email protected]>
Gerrit-Reviewer: CSteipp <[email protected]>
Gerrit-Reviewer: Daniel Kinzler <[email protected]>
Gerrit-Reviewer: Dpatrick <[email protected]>
Gerrit-Reviewer: Jonas Kress (WMDE) <[email protected]>
Gerrit-Reviewer: Legoktm <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to