Configuring CORS with Grails 3 and Spring Security REST
Asked Answered
G

2

9

I'm trying to figure out how to plug an Angular 2 frontend (running on localhost:4200) into a Grails 3 backend (running on localhost:8080) so I need to enable CORS support in the grails app.

I found this Github project (https://github.com/appcela/grails3-cors-interceptor-spring-security-rest-sample-app) that shows how to enable CORS using the grails3-cors-interceptor plugin. I'm running this very application as a test backend and I'm putting a breakpoint in CorsService.processPreflight() to check when it's called. And when I do a GET on /api/books, the browser sends an OPTIONS call first that goes through the breakpoint, but the following GET doesn't seem to go there and I can't figure out why. Any idea?

Gouty answered 7/10, 2016 at 8:5 Comment(1)
Hey! Grails 3.2.1 just released. It has inbuilt CORS docs.grails.org/latest/guide/introduction.html#whatsNewCorsBetterment
B
15

Update

Grails 3.2.1 has inbuilt feature to support CORS. Check this out http://docs.grails.org/latest/guide/theWebLayer.html#cors

Just add this in your application.yml to enable it

grails:
    cors:
        enabled: true

(Make sure you look for the environment for which you want to enable CORS)

Original Post

You don't need a plugin (unless you want to use that plugin) to enable CORS here. Well, for your rest endpoints, you can always enable the CORS using the Grails interceptors like below:

class CorsInterceptor {

    CorsInterceptor() {
        matchAll()
    }

    boolean before() {
        if (request.method == "OPTIONS") {
            response.setHeader("Access-Control-Allow-Origin", "http://localhost:4200")
            response.setHeader("Access-Control-Allow-Credentials", "true")
            response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE")
            response.setHeader("Access-Control-Max-Age", "3600")

            response.status = 200
        }

        return true
    }

    boolean after() { true }
}

But Grails interceptors cannot intercept the endpoints provided by the Spring Security core/rest plugins since the priority of their interceptors are higher than that of Grails interceptors. So you first need to add a customer filter and then register it before the Spring related filters.

Add a file in src/main/groovy:

package test

import org.springframework.web.filter.OncePerRequestFilter

import javax.servlet.FilterChain
import javax.servlet.ServletException
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse

class CorsFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest req, HttpServletResponse resp, FilterChain chain)
            throws ServletException, IOException {

        if (req.getMethod() == "OPTIONS") {
            resp.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
            resp.addHeader("Access-Control-Max-Age", "3600")
            resp.addHeader("Access-Control-Allow-Origin", "http://localhost:4200")
            resp.addHeader("Access-Control-Allow-Credentials", "true")
            resp.status = 200
        } else {
            chain.doFilter(req, resp)
        }
    }
}

Register it on the resources.groovy:

beans = {
    corsFilterFoo(CorsFilter)
}

Now, add it to the Spring's filter chain before the security context filter (in Bootstrap.groovy):

SpringSecurityUtils.clientRegisterFilter("corsFilterFoo",
    SecurityFilterPosition.SECURITY_CONTEXT_FILTER.order - 1)

References: https://github.com/grails-plugins/grails-spring-security-core/blob/v3.1.1/src/main/groovy/grails/plugin/springsecurity/SpringSecurityUtils.groovy#L698

Betterment answered 8/10, 2016 at 16:15 Comment(4)
Where do you add the last line to register the filter?Gouty
Oops! sorry. Add it to Bootstrap.groovyBetterment
@ShashankAgrawal I am using Grails 3.2.7 I followed the steps for enabling CORS with grails 3 in application.yml. I am trying to allow OPTIONS method be passed with any of the request methods. But by simply enabling the cors, I am not able to achieve it. Can you please elaborate on this?Piloting
You don't have to allow OPTIONS method because that is the method that is used for pre-flight request to check whether CORS is allowed or notBetterment
A
2

With the latest version of Grails 3 you just need to enable CORS if your running your applications locally grails run-app. My version is Grails Version: 3.3.10. Groovy grails.cors.enabled=true

Allative answered 19/2, 2020 at 21:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.