forms icon indicating copy to clipboard operation
forms copied to clipboard

make forms OCS API CORS compatible

Open everlanes opened this issue 3 years ago • 3 comments

When accessing the public OCS API in an external web application the browser performs a CORS check.

These changes add the functionality, that the Forms API responds with the needed information to the OPTIONS request. It is adding the builtin ApiController.preflightedCors endpoint and extends the Allowed Header list.

everlanes avatar Mar 24 '22 12:03 everlanes

Hey @everlanes,

thank you for watching into this and giving some contribution back! 🙂 I'm totally with you, that this would be good if the API works with CORS. However - i just created a simple testpage on another subdomain of my testlinux. Unfortunately, on firefox the cors-request does still not work with only your PR. On the other hand, if i add the @CORS comment to the methods as said in the dev-docs, then the CORS-Request works, but the forms app within the cloud does not work anymore. When i integrated the OCS-Stuff somewhen, i got told that the CORS stuff is not properly implemented/working in nc-server. It seems to me, this is still the case...?! How did you test this? Can you give an example, that you could make running with your PR?

Greets! :) Jonas

jotoeri avatar Mar 30 '22 19:03 jotoeri

Servus Jonas,

thank you for looking into this. Indeed, I missed the "@CORS" entry in my pull request. I just checked in my installation and I must have added it somewhere in the development process. By then I was working on my "production" server and copied my changes manually back.

Now I have setup a clean Nextcloud development environment in a newly created LXC container. Just for references:

cat /etc/os-release 
PRETTY_NAME="Ubuntu 21.10"
NAME="Ubuntu"
VERSION_ID="21.10"
VERSION="21.10 (Impish Indri)"
VERSION_CODENAME=impish
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=impish

Nextcloud Server: commit 6456cbe53c667dce456b3f8b4df810a4c7cc0bf7 Nextcloud Forms: commit be2d624fbc93d13f9b731926b9a92ca966f212bc

Preparation of LXC Container:

apt install -y apache2 libapache2-mod-php \
    php-zip php-xml php-mbstring php-gd php-curl php-sqlite3 npm

cd FORMS_DIRECTORY
npm ci
npm run dev

So I am running this development installation with sqlite DB and recent master versions.

Then I added a simple Form with just one short text answer and shared it via link.

First test

Accessing the API with curl and emulating Chrome preflight check:

FORMS_LINK="http://10.0.3.37/ocs/v2.php/apps/forms/api/v1.1/submission/insert"

curl -X OPTIONS -i \
    -H "Origin: http://127.0.0.1:8000" \
    "${FORMS_LINK}" 2> /dev/null | grep "Access-Control-Allow"

echo

curl -X POST -i \
    -H "OCS-APIRequest: true" \
    -H "Content-Type: application/json" \
    -H "Origin: http://127.0.0.1:8000" \
    -d '{"formId":"1","answers":{"1":["asdf"]}}' \
    "${FORMS_LINK}" 2> /dev/null | grep "Access-Control-Allow"

The response should look like this:

./check_cors_header.sh 
Access-Control-Allow-Origin: http://127.0.0.1:8000
Access-Control-Allow-Methods: PUT, POST, GET, DELETE, PATCH
Access-Control-Allow-Headers: Authorization, Content-Type, Accept, OCS-APIRequest
Access-Control-Allow-Credentials: false

Access-Control-Allow-Origin: http://127.0.0.1:8000

The first curl call simulates the Chrome preflight check. The second call is the POST request sending the form data.

When the @CORS comment is missing / removed from the ApiController.insertSubmission function, the second request does not contain the Access-Control-Allow-Origin header. In this case the prflight check is successfull, but Chrome still complains and aborts the POST request. But as the request is already sent to Nextcloud, the answer is still stored.

Adding the @CORS comment makes Chrome happy, aka no error logs in the console anymore.

Second test

I also created a minimal example that send data to the form API with a XMLHttpRequest (remove .txt extension): index.html.txt

If you would like to use this example, you'll have to change the public forms link in <form action="...." > For a simple webserver run python3 -m http.server in the same directory.

After adding the missing @CORS comment I can use this example to send data to the forms API.

Tested Browsers

I tested this with the following browsers:

Vivaldi | 5.1.2567.73 (Stable channel) stable (64-Bit)
Überarbeitung | dcad6d380887823962edf4339497ddacc2d6f519
Betriebssystem | Linux
JavaScript | V8 9.8.177.13
User-Agent | Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.141 Safari/537.36
Chromium
Version 99.0.4844.84 (Offizieller Build) Built on Ubuntu , running on Ubuntu 18.04 (64-Bit)
Firefox Browser
98.0.2 (64-Bit)
Mozilla Firefox for Ubuntu
canonical-1.0

I ~~will~~ have updated my pull request and added the @cors entry.

Cheers,

Andreas

everlanes avatar Mar 31 '22 12:03 everlanes

Oh sorry for not coming back here before... The point is, that this works for you more - i would say - 'by luck'. 😉 It works only on the insert procedure, while on the other endpoints it does not - and who would have thought, my tests ran with 'getForms'. 🙃

I also created a PR now on server, which helps making it work (& thereby included yours, which is also necessary 😉 ). Let's see how fast we get this done... ;)

jotoeri avatar Apr 04 '22 19:04 jotoeri

So, this works now with NC25. Wanna test it once again, @everlanes? 😉

jotoeri avatar Dec 21 '22 14:12 jotoeri