grails-core icon indicating copy to clipboard operation
grails-core copied to clipboard

CORS support broken in Grails 4

Open xpusostomos opened this issue 3 years ago • 3 comments

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

xpusostomos avatar Apr 14 '21 14:04 xpusostomos

@xpusostomos Would you be interested in sending PR to update the documentation?

puneetbehl avatar Apr 19 '21 18:04 puneetbehl

I ran into the same issue. This was working in grails 3.3.11 and failed in 4.0.11: cors { enabled = true mappings = [ "/**": [ allowedOrigins: [ 'http://' + System.env.SERVER_HOST_PORT, 'https://' + System.env.SERVER_HOST_PORT, 'http://' + System.env.AWS_GS_ASSETS_CLOUDFRONT_URL, 'https://' + System.env.AWS_GS_ASSETS_CLOUDFRONT_URL ] ] ] }

I tried changing it to this:

cors { enabled = true allowedOrigins = [ 'http://' + System.env.SERVER_HOST_PORT, 'https://' + System.env.SERVER_HOST_PORT, 'http://' + System.env.AWS_ASSETS_CLOUDFRONT_URL, 'https://' + System.env.AWS_ASSETS_CLOUDFRONT_URL ] }

but it still failed until I added allowCredentials = true

jaGarcia avatar Aug 21 '21 01:08 jaGarcia

It would appear that in grails 5, Spring has changed again and you now need allowedOriginPatterns

grails:
    cors:
        enabled: true
        allowCredentials: true
        allowedOriginPatterns: '*'

xpusostomos avatar Jan 19 '22 00:01 xpusostomos