Cross Site Request Forgeries (CSRF) and Grails

I recently had to come up with defenses against cross-site request forgery (CSRF) attacks for a grails application. This goes along with hand-in-hand with XSS injection protection to make your site as secure as possible. There’s lots of information spread out on the internet about CSRFs, but nothing specifically for grails, so here’s a quick guide I whipped up.

Require POST

Forms that change state should be submitted with POSTs. In views, g:forms should use the post method. This is the default for g:form tags, but regular form tags default to GET, so I prefer to make it explicit.

In controllers, limit the accepted methods for your actions with a static allowedMethods block. If the form gets submitted with a get, grails will return a 405 error code to the browser.

class SomethingController {
    static allowedMethods = [save: 'POST', update: 'POST',
        delete: 'POST']



Use A Form Token

Use the one-time token grails provides. This prevents accidental double submits, but it also rejects forged requests that weren’t submitted from your form page. A unique token is generated when the form gets loaded, and if it’s wrong or not present when the form get submitted, the controller can return an error.

<g:form action="save" method="post" useToken="true">

Wrap your controller in a withForm block:

class SomethingController {

    def save = {
        withForm {
            // token was correct, save the object
        }.invalidToken {
            response.status = 405

Verify the referer

The referer HTTP header will be set to form that submitted your request. This should be from your application, and it’s easy to test it and ensure it really is. No need for this on GET requests though, since it’ll break bookmarks and deep links in. This can be enforced on POSTs with a simple filter in grails-app/conf:

import org.codehaus.groovy.grails.commons.ConfigurationHolder as CH

class RefererFilters {
    // referer must match serverURL, optionally https
    static validRefererPrefix = "^${CH.config.grails.serverURL}".replace("http", "https?")
    def filters = {
        checkReferer(controller: '*', action: '*') {
            before = {
                if (request.method.toUpperCase() == "POST") {
                    def referer = request.getHeader('Referer')

                    return referer && referer =~ validRefererPrefix

(Maybe) Adjust the session timeout

The default session duration for tomcat is 30 minutes. A lower value can close the time window for CSRFs, but can also harm the usability of the site. To customize it, run grails install-templates add this to src/templates/war/web.xml inside the web-app tag:



  1. Fabien7474 says:

    It is great to see that there is very little effort to be protected against CSRF if we want to.
    Thx for this article.

  2. This is quite useful post. I didn’t know about the useToken attribute.

    Thanks for sharing this.

  3. eyuzwa says:

    Great stuff Andrew, thanks for sharing!

  1. [...] This post was mentioned on Twitter by Colin Harrington, Tim Yates, Andrew Taylor, Jay Bose, Benjamin Klein and others. Benjamin Klein said: RT @ataylor284: Preventing cross-site request forgeries (CSRF) in grails: #grails [...]

  2. [...] Cross Site Request Forgeries (CSRF) and Grails [...]

  3. [...] Grails et les Cross Site Request Forgeries (CSRF) [...]