?
avatar pjdevries
pjdevries
6 Nov 2020

Steps to reproduce the issue

Assuming site A is a Joomla! 4 site and site B is another site, in a domain other than site A, wanting to consume webservices of site A:

  • On site A create an API token for a Joomla! user that has adequate permissions to access the webservices.
  • On site B copy the below <script> into file administrator/components/com_content/views/articles/tmpl/default.php after line 55 if it's J3 or in file administrator/components/com_content/tmpl/articles/default.php after line 93 if it's J4.
  • Replace DOMAIN OF SITE A in the script with the domain of site A.
  • Replace YOUR TOKEN in the script with the API token created in the first step.
  • Open the browser developer console, navigate to the content articles page and notice the errors.
<script type="application/javascript">
    var myHeaders = new Headers();
    myHeaders.append("X-Joomla-Token", "YOUR TOKEN");

    var requestOptions = {
        method: 'GET',
        headers: myHeaders,
        redirect: 'follow'
    };

    fetch("http:/DOMAIN OF SITE A/api/index.php/v1/content/article", requestOptions)
        .then(response => response.text())
        .then(result => console.log(result))
        .catch(error => console.log('error', error));
</script>

Expected result

A valid 200 response for both the preflight OPTIONS request and the subsequent GET request

Actual result

A 404 for the preflight OPTIONSrequest and a Cross-Origin request blocked error for the GETrequest.

Additional comments

I ran into this issue when trying to access J4 webservices from a simple JavaScript proof of concept app. After some digging, this is what I found:

  • J4 does not handle the preflight request.
  • The browser apparently does not bother to send the GET request if it did not receive a valid response from the preflight request.

I think this is what needs to be done to handle CORS and make webservices (more) usable:

  • Preflight (OPTIONS) requests must be handled properly. This involves sending a 204 No Content response with (at least) Access-Control-Allow-Origin, Access-Control-Allow-Methods and `Access-Control-Allow-Headers.
  • At least a Access-Control-Allow-Origin header must be added to the subsequent "regular" (GET, POST, ...) request.
avatar pjdevries pjdevries - open - 6 Nov 2020
avatar joomla-cms-bot joomla-cms-bot - change - 6 Nov 2020
Labels Added: ?
avatar joomla-cms-bot joomla-cms-bot - labeled - 6 Nov 2020
avatar pjdevries pjdevries - change - 6 Nov 2020
Title
Webservices Cross-Origin Requests get blocked
[4.0] Webservices Cross-Origin Requests get blocked
avatar pjdevries pjdevries - edited - 6 Nov 2020
avatar C-Lodder
C-Lodder - comment - 8 Nov 2020

What do you expect the default for Access-Control-Allow-Origin to be? Cause it most definitely shouldn't be *

avatar pjdevries
pjdevries - comment - 8 Nov 2020

Cause it most definitely shouldn't be *

Can you elaborate on this boldbald-faced point of view?

avatar C-Lodder
C-Lodder - comment - 8 Nov 2020

Using a wildcard will allow requests from any origin. You should always define a specific origin whenever possible. You then also have to remember that using a wildcard may expose API's and general XSS attacks via other 3rd party extensions and/or scripts.

avatar pjdevries
pjdevries - comment - 8 Nov 2020

I guess CORS should be disabled by default. Which it is now, effectively :)

I think the web services API is one of the most useful new features in J4. No self respecting CMS can live without it these days. But without CORS support, it's not very useful. I can think of various implementations, with varying levels of flexibility and complexity. However, I also think a possible solution should not slow down the 4.0 release. So I would go for a simple approach to start with, as long as it is safe and fulfills the purpose.

A simple approach might be the addition of some settings in the "Global Configuration", to enable/disable CORS and set a global Origin. That would at least make it usable. Future enhancements could include the addition of similar, overruling configuration settings for users and user groups.

Just thinking out loud.

avatar bembelimen
bembelimen - comment - 8 Nov 2020

Just a comment: I think it's not intended, that you use the token in JS, where everyone can read it.

avatar C-Lodder
C-Lodder - comment - 9 Nov 2020

@bembelimen Passing a token in JS is perfectly fine, providing you don't use Access-Control-Allow-Origin: * and open your server to allow requests from any origin.

avatar pjdevries
pjdevries - comment - 9 Nov 2020

@bembelimen You are absolutely right. The snippet is just a simple example to prove a point :)

@C-Lodder Isn't that where next step user authentication methods are for? I tend to agree with @bembelimen that auth tokens should not be embedded hard coded in JS code.

avatar alikon
alikon - comment - 10 Nov 2020

I think the web services API is one of the most useful new features in J4....
....
A simple approach might be the addition of some settings in the "Global Configuration", to enable/disable CORS and set a global Origin. That would at least make it usable. Future enhancements could include the addition of similar, overruling configuration settings for users and user groups

I agree .... so...

a very simple starting approach #31379

avatar wilsonge wilsonge - change - 24 Nov 2020
Status New Closed
Closed_Date 0000-00-00 00:00:00 2020-11-24 03:12:04
Closed_By wilsonge
avatar wilsonge
wilsonge - comment - 24 Nov 2020

Closing this request in favour of #31379

avatar wilsonge wilsonge - close - 24 Nov 2020

Add a Comment

Login with GitHub to post a comment