Skip to content

Commit 09589b0

Browse files
authored
Merge pull request #13 from codeconsole/csrf-spring-security
If using Spring Security, utilize native csrf protection
2 parents d19ecae + 8460a8c commit 09589b0

File tree

4 files changed

+30
-3
lines changed

4 files changed

+30
-3
lines changed

plugin/grails-app/controllers/org/grails/plugins/console/ConsoleController.groovy

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,18 @@ class ConsoleController implements Controller {
4848
model.json.csrfToken = session['CONSOLE_CSRF_TOKEN']
4949
}
5050

51+
// Check for exsitence of Spring Security CSRF token
52+
def springCsrfToken = request.getAttribute('org.springframework.security.web.csrf.CsrfToken')
53+
if (springCsrfToken) {
54+
try {
55+
model.json.springSecurityCsrfToken = springCsrfToken.token
56+
model.json.springSecurityCsrfHeader = springCsrfToken.headerName
57+
model.json.springSecurityCsrfParameter = springCsrfToken.parameterName
58+
} catch (Exception e) {
59+
log.error("Could not access Spring Security CSRF token: ${e.message}")
60+
}
61+
}
62+
5163
render view: 'index', model: model
5264
}
5365

plugin/grails-app/controllers/org/grails/plugins/console/TokenInterceptor.groovy

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,12 @@ class TokenInterceptor implements Interceptor {
1313
}
1414

1515
boolean before() {
16+
// Skip console's CSRF validation if Spring Security CSRF is handling it
17+
def springCsrfToken = request.getAttribute('org.springframework.security.web.csrf.CsrfToken')
18+
1619
if (actionName
1720
&& csrfProtectionEnabled
21+
&& !springCsrfToken // Only validate console token if Spring Security CSRF is not present
1822
&& (!session['CONSOLE_CSRF_TOKEN'] || request.getHeader('X-CSRFToken') != session['CONSOLE_CSRF_TOKEN'])) {
1923
response.status = 403
2024
response.writer.println "CSRF token doesn't match. Please refresh the page."

web/app/app.coffee

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,13 @@ Marionette.Renderer.render = (template, data) ->
33

44
$.ajaxSetup(
55
beforeSend: (xhr, settings) ->
6-
if not this.crossDomain and App.data.csrfToken
7-
xhr.setRequestHeader 'X-CSRFToken', App.data.csrfToken
6+
if not this.crossDomain
7+
# Send Spring Security CSRF token if available
8+
if App.data.springSecurityCsrfToken and App.data.springSecurityCsrfHeader
9+
xhr.setRequestHeader App.data.springSecurityCsrfHeader, App.data.springSecurityCsrfToken
10+
# Also send console's own CSRF token if enabled
11+
else if App.data.csrfToken
12+
xhr.setRequestHeader 'X-CSRFToken', App.data.csrfToken
813
)
914

1015
Application = Backbone.Marionette.Application.extend

web/app/result/result-model.coffee

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,16 @@ App.module 'Result', (Result, App, Backbone, Marionette, $, _) ->
77
execute: ->
88
@set 'loading', true
99

10-
jqxhr = $.post App.createLink('execute'),
10+
postData =
1111
autoImportDomains: App.settings.get('editor.autoImportDomains')
1212
code: @get('input')
1313

14+
# Include Spring Security CSRF token as parameter if available
15+
if App.data.springSecurityCsrfToken and App.data.springSecurityCsrfParameter
16+
postData[App.data.springSecurityCsrfParameter] = App.data.springSecurityCsrfToken
17+
18+
jqxhr = $.post App.createLink('execute'), postData
19+
1420
console.info 'Executing script...'
1521

1622
jqxhr.done (response) =>

0 commit comments

Comments
 (0)