diff --git a/plugin/grails-app/controllers/org/grails/plugins/console/ConsoleController.groovy b/plugin/grails-app/controllers/org/grails/plugins/console/ConsoleController.groovy index 36a443b..7e0c762 100644 --- a/plugin/grails-app/controllers/org/grails/plugins/console/ConsoleController.groovy +++ b/plugin/grails-app/controllers/org/grails/plugins/console/ConsoleController.groovy @@ -48,6 +48,18 @@ class ConsoleController implements Controller { model.json.csrfToken = session['CONSOLE_CSRF_TOKEN'] } + // Check for exsitence of Spring Security CSRF token + def springCsrfToken = request.getAttribute('org.springframework.security.web.csrf.CsrfToken') + if (springCsrfToken) { + try { + model.json.springSecurityCsrfToken = springCsrfToken.token + model.json.springSecurityCsrfHeader = springCsrfToken.headerName + model.json.springSecurityCsrfParameter = springCsrfToken.parameterName + } catch (Exception e) { + log.error("Could not access Spring Security CSRF token: ${e.message}") + } + } + render view: 'index', model: model } diff --git a/plugin/grails-app/controllers/org/grails/plugins/console/TokenInterceptor.groovy b/plugin/grails-app/controllers/org/grails/plugins/console/TokenInterceptor.groovy index 50916f4..04e47d8 100644 --- a/plugin/grails-app/controllers/org/grails/plugins/console/TokenInterceptor.groovy +++ b/plugin/grails-app/controllers/org/grails/plugins/console/TokenInterceptor.groovy @@ -13,8 +13,12 @@ class TokenInterceptor implements Interceptor { } boolean before() { + // Skip console's CSRF validation if Spring Security CSRF is handling it + def springCsrfToken = request.getAttribute('org.springframework.security.web.csrf.CsrfToken') + if (actionName && csrfProtectionEnabled + && !springCsrfToken // Only validate console token if Spring Security CSRF is not present && (!session['CONSOLE_CSRF_TOKEN'] || request.getHeader('X-CSRFToken') != session['CONSOLE_CSRF_TOKEN'])) { response.status = 403 response.writer.println "CSRF token doesn't match. Please refresh the page." diff --git a/web/app/app.coffee b/web/app/app.coffee index 294b586..ac7dd3a 100644 --- a/web/app/app.coffee +++ b/web/app/app.coffee @@ -3,8 +3,13 @@ Marionette.Renderer.render = (template, data) -> $.ajaxSetup( beforeSend: (xhr, settings) -> - if not this.crossDomain and App.data.csrfToken - xhr.setRequestHeader 'X-CSRFToken', App.data.csrfToken + if not this.crossDomain + # Send Spring Security CSRF token if available + if App.data.springSecurityCsrfToken and App.data.springSecurityCsrfHeader + xhr.setRequestHeader App.data.springSecurityCsrfHeader, App.data.springSecurityCsrfToken + # Also send console's own CSRF token if enabled + else if App.data.csrfToken + xhr.setRequestHeader 'X-CSRFToken', App.data.csrfToken ) Application = Backbone.Marionette.Application.extend diff --git a/web/app/result/result-model.coffee b/web/app/result/result-model.coffee index 2fcbb72..47b86d8 100644 --- a/web/app/result/result-model.coffee +++ b/web/app/result/result-model.coffee @@ -7,10 +7,16 @@ App.module 'Result', (Result, App, Backbone, Marionette, $, _) -> execute: -> @set 'loading', true - jqxhr = $.post App.createLink('execute'), + postData = autoImportDomains: App.settings.get('editor.autoImportDomains') code: @get('input') + # Include Spring Security CSRF token as parameter if available + if App.data.springSecurityCsrfToken and App.data.springSecurityCsrfParameter + postData[App.data.springSecurityCsrfParameter] = App.data.springSecurityCsrfToken + + jqxhr = $.post App.createLink('execute'), postData + console.info 'Executing script...' jqxhr.done (response) =>