webapppassword icon indicating copy to clipboard operation
webapppassword copied to clipboard

cors error on file sharing apis (OCS)

Open SINAKZM opened this issue 2 years ago • 17 comments

Explain the Problem

i have problem with using share api . doument tells we should use /apps/webapppassword/api/v1/shares instead /ocs/v2.php/apps/files_sharing/api/v1/shares as far as i found out. when i use /apps/webapppassword/api/v1/shares OPTIONS request is ok but i got cors error on request itself (POST) and when i use /ocs/v2.php/apps/files_sharing/api/v1/shares i get method not allowed error on OPTIONS request. currently im using webapppassword and i have no problem with webdav apis im using these apis in same project . how to call share apis without cors error

Steps to Reproduce

this is my axios call

      const response = await axios.post(
          'http://nc.develop/apps/webapppassword/api/v1/shares',
          {
            path: 'welcome.txt',
            shareType: 0, // 3 represents "user" share type, change it based on your requirements
            shareWith: 'sina',
            permissions: 19,
            password: "admin",
            attributes:""
          },
          {
            headers:{
              "Authorization": "Bearer "+localStorage.getItem("access_token"),
              "authorization": "Bearer "+localStorage.getItem("access_token"),
            }
          }
      );

      console.log('Share created:', response.data);
    } catch (error) {
      console.error('Error creating share:', error.message);
    }

System Information

  • WebAppPassword app version: 23.6.0
  • Nextcloud version: 26.0.3
  • PHP version: 8.1.2

Contents of nextcloud/data/nextcloud.log

nothing adds in log

Contents of Browser Error Console

Access to XMLHttpRequest at 'http://nextcloud_proxy_backend.develop/apps/webapppassword/api/v1/shares' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

SINAKZM avatar Jul 14 '23 12:07 SINAKZM

