Skip to content

CsrfAuthenticationStrategy does not regenerate CsrfToken with CookieCsrfTokenRepository #12141

@sjohnr

Description

@sjohnr

Describe the bug
Using the new DeferredCsrfToken, CsrfAuthenticationStrategy does not regenerate CsrfToken with CookieCsrfTokenRepository within the same request. A null token cookie is added, but it does not generate a new one.

Note: In 6.0, eagerly loading the token is no longer the default, and requires accessing the request attribute (request.getAttribute(CsrfToken.class.getName())) manually as in the AuthenticationSuccessHandler below. Related gh-12094.

To Reproduce
See sample.

  1. Navigate to http://localhost:8080 in the browser and log in with user:password.
  2. Observe that POST /login contains the same token in request and response.
POST /login HTTP/1.1
Host: localhost:8080
...
Cookie: JSESSIONID=EAA9296337F0588BC18C9C1BC0F8DBA1; XSRF-TOKEN=f1f89231-50e7-4eed-a15d-45c184c34e56
HTTP/1.1 200 
Set-Cookie: JSESSIONID=5528D2BC31D24431AF4F5A1D61AB0F1A; Path=/; HttpOnly
Set-Cookie: XSRF-TOKEN=; Max-Age=0; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/
X-XSRF-TOKEN: f1f89231-50e7-4eed-a15d-45c184c34e56
...

Expected behavior
When eagerly regenerating the CsrfToken, the cookie (and header in this example) should reflect the updated token after a successful login.

Sample

Spring Security Version: 5.8.0-RC1

@SpringBootApplication
public class DemoApplication {

	public static void main(String[] args) {
		SpringApplication.run(DemoApplication.class, args);
	}

}
@Configuration
@EnableWebSecurity
public class SecurityConfig {

	@Bean
	public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
		// @formatter:off
		http
			.authorizeHttpRequests((authorize) -> authorize
				.anyRequest().authenticated()
			)
			.csrf((csrf) -> csrf
				.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
			)
			.formLogin((formLogin) -> formLogin
				.successHandler((request, response, authentication) -> {
					CsrfToken csrfToken = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
					response.setHeader(csrfToken.getHeaderName(), csrfToken.getToken());
				})
			);
		// @formatter:on
		return http.build();
	}

	@Bean 
	public UserDetailsService userDetailsService() {
		// @formatter:off
		UserDetails userDetails = User.withDefaultPasswordEncoder()
				.username("user")
				.password("password")
				.roles("USER")
				.build();
		// @formatter:on
		return new InMemoryUserDetailsManager(userDetails);
	}

}

Metadata

Metadata

Assignees

Labels

in: webAn issue in web modules (web, webmvc)type: bugA general bug

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions