CORS support broken in Grails 4
- Dominant language
- Groovy
- Stars
- 2.9k
- Forks
- 975
- Avg merge
- 1d 22h
- Merged PRs (30d)
- 92
Description
From some investigation, it's possible this is a documentation bug, possibly caused by changes in underlying Spring. But not being an expert in grails/cors, someone should look at it, and at the very least, update the doco.
Here's the situation...
I have a working Angular / Grails 3 app. It has the most basic CORS setup in application.yml:
```
grails:
cors:
enabled: true
```
If I look at what happens in Fiddler, the server responds with these headers:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://localhost:4200
Good stuff.
But in Grails 4 the server responds like this:
Access-Control-Allow-Origin: *
This results in the browser failing like this:
Access to XMLHttpRequest at 'http://localhost:8080/plant/sectionData/' from origin 'http://localhost:4200' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
But it turns out if I turn on "allowedCredentials" it starts to work...
```
grails:
cors:
enabled: true
allowCredentials: true
```
However the documentation claims that merely settings grails.cors.enabled=true results in a mapping of "/**" with "allowCredentials= true".
As far as I can see, the reason for this change in behaviour is found in Spring's CorsConfiguration.java: applyPermitDefaultValues, where Spring4 used to have a line:
```
public CorsConfiguration applyPermitDefaultValues() {
//blah blah
if (this.allowCredentials == null) {
this.setAllowCredentials(true);
}
//blah blah
}
```
But Spring 5 doesn't have that line in the code.
So I'm assuming this is for some reason deliberate, and I guess maybe the correct thing is to update this table in the documentation: https://docs.grails.org/4.0.10/guide/single.html#cors
allowedOrigins | ['*']
-- | --
allowedMethods | ['*']
allowedHeaders | ['*']
exposedHeaders | null
maxAge | 1800
allowCredentials | true
to align with what is currently existing in CorsConfiguration.applyPermitDefaultValues()
and present some examples that actually work.
### Task List
Create an Angular or javascript app, that makes grails requests. Use this config:
```
grails:
cors:
enabled: true
```
Observe the wrong headers.
### Expected Behaviour
Headers returned by Grails 3, as per above
### Actual Behaviour
The headers make browsers CORS security fail.
### Environment Information
- **Operating System**: Windows 10
- **Grails Version:** 4.0.0 through 4.0.9 fail
- **JDK Version:** 1.8.0
### Example Application
Contributor guide
Research direction
Start with the CORS configuration in application.yml, the Grails 4 CORS section at guide/single.html#cors, and Spring's CorsConfiguration.applyPermitDefaultValues. Reproduce the headers with the minimal Angular or JavaScript request, determine whether the behavior or documentation is incorrect, and finish with working behavior and documentation that matches the observed configuration.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- angular, groovy, spring
- Domain
- api, backend, documentation, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100