Skip to content

Allow to configure "allowed domains" for CORS on DAV - #40537

Draft
susnux wants to merge 6 commits into
masterfrom
feat/cors-on-webdav
Draft

Allow to configure "allowed domains" for CORS on DAV#40537
susnux wants to merge 6 commits into
masterfrom
feat/cors-on-webdav

Conversation

@susnux

@susnuxsusnux commented Sep 20, 2023

Copy link
Copy Markdown
Contributor

Summary

This adds CORS support to the DAV routes, the default is non breaking -> so no other domain is allowed.
But the admin can configure a list of allowed domains which will be allowed to access the DAV routes using CORS.

Moreover the admin can enable user defined lists, meaning that users can add their own allowed domains for WebDAV related requests, see #30964.

Why do we need CORS on DAV?

See #3131

Basically to access it within the browser from a different page, like e.g. the Dropbox file picker with allows you to pick files from your cloud onto another page (e.g. upload something from cloud to form etc).

Screenshot

Screenshot_20230920_150622

Todo

  • Follow-up: User config UI
  • Follow-up: allowed header UI
  • If this is decided: Write documentation

Checklist

* Exclude DAV CORS handling when no Origin specified
This will exclude non-browser clients from CORS handling.
Fixes some clients like davfs which break when CORS is enabled.
* fix: CORS on WebDAV is not working
WebDAV is not working at all when used by on browser Javascript because the CORS headers
are only present in the OPTION request, but not in the subsequent WebDAV methods.
* This behavior is caused by a erroneous json_decode call while retriving the user's domains whitelist.
It return an object, so the is_array always fails and no header are sent.
* Add Access-Control-Expose-Headers - to allow clients to access certain headers
* Adding many headers as allowed headers + add capability to read additional allowed headers from config.php
@susnuxsusnux added this to the Nextcloud 28 milestone Sep 20, 2023
@susnux
susnux requested review from a team, ArtificialOwl, icewind1991, nickvergessen and skjnldsv and removed request for a teamSeptember 20, 2023 13:15
I removed the beforeController logic here due to the change of handling CORS since PR 28457[1]
According to previous implementation, CORS was only allowed with methods that had @publicpage notation for preventing CSRF attacks.
But in the latest PR by me, the current implementations is as follows:
* maintain a white-list of domains for whom CORS is enabled
* This list can be viewed and edited under settings -> personal -> security
This implementation removes the need for `@PublicPage`[2].
[1] owncloud/core#28457
[2] owncloud/core#28864
@susnuxsusnux added 3. to review Waiting for reviews and removed 2. developing Work in progress labels Sep 20, 2023
github-advanced-security[bot]

This comment was marked as outdated.

