From d4218c70f1a794f3550c258bc2cb42e269b6fb17 Mon Sep 17 00:00:00 2001 From: Rob Winch Date: Thu, 5 May 2016 12:48:16 -0500 Subject: [PATCH] Update CookieCsrfTokenRepository docs to cookiHttpOnly=false Currently CookieCsrfTokenRepository does not specify that the httpOnly flag needs set to false. We should update the reference to include this setting (and a comment about it) since it states that the settings will work with AngularJS. This commit updates the documentation and provides a convenience factory method to create a CookieCsrfTokenRepository with cookiHttpOnly=false Fixes gh-3865 --- docs/manual/src/docs/asciidoc/index.adoc | 27 +++++++++++++++---- .../web/csrf/CookieCsrfTokenRepository.java | 15 ++++++++++- .../csrf/CookieCsrfTokenRepositoryTests.java | 12 +++++++++ 3 files changed, 48 insertions(+), 6 deletions(-) diff --git a/docs/manual/src/docs/asciidoc/index.adoc b/docs/manual/src/docs/asciidoc/index.adoc index 8409cb636d..4d8f5b393e 100644 --- a/docs/manual/src/docs/asciidoc/index.adoc +++ b/docs/manual/src/docs/asciidoc/index.adoc @@ -3359,9 +3359,19 @@ You can configure `CookieCsrfTokenRepository` in XML using the following: - + ---- +[NOTE] +==== +The sample explicitly sets `cookieHttpOnly=false`. +This is necessary to allow JavaScript (i.e. AngularJS) to read it. +If you do not need the ability to read the cookie with JavaScript directly, it is recommended to omit `cookieHttpOnly=false` to improve security. +==== + + You can configure `CookieCsrfTokenRepository` in Java Configuration using: [source,java] @@ -3374,11 +3384,18 @@ public class WebSecurityConfig extends protected void configure(HttpSecurity http) throws Exception { http .csrf() - .csrfTokenRepository(new CookieCsrfTokenRepository()); + .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()); } } ---- +[NOTE] +==== +The sample explicitly sets `cookieHttpOnly=false`. +This is necessary to allow JavaScript (i.e. AngularJS) to read it. +If you do not need the ability to read the cookie with JavaScript directly, it is recommended to omit `cookieHttpOnly=false` (by using `new CookieCsrfTokenRepository()` instead) to improve security. +==== + [[csrf-caveats]] === CSRF Caveats @@ -6594,9 +6611,9 @@ Spring Security provides `AuthenticationPrincipalArgumentResolver` which can aut [source,xml] ---- - - - + + + ---- diff --git a/web/src/main/java/org/springframework/security/web/csrf/CookieCsrfTokenRepository.java b/web/src/main/java/org/springframework/security/web/csrf/CookieCsrfTokenRepository.java index 9b6f90b599..c275247c72 100644 --- a/web/src/main/java/org/springframework/security/web/csrf/CookieCsrfTokenRepository.java +++ b/web/src/main/java/org/springframework/security/web/csrf/CookieCsrfTokenRepository.java @@ -31,7 +31,7 @@ import org.springframework.web.util.WebUtils; /** * A {@link CsrfTokenRepository} that persist the CSRF token in a cookie named * "XSRF-TOKEN" and reads from the header "X-XSRF-TOKEN" following the conventions of - * AngularJS. + * AngularJS. When using with AngularJS be sure to use {@link #withHttpOnlyFalse()}. * * @author Rob Winch * @since 4.1 @@ -153,6 +153,19 @@ public final class CookieCsrfTokenRepository implements CsrfTokenRepository { return contextPath.length() > 0 ? contextPath : "/"; } + /** + * Factory method to conveniently create an instance that has + * {@link #setCookieHttpOnly(boolean)} set to false. + * + * @return and instance of CookieCsrfTokenRepository with + * {@link #setCookieHttpOnly(boolean)} set to false + */ + public static CookieCsrfTokenRepository withHttpOnlyFalse() { + CookieCsrfTokenRepository result = new CookieCsrfTokenRepository(); + result.setCookieHttpOnly(false); + return result; + } + private String createNewToken() { return UUID.randomUUID().toString(); } diff --git a/web/src/test/java/org/springframework/security/web/csrf/CookieCsrfTokenRepositoryTests.java b/web/src/test/java/org/springframework/security/web/csrf/CookieCsrfTokenRepositoryTests.java index 9ffad55485..6a19774fda 100644 --- a/web/src/test/java/org/springframework/security/web/csrf/CookieCsrfTokenRepositoryTests.java +++ b/web/src/test/java/org/springframework/security/web/csrf/CookieCsrfTokenRepositoryTests.java @@ -138,6 +138,18 @@ public class CookieCsrfTokenRepositoryTests { assertThat(tokenCookie.isHttpOnly()).isFalse(); } + @Test + public void saveTokenWithHttpOnlyFalse() { + this.repository = CookieCsrfTokenRepository.withHttpOnlyFalse(); + 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.isHttpOnly()).isFalse(); + } + @Test public void loadTokenNoCookiesNull() { assertThat(this.repository.loadToken(this.request)).isNull();