Skip to content

Commit ea6ce05

Browse files
author
Steve Riesenberg
committed
Add configurer tests for CookieCsrfTokenRepository
Issue gh-12236
1 parent 2ed7cff commit ea6ce05

File tree

1 file changed

+121
-0
lines changed

1 file changed

+121
-0
lines changed

config/src/test/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerTests.java

+121
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@
1717
package org.springframework.security.config.annotation.web.configurers;
1818

1919
import java.net.URI;
20+
import java.util.Arrays;
21+
import java.util.List;
2022

23+
import javax.servlet.http.Cookie;
2124
import javax.servlet.http.HttpServletRequest;
2225
import javax.servlet.http.HttpServletResponse;
2326

@@ -28,6 +31,7 @@
2831
import org.springframework.beans.factory.annotation.Autowired;
2932
import org.springframework.context.annotation.Bean;
3033
import org.springframework.context.annotation.Configuration;
34+
import org.springframework.http.HttpHeaders;
3135
import org.springframework.http.HttpMethod;
3236
import org.springframework.mock.web.MockHttpSession;
3337
import org.springframework.security.config.Customizer;
@@ -42,6 +46,7 @@
4246
import org.springframework.security.web.SecurityFilterChain;
4347
import org.springframework.security.web.access.AccessDeniedHandler;
4448
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
49+
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
4550
import org.springframework.security.web.csrf.CsrfToken;
4651
import org.springframework.security.web.csrf.CsrfTokenRepository;
4752
import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler;
@@ -509,6 +514,86 @@ public void loginWhenXorCsrfTokenRequestAttributeHandlerSetAndMaskedCsrfTokenThe
509514
verifyNoMoreInteractions(csrfTokenRepository);
510515
}
511516

