issue 5414 - configurable secure flag in CookieCsrfTokenRepository

While using the request's "isSecure" flag is a reasonable default, when webapps sit behind firewalls, sometimes the firewall does the SSL, and the traffic between the firewall and the app is plain HTTP (not HTTPS). In this case the "isSecure" flag on the request is always false, but we still want th XSRF-TOKEN cookie to be secure (the firewall forwards all cookies to the app, and the browser sends the secure cookie to the firewall).

It would be nice if we could configure the desired value for the secure flag of the cookie, just like we can configure the value for the httpOnly flag of the cookie.
This commit is contained in:
michal 2020-06-22 22:29:14 +02:00 committed by Rob Winch
parent 565fd28d08
commit e113bd3c01
2 changed files with 49 additions and 1 deletions

View File

@ -18,6 +18,7 @@ package org.springframework.security.web.csrf;
import java.util.UUID;
import javax.servlet.ServletRequest;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -53,6 +54,8 @@ public final class CookieCsrfTokenRepository implements CsrfTokenRepository {
private String cookieDomain;
private Boolean secure;
public CookieCsrfTokenRepository() {
}
@ -67,7 +70,12 @@ public final class CookieCsrfTokenRepository implements CsrfTokenRepository {
HttpServletResponse response) {
String tokenValue = token == null ? "" : token.getToken();
Cookie cookie = new Cookie(this.cookieName, tokenValue);
cookie.setSecure(request.isSecure());
if (secure == null) {
cookie.setSecure(request.isSecure());
} else {
cookie.setSecure(secure);
}
if (this.cookiePath != null && !this.cookiePath.isEmpty()) {
cookie.setPath(this.cookiePath);
} else {
@ -195,4 +203,17 @@ public final class CookieCsrfTokenRepository implements CsrfTokenRepository {
this.cookieDomain = cookieDomain;
}
/**
* Sets secure flag of the cookie that the expected CSRF token is saved to and read from.
* By default secure flag depends on {@link ServletRequest#isSecure()}
*
* @since 5.4
* @param secure the secure flag of the cookie that the expected CSRF token is saved to
* and read from
*/
public void setSecure(Boolean secure) {
this.secure = secure;
}
}

View File

@ -98,6 +98,33 @@ public class CookieCsrfTokenRepositoryTests {
assertThat(tokenCookie.getSecure()).isTrue();
}
@Test
public void saveTokenSecureFlagTrue() {
this.request.setSecure(false);
this.repository.setSecure(Boolean.TRUE);
CsrfToken token = this.repository.generateToken(this.request);
this.repository.saveToken(token, this.request, this.response);
Cookie tokenCookie = this.response
.getCookie(CookieCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME);
assertThat(tokenCookie.getSecure()).isTrue();
}
@Test
public void saveTokenSecureFlagFalse() {
this.request.setSecure(true);
this.repository.setSecure(Boolean.FALSE);
CsrfToken token = this.repository.generateToken(this.request);
this.repository.saveToken(token, this.request, this.response);
Cookie tokenCookie = this.response
.getCookie(CookieCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME);
assertThat(tokenCookie.getSecure()).isFalse();
}
@Test
public void saveTokenNull() {
this.request.setSecure(true);