SEC-2276: Delay saving CsrfToken until token is accessed
This also removed the CsrfToken from the response headers to prevent the token from being saved. If user's wish to return the CsrfToken in the response headers, they should use the CsrfToken found on the request.
This commit is contained in:
+2
-1
@@ -36,6 +36,7 @@ import org.springframework.security.web.access.intercept.FilterSecurityIntercept
|
||||
import org.springframework.security.web.context.HttpRequestResponseHolder
|
||||
import org.springframework.security.web.context.HttpSessionSecurityContextRepository
|
||||
import org.springframework.security.web.csrf.CsrfToken
|
||||
import org.springframework.security.web.csrf.DefaultCsrfToken;
|
||||
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository
|
||||
|
||||
import spock.lang.AutoCleanup
|
||||
@@ -69,7 +70,7 @@ abstract class BaseSpringSpec extends Specification {
|
||||
}
|
||||
|
||||
def setupCsrf(csrfTokenValue="BaseSpringSpec_CSRFTOKEN") {
|
||||
csrfToken = new CsrfToken("X-CSRF-TOKEN","_csrf",csrfTokenValue)
|
||||
csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN","_csrf",csrfTokenValue)
|
||||
new HttpSessionCsrfTokenRepository().saveToken(csrfToken, request,response)
|
||||
request.setParameter(csrfToken.parameterName, csrfToken.token)
|
||||
}
|
||||
|
||||
+1
-2
@@ -79,8 +79,7 @@ class WebSecurityConfigurerAdapterTests extends BaseSpringSpec {
|
||||
'Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains',
|
||||
'Cache-Control': 'no-cache,no-store,max-age=0,must-revalidate',
|
||||
'Pragma':'no-cache',
|
||||
'X-XSS-Protection' : '1; mode=block',
|
||||
'X-CSRF-TOKEN' : csrfToken.token]
|
||||
'X-XSS-Protection' : '1; mode=block']
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
|
||||
+10
-20
@@ -49,8 +49,7 @@ public class NamespaceHttpHeadersTests extends BaseSpringSpec {
|
||||
'Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains',
|
||||
'Cache-Control': 'no-cache,no-store,max-age=0,must-revalidate',
|
||||
'Pragma':'no-cache',
|
||||
'X-XSS-Protection' : '1; mode=block',
|
||||
'X-CSRF-TOKEN' : csrfToken.token]
|
||||
'X-XSS-Protection' : '1; mode=block']
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@@ -70,8 +69,7 @@ public class NamespaceHttpHeadersTests extends BaseSpringSpec {
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then:
|
||||
responseHeaders == ['Cache-Control': 'no-cache,no-store,max-age=0,must-revalidate',
|
||||
'Pragma':'no-cache',
|
||||
'X-CSRF-TOKEN' : csrfToken.token]
|
||||
'Pragma':'no-cache']
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@@ -91,8 +89,7 @@ public class NamespaceHttpHeadersTests extends BaseSpringSpec {
|
||||
when:
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then:
|
||||
responseHeaders == ['Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains',
|
||||
'X-CSRF-TOKEN' : csrfToken.token]
|
||||
responseHeaders == ['Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains']
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@@ -111,8 +108,7 @@ public class NamespaceHttpHeadersTests extends BaseSpringSpec {
|
||||
when:
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then:
|
||||
responseHeaders == ['Strict-Transport-Security': 'max-age=15768000',
|
||||
'X-CSRF-TOKEN' : csrfToken.token]
|
||||
responseHeaders == ['Strict-Transport-Security': 'max-age=15768000']
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@@ -133,8 +129,7 @@ public class NamespaceHttpHeadersTests extends BaseSpringSpec {
|
||||
when:
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then:
|
||||
responseHeaders == ['X-Frame-Options': 'SAMEORIGIN',
|
||||
'X-CSRF-TOKEN' : csrfToken.token]
|
||||
responseHeaders == ['X-Frame-Options': 'SAMEORIGIN']
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@@ -156,8 +151,7 @@ public class NamespaceHttpHeadersTests extends BaseSpringSpec {
|
||||
when:
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then:
|
||||
responseHeaders == ['X-Frame-Options': 'ALLOW-FROM https://example.com',
|
||||
'X-CSRF-TOKEN' : csrfToken.token]
|
||||
responseHeaders == ['X-Frame-Options': 'ALLOW-FROM https://example.com']
|
||||
}
|
||||
|
||||
|
||||
@@ -178,8 +172,7 @@ public class NamespaceHttpHeadersTests extends BaseSpringSpec {
|
||||
when:
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then:
|
||||
responseHeaders == ['X-XSS-Protection': '1; mode=block',
|
||||
'X-CSRF-TOKEN' : csrfToken.token]
|
||||
responseHeaders == ['X-XSS-Protection': '1; mode=block']
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@@ -199,8 +192,7 @@ public class NamespaceHttpHeadersTests extends BaseSpringSpec {
|
||||
when:
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then:
|
||||
responseHeaders == ['X-XSS-Protection': '1',
|
||||
'X-CSRF-TOKEN' : csrfToken.token]
|
||||
responseHeaders == ['X-XSS-Protection': '1']
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@@ -220,8 +212,7 @@ public class NamespaceHttpHeadersTests extends BaseSpringSpec {
|
||||
when:
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then:
|
||||
responseHeaders == ['X-Content-Type-Options': 'nosniff',
|
||||
'X-CSRF-TOKEN' : csrfToken.token]
|
||||
responseHeaders == ['X-Content-Type-Options': 'nosniff']
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@@ -243,8 +234,7 @@ public class NamespaceHttpHeadersTests extends BaseSpringSpec {
|
||||
when:
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then:
|
||||
responseHeaders == ['customHeaderName': 'customHeaderValue',
|
||||
'X-CSRF-TOKEN' : csrfToken.token]
|
||||
responseHeaders == ['customHeaderName': 'customHeaderValue']
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
||||
+6
-5
@@ -29,6 +29,7 @@ import org.springframework.security.web.access.AccessDeniedHandler;
|
||||
import org.springframework.security.web.csrf.CsrfFilter
|
||||
import org.springframework.security.web.csrf.CsrfToken;
|
||||
import org.springframework.security.web.csrf.CsrfTokenRepository;
|
||||
import org.springframework.security.web.csrf.DefaultCsrfToken;
|
||||
import org.springframework.security.web.servlet.support.csrf.CsrfRequestDataValueProcessor
|
||||
import org.springframework.security.web.util.RequestMatcher
|
||||
|
||||
@@ -113,7 +114,7 @@ class CsrfConfigTests extends AbstractHttpConfigTests {
|
||||
mockBean(CsrfTokenRepository,'repo')
|
||||
createAppContext()
|
||||
CsrfTokenRepository repo = appContext.getBean("repo",CsrfTokenRepository)
|
||||
CsrfToken token = new CsrfToken("X-CSRF-TOKEN","_csrf", "abc")
|
||||
CsrfToken token = new DefaultCsrfToken("X-CSRF-TOKEN","_csrf", "abc")
|
||||
when(repo.loadToken(any(HttpServletRequest))).thenReturn(token)
|
||||
request.setParameter(token.parameterName,token.token)
|
||||
request.servletPath = "/some-url"
|
||||
@@ -147,7 +148,7 @@ class CsrfConfigTests extends AbstractHttpConfigTests {
|
||||
mockBean(CsrfTokenRepository,'repo')
|
||||
createAppContext()
|
||||
CsrfTokenRepository repo = appContext.getBean("repo",CsrfTokenRepository)
|
||||
CsrfToken token = new CsrfToken("X-CSRF-TOKEN","_csrf", "abc")
|
||||
CsrfToken token = new DefaultCsrfToken("X-CSRF-TOKEN","_csrf", "abc")
|
||||
when(repo.loadToken(any(HttpServletRequest))).thenReturn(token)
|
||||
request.setParameter(token.parameterName,token.token)
|
||||
request.servletPath = "/some-url"
|
||||
@@ -200,7 +201,7 @@ class CsrfConfigTests extends AbstractHttpConfigTests {
|
||||
mockBean(CsrfTokenRepository,'repo')
|
||||
createAppContext()
|
||||
CsrfTokenRepository repo = appContext.getBean("repo",CsrfTokenRepository)
|
||||
CsrfToken token = new CsrfToken("X-CSRF-TOKEN","_csrf", "abc")
|
||||
CsrfToken token = new DefaultCsrfToken("X-CSRF-TOKEN","_csrf", "abc")
|
||||
when(repo.loadToken(any(HttpServletRequest))).thenReturn(token)
|
||||
request.setParameter(token.parameterName,token.token)
|
||||
request.method = "POST"
|
||||
@@ -223,7 +224,7 @@ class CsrfConfigTests extends AbstractHttpConfigTests {
|
||||
mockBean(CsrfTokenRepository,'repo')
|
||||
createAppContext()
|
||||
CsrfTokenRepository repo = appContext.getBean("repo",CsrfTokenRepository)
|
||||
CsrfToken token = new CsrfToken("X-CSRF-TOKEN","_csrf", "abc")
|
||||
CsrfToken token = new DefaultCsrfToken("X-CSRF-TOKEN","_csrf", "abc")
|
||||
when(repo.loadToken(any(HttpServletRequest))).thenReturn(token)
|
||||
request.setParameter(token.parameterName,token.token)
|
||||
request.method = "POST"
|
||||
@@ -244,7 +245,7 @@ class CsrfConfigTests extends AbstractHttpConfigTests {
|
||||
mockBean(CsrfTokenRepository,'repo')
|
||||
createAppContext()
|
||||
CsrfTokenRepository repo = appContext.getBean("repo",CsrfTokenRepository)
|
||||
CsrfToken token = new CsrfToken("X-CSRF-TOKEN","_csrf", "abc")
|
||||
CsrfToken token = new DefaultCsrfToken("X-CSRF-TOKEN","_csrf", "abc")
|
||||
when(repo.loadToken(any(HttpServletRequest))).thenReturn(token)
|
||||
request.setParameter(token.parameterName,token.token)
|
||||
request.method = "POST"
|
||||
|
||||
+3
-2
@@ -40,7 +40,6 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.mock.web.MockFilterChain;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
@@ -96,7 +95,9 @@ public class SessionManagementConfigurerServlet31Tests {
|
||||
request.setMethod("POST");
|
||||
request.setParameter("username", "user");
|
||||
request.setParameter("password", "password");
|
||||
CsrfToken token = new HttpSessionCsrfTokenRepository().generateAndSaveToken(request, response);
|
||||
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
|
||||
CsrfToken token = repository.generateToken(request);
|
||||
repository.saveToken(token, request, response);
|
||||
request.setParameter(token.getParameterName(),token.getToken());
|
||||
when(ReflectionUtils.findMethod(HttpServletRequest.class, "changeSessionId")).thenReturn(method);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user