Problem/Motivation
If a CORS configuration is enabled in services.yml, it will break the submission of forms via the Drupal website's core UI (for example, updating permissions and updating a node via the edit form both fail), unless the site's own host name is specified as an allowed origin in the CORS configuration.
This CORS configuration leads to form submission failures:
cors.config:
enabled: true
allowedHeaders: ['Content-Type', 'Access-Control-Allow-Headers', 'Authorization', 'X-Requested-With', 'X-CSRF-Token']
allowedMethods: ['POST', 'GET', 'OPTIONS', 'PATCH', 'DELETE']
allowedOrigins: ['http://localhost:4200']
exposedHeaders: true
maxAge: false
supportsCredentials: true
Specifying allowedOrigins: '*'
or allowedOrigins: ['http://localhost:4200', 'http://the-drupal-site.com']
works around the failure.
Proposed resolution
- Get the Pull Request that has been outstanding in the upstream library committed: https://github.com/asm89/stack-cors/pull/11
- Update the version requirement for that library in core/composer.json
Remaining tasks
- Tests
Comment | File | Size | Author |
---|---|---|---|
#31 | interdiff-2853201.txt | 895 bytes | dawehner |
#31 | 2853201-31.patch | 3.88 KB | dawehner |
#27 | interdiff-2853201-26-27.txt | 1.52 KB | hampercm |
#27 | upstream_cors_breaks-2853201-27.patch | 3.94 KB | hampercm |
#27 | upstream_cors_breaks-2853201-27-test-only.patch | 1.33 KB | hampercm |
Comments
Comment #2
Wim LeersHm, is this actually a bug? I guess we could whitelist all trusted hosts automatically (
\Symfony\Component\HttpFoundation\Request::getTrustedHosts()
).This almost seems more like a documentation problem?
Comment #3
hampercm CreditAttribution: hampercm at Acquia commentedCORS is only supposed to be relevant to cross-origin requests, hence the name, so it seems like a bad idea to maintain the current behavior. it will also encourage people to just specify
allowedOrigins: '*’
, which is less secure.Comment #4
Wim LeersThat is a very good point! :)
However, I don't understand how this is possible, because
\Asm89\Stack\Cors::handle()
does this:… and
isCorsRequest()
does this:Aha!
I just submitted a form with Chrome, and sure enough, there was an
Origin
request header.So guess, what? This has been broken since July 2014: https://github.com/asm89/stack-cors/issues/10 + https://github.com/asm89/stack-cors/pull/11.
Comment #5
Wim LeersComment #6
piyuesh23 CreditAttribution: piyuesh23 at QED42 commentedJust in case someone is looking for using the github patches, you can update your composer.json with the following:
Comment #7
dawehnerI'm wondering whether core should point to the fork containing the fix for now.
The alternative would be to actually override the classes. Sadly they are using private functions which makes things harder than it would have to be.
Comment #8
hampercm CreditAttribution: hampercm at Acquia commentedThis finally got committed upstream! No more need for the work-around patch in #7.
Working on a standard composer.json patch...
Comment #9
hampercm CreditAttribution: hampercm at Acquia commentedUgh, just realized the release hasn't been cut yet. I pinged @asm86 on GitHub asking for that to be done.
Comment #10
navneet0693 CreditAttribution: navneet0693 as a volunteer and at QED42 commentedYeah! finally, it got merged. https://github.com/asm89/stack-cors/pull/11
Comment #11
hampercm CreditAttribution: hampercm at Acquia commentedUpdated requirement for
asm89/stack-cors
incore/composer.json
to to "~1.1"Comment #12
dawehnerI am wondering whether we should have some form of regression / basic functional test coverage for that.
Comment #13
Wim Leers#12 I wonder the same, but then again: shouldn't that be up to the upstream? We shouldn't have test coverage for every upstream bugfix, should we?
Difficult line to walk.
Comment #14
Wim LeersAlthough I guess in this case thanks to
CorsIntegrationTest
being added in #2850034: CORS allow-origin '*' not possible because of cached headers, it's now trivial to add this test coverage? So, let's do this.Comment #15
dawehnerWell I agree there should be upstream unit testing ... but I think from the Drupal REST product point of view ensuring that enabling cors doesn't break the Drupal site makes sense, and as such having test coverage would be useful. Some simple form would be totally enough.
Comment #16
Wim LeersYou're absolutely right. Thanks for insisting on that!
Comment #17
hampercm CreditAttribution: hampercm at Acquia commentedWorking on a test for this...
Comment #18
hampercm CreditAttribution: hampercm at Acquia commentedAdds a test to verify that POSTs with an "Origin" header the same as the site's base URL are permitted.
Interdiff for this patch is the same as the test-only patch
Comment #21
hampercm CreditAttribution: hampercm at Acquia commentedFix origin string calculation so it (hopefully) works on Drupal CI
Comment #22
hampercm CreditAttribution: hampercm at Acquia commentedComment #23
hampercm CreditAttribution: hampercm at Acquia commentedArg, forgot to attach interdiff :P
Comment #25
dawehnerYou should get the client from mink directly:
$client = $this->getSession()->getDriver()->getClient()->getClient();
, see\Drupal\Tests\rest\Functional\ResourceTestBase::request
Comment #26
hampercm CreditAttribution: hampercm at Acquia commentedModified test to address #25
Comment #27
hampercm CreditAttribution: hampercm at Acquia commentedRemove unnecessary setUp() and httpClient member
Comment #31
dawehnerHere is a small improvement for the test, but all in all, this looks great.
Comment #32
alexpottCommitted 453d552 and pushed to 8.4.x. Thanks!
Unfortunately we can only bump minors in our own minor release so that makes this allegedly not patch safe. However there is something interesting here and worth thinking about.
By our current definitions 1.1 is compatible with ~1.0 - so what we're really changing here is the minimum version. So the question is can we change our minimum version in a patch release. Looking at https://github.com/asm89/stack-cors/compare/1.0.0...1.1.0 it drops PHP 5.3 and 5.4 support but non of the other changes would not be considered for a Drupal patch release.
I guess a mitigation is that work around is pretty simple.
Tagging with 8.4.0 release notes as I think library upgrades should be mentioned.
Comment #34
dawehnerWe could ask the author to release a 1.0.1 which has the fix applied.
Comment #35
alexpott@dawehner yep that'd allow use to fix this in a patch release imo. Do you think it is worth it given the mitigation?
Comment #36
dawehnerPractically it makes it impossible to use CORS for real sites, I would argue.
It is never not worth to try: https://github.com/asm89/stack-cors/issues/44
Comment #37
hampercm CreditAttribution: hampercm at Acquia commentedIt seems to me that bug fixes should preempt the restriction against minor-version library updates. If something is broken in a way that is impacting usability significantly, it should be fixed.
I certainly see the point of this restriction, but in this case it feels like the people are serving the process, instead of the process serving the people.
Comment #39
dawehnerBoth contentacms and reserverouir ran into this specific problem. It makes it impossible for them to use cors. I think the theoretical possibility of a BC problem, vs. people running into a broken site is a bit ridiculous.
Comment #40
xjmToday was the final normal bugfix release for 8.3.x. Aside from criticals and security fixes, no more commits will be made to 8.3.x, so marking this issue fixed again. Thanks!
Comment #42
Wim Leers