@susnuxsusnux changed the title Allow to configure trusted domains for CORS on DAVAllow to configure "allowed domains" for CORS on DAVSep 20, 2023
Also make sure to only return allowed methods for DAV responses
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
Comment threadapps/dav/lib/Connector/Sabre/CorsPlugin.php
return;
}
} catch (\InvalidArgumentException $e) {
\OC::$server->getLogger()->debug('Invalid origin header was passed', ['Origin' => $originHeader, 'exception' => $e]);

Check notice

Code scanning / Psalm

DeprecatedMethod

The method OC\Server::getLogger has been marked as deprecated

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
\OC::$server->getLogger()->debug('Invalid origin header was passed', ['Origin' => $originHeader, 'exception' => $e]);
\OC::$server->get(LoggerInterface::class)->debug('Invalid origin header was passed', ['origin' => $originHeader, 'exception' => $e]);

return;
}
} catch (\InvalidArgumentException $e) {
\OC::$server->getLogger()->debug('Invalid origin header was passed', ['Origin' => $originHeader, 'exception' => $e]);

Check notice

Code scanning / Psalm

DeprecatedMethod

The method OCP\ILogger::debug has been marked as deprecated
// unauthenticated request shall add cors headers as well
$userId = null;
if ($this->userSession->getUser() !== null) {
$userId = $this->userSession->getUser()->getUID();

Check notice

Code scanning / Psalm

PossiblyNullReference

Cannot call method getUID on possibly null value
$this->server->addPlugin(new ProfilerPlugin($this->request));
$this->server->addPlugin(new BlockLegacyClientPlugin(\OC::$server->getConfig()));
$this->server->addPlugin(new AnonymousOptionsPlugin());
$this->server->addPlugin(new CorsPlugin(\OC::$server->getUserSession(), \OC::$server->getConfig()));

Check notice

Code scanning / Psalm

DeprecatedMethod

The method OC\Server::getUserSession has been marked as deprecated

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can change to:

Suggested change
$this->server->addPlugin(newCorsPlugin(\OC::$server->getUserSession(), \OC::$server->getConfig()));
$this->server->addPlugin(newCorsPlugin(\OC::$server->get(IUserSession), \OC::$server->get(IConfig::class)));

With:

use \OCP\IConfig;
use \OCP\IUserSession

$this->server->addPlugin(new ProfilerPlugin($this->request));
$this->server->addPlugin(new BlockLegacyClientPlugin(\OC::$server->getConfig()));
$this->server->addPlugin(new AnonymousOptionsPlugin());
$this->server->addPlugin(new CorsPlugin(\OC::$server->getUserSession(), \OC::$server->getConfig()));

Check notice

Code scanning / Psalm

DeprecatedMethod

The method OC\Server::getConfig has been marked as deprecated
* @return DataResponse
*/
public function updateUserEnabled($value) {
if (!is_bool($value)) {

Check notice

Code scanning / Psalm

DocblockTypeContradiction

Docblock-defined type bool for $value is always bool

// Reach here if it's valid
$response = new \OC\OCS\Result(null, 100, 'OPTIONS request successful');
\OC_Response::setOptionsRequestHeaders($response, $this->config);

Check failure

Code scanning / Psalm

InvalidArgument

Argument 1 of OC_Response::setOptionsRequestHeaders expects OCP\AppFramework\Http\Response<int, array<string, mixed>>|Sabre\HTTP\ResponseInterface, but OC\OCS\Result provided
@nickvergessen
nickvergessen removed their request for review September 21, 2023 08:37
@skjnldsv
skjnldsv removed their request for review September 22, 2023 09:16
@skjnldsv

This comment was marked as resolved.

This was referenced Mar 18, 2024
@skjnldsvskjnldsv mentioned this pull request Mar 28, 2024
81 tasks
@skjnldsvskjnldsv added 2. developing Work in progress stale Ticket or PR with no recent activity and removed 3. to review Waiting for reviews labels Jul 27, 2024
This was referenced Jul 30, 2024
This was referenced Aug 5, 2024
@skjnldsvskjnldsv mentioned this pull request Aug 13, 2024
@skjnldsvskjnldsv removed this from the Nextcloud 30 milestone Aug 14, 2024
@aleixq

Copy link
Copy Markdown

I am coming from #37716 for which I was proposing #37896 .
If the reason to allow dav cors is to make it easier to offer a filepicker, I think that filesharing api and filepreview api may be covered to be allowed in a similar way too. If not it will be a raw basic one IMHO.
By now the way to offer a functional filepicker is to use the webapppassword app as it also includes the filesharing api extended and preview api extended, for which I made the accepted PR some time ago when I was trying to offer Nextcloud as a DAM for a CMS (drupal).

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

2. developingWork in progressenhancementfeature: davsecuritystaleTicket or PR with no recent activity

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CORS origin allowed list check CORS setting at user level Support for cross-domain WebDAV access (CORS)

10 participants

@susnux@skjnldsv@aleixq@Altahrim@github-advanced-security@AndyScherzinger@joshtrichards@blizzz@nextcloud-bot@noveens