Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CORS-header ‘Access-Control-Allow-Origin’ missing (Nextcloud) #116

Closed
memen45 opened this issue Nov 13, 2018 · 19 comments
Closed

CORS-header ‘Access-Control-Allow-Origin’ missing (Nextcloud) #116

memen45 opened this issue Nov 13, 2018 · 19 comments

Comments

@memen45
Copy link

memen45 commented Nov 13, 2018

Just tried to follow the guide in the readme.md to connect to a nextcloud server. The code is

var client = Webdav(
   "https://some.nextcloudserver.nl/remote.php/webdav",
   "username"
);
client
   .getDirectoryContents("/", { withCredentials: true })
   .then(function(contents) {
     console.log(JSON.stringify(contents, undefined, 4));
   });

But when it executes the console reports 'CORS-header ‘Access-Control-Allow-Origin’ missing'.

More information: using a standard empty VueJS project template with webdav version 1.6.1, on http://localhost:8080 and the nextcloud server is a remote server. Not sure if this is expected behaviour or not, since the example in the readme.md is doing exactly the same.

@perry-mitchell
Copy link
Owner

Hi @memen45 - What version of this library are you using? I'm currently testing with v2 in one of the PRs - #114 - And it works fine. No need for withCredentials it seems. How are you running this? In node or a browser?

@memen45
Copy link
Author

memen45 commented Nov 14, 2018

In dependencies it has 'webdav': '^1.6.1'. I tried to change it to 'webdav': '^2.0.0rc1' followed by the command npm install, however the browser console would then give a TypeError instead, so that did not work either. Maybe there are required dependencies that are not automatically installed?

I am running the project (with unmodified webpack config from vue-cli vue-init commands) using npm run dev and then indeed it is the browser giving the CORS errors.

@perry-mitchell
Copy link
Owner

perry-mitchell commented Nov 14, 2018

Please post the error message you're seeing.

In the mean time, try adding the following in your webpack config:

{
	node: {
		net: "empty"
	}
}

@memen45
Copy link
Author

memen45 commented Nov 15, 2018

I set 'webdav': '^2.0.0-rc1' in package.json, followed by the command npm install, then opened the browser to execute the same code as above, but this time without the withCredentials = true. The error I get is

TypeError: __WEBPACK_IMPORTED_MODULE_0_webdav___default(...) is not a function
	testwebdav			App.vue:36
	testwebdav			self-hosted:974:17 
	invoker				vue.esm.js:2027
	withMacroTask/fn._withTask	vue.esm.js:1826

I then tried adding your suggestion to the webpack config, got the same TypeError. Then I changed the webdav version back to 1.6.1, with the same webpack config and I am back to the CORS header missing error.

@perry-mitchell
Copy link
Owner

When requiring webdav, make sure not to require the default. As you'll see here, createClient is a property exported from the library.. The default is now an object and not a function like in version 1.*

Use this: const { createClient } = require("webdav"), not const createClient = require("webdav"); like before.

@memen45
Copy link
Author

memen45 commented Nov 15, 2018

That indeed solves the error, and now it is back to the CORS header missing.

Could it be a server side problem in Nextcloud? Is there a simple axios command that could show whether the problem is in this git or actually somewhere else (either VueJS/Webpack or Nextcloud server then I would think).

@perry-mitchell
Copy link
Owner

That indeed solves the error, and now it is back to the CORS header missing.

Progress, at least 😊

In the axios request docs it simply lists withCredentials as being the one point to do with CORS. You could share what headers are coming back from your Nextcloud server... if you could get those.

@memen45
Copy link
Author

memen45 commented Nov 15, 2018

The request headers:

Host: some.ncserver.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:63.0) Gecko/20100101 Firefox/63.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: nl,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate, br
Access-Control-Request-Method: PROPFIND
Access-Control-Request-Headers: depth
Origin: http://localhost:8080
Connection: keep-alive

And the response headers:

HTTP/1.1 200 OK
Date: Thu, 15 Nov 2018 21:46:26 GMT
Server: Apache/2.4.29 (Ubuntu)
Strict-Transport-Security: max-age=15552000; preload
Set-Cookie: octydpzmhl5q=<somestring>; path=/; secure; HttpOnly
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Set-Cookie: oc_sessionPassphrase=<somelongstring; path=/; secure; HttpOnly
Content-Security-Policy: default-src 'none';
X-Frame-Options: SAMEORIGIN
Set-Cookie: __Host-nc_sameSiteCookielax=true; path=/; httponly;secure; expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=lax
Set-Cookie: __Host-nc_sameSiteCookiestrict=true; path=/; httponly;secure; expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=strict
Allow: OPTIONS, GET, HEAD, DELETE, PROPFIND, PUT, PROPPATCH, COPY, MOVE, REPORT
DAV: 1, 3, extended-mkcol
MS-Author-Via: DAV
Accept-Ranges: bytes
Content-Length: 0
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
Referrer-Policy: no-referrer
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8