517+
@Test
518+
public void loginWhenFormLoginAndCookieCsrfTokenRepositorySetAndExistingTokenThenRemovesAndGeneratesNewToken()
519+
throws Exception {
520+
CsrfToken csrfToken = new DefaultCsrfToken("X-XSRF-TOKEN", "_csrf", "token");
521+
Cookie existingCookie = new Cookie("XSRF-TOKEN", csrfToken.getToken());
522+
CookieCsrfTokenRepository csrfTokenRepository = CookieCsrfTokenRepository.withHttpOnlyFalse();
523+
csrfTokenRepository.setCookieName(existingCookie.getName());
524+
CsrfTokenRequestHandlerConfig.REPO = csrfTokenRepository;
525+
CsrfTokenRequestHandlerConfig.HANDLER = new CsrfTokenRequestAttributeHandler();
526+
this.spring.register(CsrfTokenRequestHandlerConfig.class, BasicController.class).autowire();
527+
528+
// @formatter:off
529+
MockHttpServletRequestBuilder loginRequest = post("/login")
530+
.cookie(existingCookie)
531+
.header(csrfToken.getHeaderName(), csrfToken.getToken())
532+
.param("username", "user")
533+
.param("password", "password");
534+
// @formatter:on
535+
MvcResult mvcResult = this.mvc.perform(loginRequest).andExpect(redirectedUrl("/")).andReturn();
536+
List<Cookie> cookies = Arrays.asList(mvcResult.getResponse().getCookies());
537+
cookies.removeIf((cookie) -> !cookie.getName().equalsIgnoreCase(existingCookie.getName()));
538+
assertThat(cookies).hasSize(2);
539+
assertThat(cookies.get(0).getValue()).isEmpty();
540+
assertThat(cookies.get(1).getValue()).isNotEmpty();
541+
}
542+
543+
@Test
544+
public void postWhenHttpBasicAndCookieCsrfTokenRepositorySetAndExistingTokenThenRemovesAndGeneratesNewToken()
545+
throws Exception {
546+
CsrfToken csrfToken = new DefaultCsrfToken("X-XSRF-TOKEN", "_csrf", "token");
547+
Cookie existingCookie = new Cookie("XSRF-TOKEN", csrfToken.getToken());
548+
CookieCsrfTokenRepository csrfTokenRepository = CookieCsrfTokenRepository.withHttpOnlyFalse();
549+
csrfTokenRepository.setCookieName(existingCookie.getName());
550+
HttpBasicCsrfTokenRequestHandlerConfig.REPO = csrfTokenRepository;
551+
HttpBasicCsrfTokenRequestHandlerConfig.HANDLER = new CsrfTokenRequestAttributeHandler();
552+
this.spring.register(HttpBasicCsrfTokenRequestHandlerConfig.class, BasicController.class).autowire();
553+
554+
HttpHeaders headers = new HttpHeaders();
555+
headers.set(csrfToken.getHeaderName(), csrfToken.getToken());
556+
headers.setBasicAuth("user", "password");
557+
// @formatter:off
558+
MvcResult mvcResult = this.mvc.perform(post("/")
559+
.cookie(existingCookie)
560+
.headers(headers))
561+
.andExpect(status().isOk())
562+
.andReturn();
563+
// @formatter:on
564+
List<Cookie> cookies = Arrays.asList(mvcResult.getResponse().getCookies());
565+
cookies.removeIf((cookie) -> !cookie.getName().equalsIgnoreCase(existingCookie.getName()));
566+
assertThat(cookies).hasSize(2);
567+
assertThat(cookies.get(0).getValue()).isEmpty();
568+
assertThat(cookies.get(1).getValue()).isNotEmpty();
569+
}
570+
571+
@Test
572+
public void getWhenHttpBasicAndCookieCsrfTokenRepositorySetAndNoExistingCookieThenGeneratesNewToken()
573+
throws Exception {
574+
CsrfToken csrfToken = new DefaultCsrfToken("X-XSRF-TOKEN", "_csrf", "token");
575+
Cookie expectedCookie = new Cookie("XSRF-TOKEN", csrfToken.getToken());
576+
CookieCsrfTokenRepository csrfTokenRepository = CookieCsrfTokenRepository.withHttpOnlyFalse();
577+
csrfTokenRepository.setCookieName(expectedCookie.getName());
578+
HttpBasicCsrfTokenRequestHandlerConfig.REPO = csrfTokenRepository;
579+
HttpBasicCsrfTokenRequestHandlerConfig.HANDLER = new CsrfTokenRequestAttributeHandler();
580+
this.spring.register(HttpBasicCsrfTokenRequestHandlerConfig.class, BasicController.class).autowire();
581+
582+
HttpHeaders headers = new HttpHeaders();
583+
headers.set(csrfToken.getHeaderName(), csrfToken.getToken());
584+
headers.setBasicAuth("user", "password");
585+
// @formatter:off
586+
MvcResult mvcResult = this.mvc.perform(get("/")
587+
.headers(headers))
588+
.andExpect(status().isOk())
589+
.andReturn();
590+
// @formatter:on
591+
List<Cookie> cookies = Arrays.asList(mvcResult.getResponse().getCookies());
592+
cookies.removeIf((cookie) -> !cookie.getName().equalsIgnoreCase(expectedCookie.getName()));
593+
assertThat(cookies).hasSize(1);
594+
assertThat(cookies.get(0).getValue()).isNotEmpty();
595+
}
596+
512597
@Configuration
513598
static class AllowHttpMethodsFirewallConfig {
514599

@@ -886,6 +971,42 @@ void configure(AuthenticationManagerBuilder auth) throws Exception {
886971

887972
}
888973

974+
@Configuration
975+
@EnableWebSecurity
976+
static class HttpBasicCsrfTokenRequestHandlerConfig {
977+
978+
static CsrfTokenRepository REPO;
979+
980+
static CsrfTokenRequestHandler HANDLER;
981+
982+
@Bean
983+
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
984+
// @formatter:off
985+
http
986+
.authorizeHttpRequests((authorize) -> authorize
987+
.anyRequest().authenticated()
988+
)
989+
.httpBasic(Customizer.withDefaults())
990+
.csrf((csrf) -> csrf
991+
.csrfTokenRepository(REPO)
992+
.csrfTokenRequestHandler(HANDLER)
993+
);
994+
// @formatter:on
995+
996+
return http.build();
997+
}
998+
999+
@Autowired
1000+
void configure(AuthenticationManagerBuilder auth) throws Exception {
1001+
// @formatter:off
1002+
auth
1003+
.inMemoryAuthentication()
1004+
.withUser(PasswordEncodedUser.user());
1005+
// @formatter:on
1006+
}
1007+
1008+
}
1009+
8891010
@RestController
8901011
static class BasicController {
8911012

0 commit comments

Comments
 (0)