Browse Source

Adds the ability to set the CSRF Token cookie max age value

Closes gh-11432
Alonso Araya Calvo 3 years ago
parent
commit
7841827169

+ 31 - 2
web/src/main/java/org/springframework/security/web/server/csrf/CookieServerCsrfTokenRepository.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2021 the original author or authors.
+ * Copyright 2002-2022 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -35,6 +35,7 @@ import org.springframework.web.server.ServerWebExchange;
  *
  * @author Eric Deandrea
  * @author Thomas Vitale
+ * @author Alonso Araya
  * @since 5.1
  */
 public final class CookieServerCsrfTokenRepository implements ServerCsrfTokenRepository {
@@ -57,6 +58,8 @@ public final class CookieServerCsrfTokenRepository implements ServerCsrfTokenRep
 
 	private Boolean secure;
 
+	private int cookieMaxAge = -1;
+
 	/**
 	 * Factory method to conveniently create an instance that has
 	 * {@link #setCookieHttpOnly(boolean)} set to false.
@@ -83,7 +86,7 @@ public final class CookieServerCsrfTokenRepository implements ServerCsrfTokenRep
 					.from(this.cookieName, tokenValue)
 					.domain(this.cookieDomain)
 					.httpOnly(this.cookieHttpOnly)
-					.maxAge(!tokenValue.isEmpty() ? -1 : 0)
+					.maxAge(!tokenValue.isEmpty() ? this.cookieMaxAge : 0)
 					.path((this.cookiePath != null) ? this.cookiePath : getRequestContext(exchange.getRequest()))
 					.secure((this.secure != null) ? this.secure : (exchange.getRequest().getSslInfo() != null))
 					.build();
@@ -164,6 +167,32 @@ public final class CookieServerCsrfTokenRepository implements ServerCsrfTokenRep
 		this.secure = secure;
 	}
 
+	/**
+	 * Sets maximum age in seconds for the cookie that the expected CSRF token is saved to
+	 * and read from. By default maximum age value is -1.
+	 *
+	 * <p>
+	 * A positive value indicates that the cookie will expire after that many seconds have
+	 * passed. Note that the value is the <i>maximum</i> age when the cookie will expire,
+	 * not the cookie's current age.
+	 *
+	 * <p>
+	 * A negative value means that the cookie is not stored persistently and will be
+	 * deleted when the Web browser exits.
+	 *
+	 * <p>
+	 * A zero value causes the cookie to be deleted immediately therefore it is not a
+	 * valid value and in that case an {@link IllegalArgumentException} will be thrown.
+	 * @param cookieMaxAge an integer specifying the maximum age of the cookie in seconds;
+	 * if negative, means the cookie is not stored; if zero, the method throws an
+	 * {@link IllegalArgumentException}
+	 * @since 5.8
+	 */
+	public void setCookieMaxAge(int cookieMaxAge) {
+		Assert.isTrue(cookieMaxAge != 0, "cookieMaxAge cannot be zero");
+		this.cookieMaxAge = cookieMaxAge;
+	}
+
 	private CsrfToken createCsrfToken() {
 		return createCsrfToken(createNewToken());
 	}

+ 14 - 1
web/src/test/java/org/springframework/security/web/server/csrf/CookieServerCsrfTokenRepositoryTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2021 the original author or authors.
+ * Copyright 2002-2022 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -34,6 +34,7 @@ import static org.assertj.core.api.Assertions.assertThat;
 /**
  * @author Eric Deandrea
  * @author Thomas Vitale
+ * @author Alonso Araya
  * @since 5.1
  */
 public class CookieServerCsrfTokenRepositoryTests {
@@ -113,6 +114,12 @@ public class CookieServerCsrfTokenRepositoryTests {
 		saveAndAssertExpectedValues(createToken());
 	}
 
+	@Test
+	public void saveTokenWhenCookieMaxAgeThenCookieMaxAge() {
+		setExpectedCookieMaxAge(3600);
+		saveAndAssertExpectedValues(createToken());
+	}
+
 	@Test
 	public void saveTokenWhenCustomPropertiesThenCustomProperties() {
 		setExpectedDomain("spring.io");
@@ -120,6 +127,7 @@ public class CookieServerCsrfTokenRepositoryTests {
 		setExpectedPath("/some/path");
 		setExpectedHeaderName("headerName");
 		setExpectedParameterName("paramName");
+		setExpectedCookieMaxAge(3600);
 		saveAndAssertExpectedValues(createToken());
 	}
 
@@ -235,6 +243,11 @@ public class CookieServerCsrfTokenRepositoryTests {
 		this.csrfTokenRepository.setCookieName(expectedCookieName);
 	}
 
+	private void setExpectedCookieMaxAge(int expectedCookieMaxAge) {
+		this.csrfTokenRepository.setCookieMaxAge(expectedCookieMaxAge);
+		this.expectedMaxAge = Duration.ofSeconds(expectedCookieMaxAge);
+	}
+
 	private void setExpectedCookieValue(String expectedCookieValue) {
 		this.expectedCookieValue = expectedCookieValue;
 	}