I hope these are the headers you are looking for? Thanks in advance!

@perry-mitchell
Copy link
Owner

perry-mitchell commented Nov 15, 2018 via email

@memen45
Copy link
Author

memen45 commented Nov 16, 2018

I tried to run it in incognito, but the headers look exactly the same, the only difference being the values for <somestring> and <somelongstring>.

@memen45
Copy link
Author

memen45 commented Nov 18, 2018

  • the request header may be incorrect, such that the Access-Control-Allow-Origin is not part of the response headers. Could you show me the headers that are sent and received by a properly working javascript example?
  • the nextcloud webdav may not support cross domain requests by design (that would not explain the example you provided here, but it is apparent from this link and it is common for webdav servers to not support it). Did you add something to the apache config serverside to allow cross domain connections?
  • there may be something with VueJS preventing the Access-Control-Allow-Origin-header from being available, therefore resulting in a CORS error. What minimum setup do you use for testing connection? Did you perhaps already test it in a default initialized vue project?

Would be great if we could sort out the problem! Thanks for your help in advance.

@perry-mitchell
Copy link
Owner

Could you show me the headers that are sent and received by a properly working javascript example?

We use the new version of webdav-client in the Buttercup browser extension (master), which I've tested recently to work with the Nextcloud demo site. I don't have a Nextcloud instance myself to test on (only ownCloud, which works fine).

It's not exactly a simple example, but I transpile webdav-client there using Webpack and then use it in the browser to request contents from WebDAV sources such as Nextcloud, which doesn't fail to my recollection. The new version of this extension will be out soon so hopefully that'll confirm this.

but it is apparent from this link and it is common for webdav servers to not support it)

Well that's a bit of a sweeping statement.. If it's an older webdav server they may not even use CORS headers, which means that there'd be no problem. If the server is new enough to implement CORS, it's definitely then possible that this client would break when in-browser. I've seen previously that a transpiled fetch library (like node-fetch) will fail due to the fact that the Origin header is sent incorrectly. This shouldn't be the case with the newest version of this library so I would expect still that there are no CORS issues.

That being said, I could be wrong on this completely due to the fact that I'm not currently testing against a live instance (relying on demo, like I said).

Did you add something to the apache config serverside to allow cross domain connections

I've made no alterations to any webdav service to bypass CORS.

there may be something with VueJS preventing the Access-Control-Allow-Origin-header from being available, therefore resulting in a CORS error

VueJS is just a UI framework.. I can't see how it'd affect network requests.

What minimum setup do you use for testing connection?

Unfortunately I don't have a simple setup I test besides the use I have for it in the Buttercup project. I regularly test it in that context as a transpiled library (using babel and webpack), and it's worked fine so far.


Definitely hope we can find the solution to your issue. I plan to release the new major version of this shortly so let's see if we can't find a way around it.

@memen45
Copy link
Author

memen45 commented Nov 22, 2018

The way I understand CORS at this point, is that it is a limitation imposed by browsers on the running webpage / web application. The remote server has to respond explicitly with a CORS header (Access-Control-Allow-.......), otherwise the request is not passed to the client code. Since older or simpler webdav servers would not know about the CORS headers, requests to these servers will always be limited by the browser. As soon as the code is not running inside a webpage, the requests are not limited by CORS anymore, so a browser extension should indeed be able to access cross origin sources.
However, this is just my understanding of the matter, but I am no expert nor experienced with this, so it could be completely incorrect. This link is from the mozilla docs on CORS, which I found through this project which supports webdav, except when the project is run from the browser as a webapp (see readme > Q&A).

@perry-mitchell
Copy link
Owner

Yeah, I get how CORS works on a basic level but I haven't delved in to all of the different ways of authenticating against it. I work with it a bit in my job but it's use within Buttercup+WebDAV has been a bit mysterious. It was previously working with Nextcloud (in the last several months) but as of today I've not been able to get it working on a demo instance. Seems that it's no longer working (their headers look very strict).

Unfortunately if the Nextcloud developers are going to restrict it like this and provide no workaround, there's not going to be much we can do.. 😕

