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();