@aleixq (#61)

pbek avatar Jul 14 '23 13:07 pbek

@aleixq (#61)

is that bug right?

SINAKZM avatar Jul 15 '23 09:07 SINAKZM

I'll take a look asap. I've got it working using the webdav picker. Let me check and compare requests and responses.

aleixq avatar Jul 17 '23 08:07 aleixq

I couldn't reproduce...

Just inspecting a little and as I said I have it working using webdav-filepicker (patching a file to change the share endpoint url to the webapppassord one).
When creating a share it will send a preflight automatically to check the access-control options:

fetch("https://nextcloud/index.php/apps/webapppassword/api/v1/shares", {
  "headers": {
    "accept": "*/*",
    "accept-language": "ca-ES,ca;q=0.9",
    "sec-fetch-dest": "empty",
    "sec-fetch-mode": "cors",
    "sec-fetch-site": "same-site"
  },
  "referrer": "https://cms-site.org/",
  "referrerPolicy": "strict-origin-when-cross-origin",
  "body": null,
  "method": "OPTIONS",
  "mode": "cors",
  "credentials": "omit"
});

This call must return

Access-Control-Allow-Credentials: false
Access-Control-Allow-Headers: Authorization, Content-Type, Accept, OCS-APIRequest
Access-Control-Allow-Methods: PUT, POST, GET, DELETE, PATCH
Access-Control-Allow-Origin: https://cms-site.org
Access-Control-Max-Age: 1728000
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 0
Content-Security-Policy: default-src 'none';base-uri 'none';manifest-src 'self';frame-ancestors 'none'
Content-Type: text/html; charset=UTF-8
Feature-Policy: autoplay 'none';camera 'none';fullscreen 'none';geolocation 'none';microphone 'none';payment 'none'
Pragma: no-cache
Referrer-policy: no-referrer
X-Content-Type-Options: nosniff
X-Debug-Message: debug-msg 3
X-Download-Options: noopen
X-Frame-Options: SAMEORIGIN
X-Permitted-Cross-Domain-Policies: none
X-Robots-Tag: noindex, nofollow
X-Robots-Tag: none
X-Xss-Protection: 1; mode=block

(Where the relevant ones are the Access-control ones)

After that a regular post request to https://nextcloud/index.php/apps/webapppassword/api/v1/shares is sent.

If you paste the options request headers and repsonse maybe I could help a little more... Also maybe check https://github.com/axios/axios/issues/4712 similar issue? Or maybe the server is blocking OPTIONS request?

aleixq avatar Jul 18 '23 18:07 aleixq

@aleixq yes i copied your fetch request in my code its status code is 200 for options request and header of response is exactly you said at the moment for my api call like create share i get cors error on post request not option as i check network/xhr section of browser and i have no problem with axios for not send option request about an issue that you share because response of option request is 200. for reproduce this is my code that get cors error on post request:

      const response = await axios.post(
          'http://nextcloud_proxy_backend.develop/apps/webapppassword/api/v1/shares',
          {
            path: 'welcome.txt',
            shareType: 0,
            shareWith: 'sina',
            permissions: 19,
            password: "admin",
            attributes:""
          },
          {
            headers:{
              // "OCS-APIREQUEST": true,
              "Authorization": "Bearer "+localStorage.getItem("access_token"),
              "authorization": "Bearer "+localStorage.getItem("access_token"),
            }
          }
      );

      console.log('Share created:', response.data);
    } catch (error) {
      console.error('Error creating share:', error.message);
    }

mention that this is error in console:

`Access to XMLHttpRequest at 'http://nextcloud_proxy_backend.develop/apps/webapppassword/api/v1/shares' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.`

SINAKZM avatar Jul 19 '23 23:07 SINAKZM

Could you please paste using "add collapsible content" button in this editor the request and response headers of OPTIONS and POST ? you could use next as template: ---- START of TEMPLATE ----

OPTIONS headers request
paste content 
here
OPTIONS headers response
paste content 
here
POST headers request
paste content
 here
POST headers response
paste content 
here

---- END of TEMPLATE ----

These headers will help a lot determining if the origins check is made as it should (logics are in https://github.com/digital-blueprint/webapppassword/pull/61/files#diff-e9996f62a46f389c1d8031d1020d33d4a97c47db07606c0ad730eb7d0b88e7de if you want to help debugging it)

About the issue itself, Is 'http://localhost:8080' among the allowed origins?

aleixq avatar Jul 20 '23 09:07 aleixq

OPTIONS headers request
OPTIONS /apps/webapppassword/api/v1/shares HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Access-Control-Request-Headers: authorization,content-type
Access-Control-Request-Method: POST
Cache-Control: no-cache
Connection: keep-alive
Host: nextcloud_proxy_backend.develop
Origin: http://localhost:8080
Pragma: no-cache
Referer: http://localhost:8080/
Sec-Fetch-Mode: cors
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36
OPTIONS headers response
HTTP/1.1 200 OK
Server: nginx/1.18.0 (Ubuntu)
Date: Thu, 20 Jul 2023 09:57:45 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 0
Connection: keep-alive
Set-Cookie: oc_sessionPassphrase=xlCi5N5zOuR6s0V%2FonFRz8yr9jS3BnINfHLYhBB5ti9jcH7iC4fomsS%2BstH3lyIaZkJyOP4Zl2BauokFUCKKrVkpj1MktyC%2FwEoy%2ButxTMOkN7gVTmmK%2BVuMvE6VaJkc; path=/; HttpOnly; SameSite=Lax
Set-Cookie: nc_sameSiteCookielax=true; path=/; httponly;expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=lax
Set-Cookie: nc_sameSiteCookiestrict=true; path=/; httponly;expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=strict
Set-Cookie: ocn93pv6mvl1=jlv8jbcbjmckukfihakl57grk8; path=/; HttpOnly; SameSite=Lax
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Pragma: no-cache
Cache-Control: no-cache, no-store, must-revalidate
X-Request-Id: uyhhV8hxuQ5QD2QAP5gx
Access-Control-Allow-Origin: http://localhost:8080
Access-Control-Allow-Methods: PUT, POST, GET, DELETE, PATCH
Access-Control-Max-Age: 1728000
Access-Control-Allow-Headers: Authorization, Content-Type, Accept, OCS-APIRequest
Access-Control-Allow-Credentials: false
Content-Security-Policy: default-src 'none';base-uri 'none';manifest-src 'self';frame-ancestors 'none'
Feature-Policy: autoplay 'none';camera 'none';fullscreen 'none';geolocation 'none';microphone 'none';payment 'none'
X-Robots-Tag: noindex, nofollow
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
X-Robots-Tag: none
X-Download-Options: noopen
X-Permitted-Cross-Domain-Policies: none
POST headers request
POST /apps/webapppassword/api/v1/shares HTTP/1.1
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Authorization: Bearer 4wzjwHlqtsMPQbhwpEYvJ1UXICetLpwhN1TKCEHmqWKq7VNT6jNJMmwOz6caIZNeQpKJ8PBR
Cache-Control: no-cache
Connection: keep-alive
Content-Length: 107
Content-Type: application/json
Host: nextcloud_proxy_backend.develop
Origin: http://localhost:8080
Pragma: no-cache
Referer: http://localhost:8080/
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36
POST headers response
HTTP/1.1 200 OK
Server: nginx/1.18.0 (Ubuntu)
Date: Thu, 20 Jul 2023 09:57:45 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 138
Connection: keep-alive
Set-Cookie: oc_sessionPassphrase=o9XowNurZX4ExunllF0B9M%2FDkyjhn2T%2F2eD3tG7sQUnUoF%2BHZbLnTnRwN83nRfcmLfEjCira%2FjDpryMnuSNcRhaLMEUTSDrRlFq21Lm12yBVHdLGPa2fBsEuMWGiPeBH; path=/; HttpOnly; SameSite=Lax
Set-Cookie: nc_sameSiteCookielax=true; path=/; httponly;expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=lax
Set-Cookie: nc_sameSiteCookiestrict=true; path=/; httponly;expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=strict
Set-Cookie: ocn93pv6mvl1=559tbndl46embtvknhia242g01; path=/; HttpOnly; SameSite=Lax
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Pragma: no-cache
Cache-Control: no-cache, no-store, must-revalidate
X-Request-Id: hXD9cNBQwxDtqtFYynP4
Content-Security-Policy: default-src 'none';base-uri 'none';manifest-src 'self';frame-ancestors 'none'
Feature-Policy: autoplay 'none';camera 'none';fullscreen 'none';geolocation 'none';microphone 'none';payment 'none'
X-Robots-Tag: noindex, nofollow
Content-Encoding: gzip
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
X-Robots-Tag: none
X-Download-Options: noopen
X-Permitted-Cross-Domain-Policies: none

i added to allow origins 'http://localhost:8080' like webdav section @aleixq

SINAKZM avatar Jul 20 '23 10:07 SINAKZM

Why did you comment the OCS-APIRequest header in your axios post? Could you please check setting this to true.

Let's test but i think this is the cause. Despite it is not a regular OCS endpoint request it needs these set to true as this method is inherited from an ocs endpoint. And as documentation says in https://docs.nextcloud.com/server/latest/developer_manual/client_apis/OCS/ocs-share-api.html :

All calls to OCS endpoints require the OCS-APIRequest header to be set to true.

aleixq avatar Jul 20 '23 15:07 aleixq

@aleixq i tested it previously so i comment that now i checked that with header again but still cors error and nothing changes .

post request headers POST /apps/webapppassword/api/v1/shares HTTP/1.1
Accept: application/json, text/plain, */*

Accept-Encoding: gzip, deflate

Accept-Language: en-US,en;q=0.9

Authorization: Bearer o6Q3QzP4pnVxg4AajbwMEiNM6x6CvT7TmI9nuJCudR1a3toJO95AFVTFNA7G8GPeH9LEKc7Q

Cache-Control: no-cache

Connection: keep-alive

Content-Length: 107

Content-Type: application/json

Host: nextcloud_proxy_backend.develop

OCS-APIRequest: true

Origin: http://localhost:8080

Pragma: no-cache

Referer: http://localhost:8080/

User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36
post response headers HTTP/1.1 200 OK
Server: nginx/1.18.0 (Ubuntu)

Date: Thu, 20 Jul 2023 23:48:16 GMT

Content-Type: application/json; charset=utf-8

Content-Length: 138

Connection: keep-alive

Set-Cookie: oc_sessionPassphrase=opmQ2VV5KTnXj47I01jCNTj48wL6xXDcFvHkx6yqpJMs5%2Bqjz6cvae9oXF%2B1%2FMfB%2BTFB21BIcdsdwsYKDh%2BoCCACd38reRTZOHiYIoGRxoy5cNd0HmrnO04YY0uLAbff; path=/; HttpOnly; SameSite=Lax
Set-Cookie: nc_sameSiteCookielax=true; path=/; httponly;expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=lax

Set-Cookie: nc_sameSiteCookiestrict=true; path=/; httponly;expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=strict

Set-Cookie: ocn93pv6mvl1=tnqsg3vs2pn21o5g6qbmb5l4db; path=/; HttpOnly; SameSite=Lax

Expires: Thu, 19 Nov 1981 08:52:00 GMT

Pragma: no-cache

Cache-Control: no-cache, no-store, must-revalidate

X-Request-Id: QlqpT8U9jL1FgI8gR7eX

Content-Security-Policy: default-src 'none';base-uri 'none';manifest-src 'self';frame-ancestors 'none'

Feature-Policy: autoplay 'none';camera 'none';fullscreen 'none';geolocation 'none';microphone 'none';payment 'none'

X-Robots-Tag: noindex, nofollow

Content-Encoding: gzip

X-Content-Type-Options: nosniff

X-XSS-Protection: 1; mode=block

X-Robots-Tag: none

X-Download-Options: noopen

X-Permitted-Cross-Domain-Policies: none

SINAKZM avatar Jul 20 '23 23:07 SINAKZM

Well. Let's check another thing. Did you test with basic auth rather than bearer ?

aleixq avatar Jul 21 '23 09:07 aleixq

@aleixq i tested it and not worked too when everything is ok its error is cors error. i think this can be helpful when i enable cors extension on chrome it works correctly but the problem is when i enable cors extension, web dav apis get cors error and and no longer works.

SINAKZM avatar Jul 21 '23 09:07 SINAKZM

I don't know if i am understanding... Could you use punctuation? So the problem appears when using a chrome extension?

aleixq avatar Jul 21 '23 10:07 aleixq

@aleixq no no . im working with webdav apis and share apis without enabling cors extension . with disable cors extension webdav apis works correctly and share apis get cors error but if you enable cors extension, share apis will works but webdav apis get cors error. i know cors extension should be disabled, for getting any clue and for test i just enabled it

SINAKZM avatar Jul 21 '23 10:07 SINAKZM

@aleixq if we comment the section of header set in webapppassword/lib/Controller/AccessControl.php still option request of share api is 204 and it seems not has any effect but if we comment setCorsHeaders in webapppassword/lib/Connector/Sabre/CorsPlugin.php webdav apis get cors error so CorsPlugin.php works correctly and has effect i think set header for share apis has problem and not trigger at all

SINAKZM avatar Jul 21 '23 15:07 SINAKZM

@aleixq if we comment the section of header set in webapppassword/lib/Controller/AccessControl.php still option request of share api is 204 and it seems not has any effect but if we comment setCorsHeaders in webapppassword/lib/Connector/Sabre/CorsPlugin.php webdav apis get cors error so CorsPlugin.php works correctly and has effect i think set header for share apis has problem and not trigger at all

Let me create a simple manual test case to evaluate if there's something wrong(asap). What is true is that I have it working fine with nextcloud-webdav-filepicker both webdav and share api. While test is not made you can check it out with this filepicker (you must change the endpoint url to point to webapppassword filesharing endpoint url)

aleixq avatar Jul 22 '23 10:07 aleixq

@aleixq im using webapppassword filesharing endpoint as code already posted here and im looking at nextcloud-webdav-filepicker codes and to be honest i didnt find any useful tip . now i added these headers temporary in first line of ShareApiController and now works but as you know this way is not ok

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization');
header('Access-Control-Max-Age: 86400');

SINAKZM avatar Jul 26 '23 23:07 SINAKZM

Hi again, I have created some manual tests in https://gitlab.com/communia/nc-webapppassword-share-test . They are ran as it should... Could you test to see if fails in your case ? note that I am using fetch api so not axios directly. The readme.md explains everything. More users and environments tests are welcome to find errors...

I see another issue but not in our domain: a thing that must be reviewed is that share api call to native files_sharing endpoint is not allowed but is executed and share is created... despite cors origin failing... So share is created but no response text can be used in script because of cors.

aleixq avatar Jul 29 '23 10:07 aleixq