@Geraldf
Copy link

Geraldf commented Nov 23, 2018

I do have exactly the same issue. I am trying to make a Webdav Request to next cloud from a react app. (so Node.js). My Error message is:
Access to XMLHttpRequest at 'https://cloud.fuchsclan.de/remote.php/webdav' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

it happens at this Code:
client .getDirectoryContents("/") .then(function(contents) { console.log(JSON.stringify(contents, undefined, 4)); });

in my Webpack config file, I have added the following:

devServer: {
hot: true , // enable HMR on the server
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "*",
"Access-Control-Allow-Methods": "GET, POST, PUT, MOVE, OPTIONS, PROPFIND"
}
},

@memen45
Copy link
Author

memen45 commented Nov 24, 2018

in my Webpack config file, I have added the following:

devServer: {
hot: true , // enable HMR on the server
headers: {
"Access-Control-Allow-Origin": "",
"Access-Control-Allow-Headers": "
",
"Access-Control-Allow-Methods": "GET, POST, PUT, MOVE, OPTIONS, PROPFIND"
}
},

These Acces-Control-Allow-xxx headers should be set on your nextcloud server, not the server from which the app is running. You could set those manually by editing the apache config file, however, from a security point of view you should only allow trusted domains to make requests (e.g. "Access-Control-Allow-Origin": "domainof.yourwebapp.com"). For a local instance in development it is of course not a problem to add "Access-Control-Allow-Origin": "*".

It was previously working with Nextcloud (in the last several months) but as of today I've not been able to get it working on a demo instance. Seems that it's no longer working (their headers look very strict).

Aha, so it probably has changed on the nextcloud side after an update then unfortunately.

@perry-mitchell perry-mitchell changed the title CORS-header ‘Access-Control-Allow-Origin’ missing CORS-header ‘Access-Control-Allow-Origin’ missing (Nextcloud) Nov 24, 2018
@perry-mitchell
Copy link
Owner

perry-mitchell commented Jan 10, 2019

I'll close this as it's not really related to this project. I've added a notice for CORS issues.

@aliyss
Copy link

aliyss commented May 26, 2019

So I actually managed to get this stuff working.

When setting up the whole stuff it is very important to configure the .htaccess file of the hosting. You will see a line with the following text: "#### DO NOT CHANGE ANYTHING ABOVE THIS LINE ####". All the changes below are the changes I made above that line. The main thing you have to do is edit:


<IfModule mod_env.c>
    Header set X-Content-Type-Options "nosniff"
    Header set X-XSS-Protection "1; mode=block"
    # Add security and privacy related headers
    Header always set Access-Control-Max-Age 1728000
    SetEnvIf Origin "http(s)?://(www.mywebsite.com|localhost:8080)$" AccessControlAllowOrigin=$0
    Header always set Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
    Header always set Access-Control-Allow-Methods: "GET,POST,OPTIONS,DELETE,PUT,PROPFIND"
    Header always set Access-Control-Allow-Headers: "Access-Control-Allow-Headers, Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers, Authorization, X-CSRF-Token, Depth, OCS-AP$"
    Header always set Access-Control-Allow-Credentials true
    SetEnv modHeadersAvailable true

    RewriteEngine On
    RewriteCond %{REQUEST_METHOD} OPTIONS
    RewriteRule ^(.*)$ $1 [R=200,L]
<IfModule>

As you see here you can replace the part with your own website (and add additional websites by using | as a seperator):

SetEnvIf Origin "http(s)?://(www.mywebsite.com|localhost:8080)$" AccessControlAllowOrigin=$0

I have added localhost:8080 as I am working with Vue on my website. This is highly discouraged and should be removed once the website is deployed.

Now follow the tutorial as given on the README:

In case you are getting a PROPFIND 405 error, this is most likely the solution:

.getDirectoryContents("remote.php/dav/files/...") instead of .getDirectoryContents("/")

It could be that I forgot a few changes in the .htaccess file, so in case it does not work out and you are still getting CORS errors just ping me.

@perry-mitchell
Copy link
Owner

In case you are getting a PROPFIND 405 error, this is most likely the solution:
.getDirectoryContents("remote.php/dav/files/...") instead of .getDirectoryContents("/")

This should have nothing to do with CORS, as these paths are appended to the host passed in during the factory creation.. The two examples you gave are not equivalent. The host should include the remote.php/dav/files/ in your example. So if your domain is example.com, your full connection URL should be https://example.com/remote.php/dav/files/.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants