Skip to content

Commit

Permalink
Editing pass
Browse files Browse the repository at this point in the history
I went through everything to get it to fit with Spring's docuemntation standard.
Lots of small changes for punctuation, grammar, usage, voice, and so on.
Also added some links, mostly to the API Javadoc.
  • Loading branch information
Jay Bryant committed Jun 4, 2021
1 parent 52b8202 commit 9219cbf
Show file tree
Hide file tree
Showing 103 changed files with 29,230 additions and 5,045 deletions.
254 changes: 254 additions & 0 deletions 0001-master-main.patch

Large diffs are not rendered by default.

271 changes: 271 additions & 0 deletions 0002-Make-Csrf-cookie-secure-flag-configurable-WebFlux.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,271 @@
From e2993d93e109c1a3c9020b7ea9efb6e556751ed4 Mon Sep 17 00:00:00 2001

This comment has been minimized.

Copy link
@sara9674
From: Thomas Vitale <[email protected]>
Date: Mon, 26 Apr 2021 18:13:20 +0200
Subject: [PATCH 2/3] Make Csrf cookie secure flag configurable (WebFlux)

Make the XSRF-TOKEN cookie secure flag configurable in CookieServerCsrfTokenRepository.

Closes gh-9678
---
.../csrf/CookieServerCsrfTokenRepository.java | 30 ++++--
.../CookieServerCsrfTokenRepositoryTests.java | 100 ++++++++++++++++--
2 files changed, 113 insertions(+), 17 deletions(-)

diff --git a/web/src/main/java/org/springframework/security/web/server/csrf/CookieServerCsrfTokenRepository.java b/web/src/main/java/org/springframework/security/web/server/csrf/CookieServerCsrfTokenRepository.java
index 5910ff3e45..bc3a20e711 100644
--- a/web/src/main/java/org/springframework/security/web/server/csrf/CookieServerCsrfTokenRepository.java
+++ b/web/src/main/java/org/springframework/security/web/server/csrf/CookieServerCsrfTokenRepository.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2019 the original author or authors.
+ * Copyright 2002-2021 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 org.springframework.web.server.ServerWebExchange;
* AngularJS. When using with AngularJS be sure to use {@link #withHttpOnlyFalse()} .
*
* @author Eric Deandrea
+ * @author Thomas Vitale
* @since 5.1
*/
public final class CookieServerCsrfTokenRepository implements ServerCsrfTokenRepository {
@@ -54,6 +55,8 @@ public final class CookieServerCsrfTokenRepository implements ServerCsrfTokenRep

private boolean cookieHttpOnly = true;

+ private Boolean secure;
+
/**
* Factory method to conveniently create an instance that has
* {@link #setCookieHttpOnly(boolean)} set to false.
@@ -75,11 +78,16 @@ public final class CookieServerCsrfTokenRepository implements ServerCsrfTokenRep
public Mono<Void> saveToken(ServerWebExchange exchange, CsrfToken token) {
return Mono.fromRunnable(() -> {
String tokenValue = (token != null) ? token.getToken() : "";
- int maxAge = !tokenValue.isEmpty() ? -1 : 0;
- String path = (this.cookiePath != null) ? this.cookiePath : getRequestContext(exchange.getRequest());
- boolean secure = exchange.getRequest().getSslInfo() != null;
- ResponseCookie cookie = ResponseCookie.from(this.cookieName, tokenValue).domain(this.cookieDomain)
- .httpOnly(this.cookieHttpOnly).maxAge(maxAge).path(path).secure(secure).build();
+ // @formatter:off
+ ResponseCookie cookie = ResponseCookie
+ .from(this.cookieName, tokenValue)
+ .domain(this.cookieDomain)
+ .httpOnly(this.cookieHttpOnly)
+ .maxAge(!tokenValue.isEmpty() ? -1 : 0)
+ .path((this.cookiePath != null) ? this.cookiePath : getRequestContext(exchange.getRequest()))
+ .secure((this.secure != null) ? this.secure : (exchange.getRequest().getSslInfo() != null))
+ .build();
+ // @formatter:on
exchange.getResponse().addCookie(cookie);
});
}
@@ -146,6 +154,16 @@ public final class CookieServerCsrfTokenRepository implements ServerCsrfTokenRep
this.cookieDomain = cookieDomain;
}

+ /**
+ * Sets the cookie secure flag. If not set, the value depends on
+ * {@link ServerHttpRequest#getSslInfo()}.
+ * @param secure The value for the secure flag
+ * @since 5.5
+ */
+ public void setSecure(boolean secure) {
+ this.secure = secure;
+ }
+
private CsrfToken createCsrfToken() {
return createCsrfToken(createNewToken());
}
diff --git a/web/src/test/java/org/springframework/security/web/server/csrf/CookieServerCsrfTokenRepositoryTests.java b/web/src/test/java/org/springframework/security/web/server/csrf/CookieServerCsrfTokenRepositoryTests.java
index d16f131920..7160337053 100644
--- a/web/src/test/java/org/springframework/security/web/server/csrf/CookieServerCsrfTokenRepositoryTests.java
+++ b/web/src/test/java/org/springframework/security/web/server/csrf/CookieServerCsrfTokenRepositoryTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2018 the original author or authors.
+ * Copyright 2002-2021 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.
@@ -16,12 +16,15 @@

package org.springframework.security.web.server.csrf;

+import java.security.cert.X509Certificate;
import java.time.Duration;

+import org.junit.Before;
import org.junit.Test;

import org.springframework.http.HttpCookie;
import org.springframework.http.ResponseCookie;
+import org.springframework.http.server.reactive.SslInfo;
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
import org.springframework.mock.web.server.MockServerWebExchange;
import org.springframework.util.StringUtils;
@@ -30,13 +33,14 @@ import static org.assertj.core.api.Assertions.assertThat;

/**
* @author Eric Deandrea
+ * @author Thomas Vitale
* @since 5.1
*/
public class CookieServerCsrfTokenRepositoryTests {

- private MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/someUri"));
+ private CookieServerCsrfTokenRepository csrfTokenRepository;

- private CookieServerCsrfTokenRepository csrfTokenRepository = new CookieServerCsrfTokenRepository();
+ private MockServerHttpRequest.BaseBuilder<?> request;

private String expectedHeaderName = CookieServerCsrfTokenRepository.DEFAULT_CSRF_HEADER_NAME;

@@ -56,6 +60,12 @@ public class CookieServerCsrfTokenRepositoryTests {

private String expectedCookieValue = "csrfToken";

+ @Before
+ public void setUp() {
+ this.csrfTokenRepository = new CookieServerCsrfTokenRepository();
+ this.request = MockServerHttpRequest.get("/someUri");
+ }
+
@Test
public void generateTokenWhenDefaultThenDefaults() {
generateTokenAndAssertExpectedValues();
@@ -82,8 +92,9 @@ public class CookieServerCsrfTokenRepositoryTests {

@Test
public void saveTokenWhenNoSubscriptionThenNotWritten() {
- this.csrfTokenRepository.saveToken(this.exchange, createToken());
- assertThat(this.exchange.getResponse().getCookies().getFirst(this.expectedCookieName)).isNull();
+ MockServerWebExchange exchange = MockServerWebExchange.from(this.request);
+ this.csrfTokenRepository.saveToken(exchange, createToken());
+ assertThat(exchange.getResponse().getCookies().getFirst(this.expectedCookieName)).isNull();
}

@Test
@@ -112,6 +123,56 @@ public class CookieServerCsrfTokenRepositoryTests {
saveAndAssertExpectedValues(createToken());
}

+ @Test
+ public void saveTokenWhenSslInfoPresentThenSecure() {
+ this.request.sslInfo(new MockSslInfo());
+ MockServerWebExchange exchange = MockServerWebExchange.from(this.request);
+ this.csrfTokenRepository.saveToken(exchange, createToken()).block();
+ ResponseCookie cookie = exchange.getResponse().getCookies().getFirst(this.expectedCookieName);
+ assertThat(cookie).isNotNull();
+ assertThat(cookie.isSecure()).isTrue();
+ }
+
+ @Test
+ public void saveTokenWhenSslInfoNullThenNotSecure() {
+ MockServerWebExchange exchange = MockServerWebExchange.from(this.request);
+ this.csrfTokenRepository.saveToken(exchange, createToken()).block();
+ ResponseCookie cookie = exchange.getResponse().getCookies().getFirst(this.expectedCookieName);
+ assertThat(cookie).isNotNull();
+ assertThat(cookie.isSecure()).isFalse();
+ }
+
+ @Test
+ public void saveTokenWhenSecureFlagTrueThenSecure() {
+ MockServerWebExchange exchange = MockServerWebExchange.from(this.request);
+ this.csrfTokenRepository.setSecure(true);
+ this.csrfTokenRepository.saveToken(exchange, createToken()).block();
+ ResponseCookie cookie = exchange.getResponse().getCookies().getFirst(this.expectedCookieName);
+ assertThat(cookie).isNotNull();
+ assertThat(cookie.isSecure()).isTrue();
+ }
+
+ @Test
+ public void saveTokenWhenSecureFlagFalseThenNotSecure() {
+ MockServerWebExchange exchange = MockServerWebExchange.from(this.request);
+ this.csrfTokenRepository.setSecure(false);
+ this.csrfTokenRepository.saveToken(exchange, createToken()).block();
+ ResponseCookie cookie = exchange.getResponse().getCookies().getFirst(this.expectedCookieName);
+ assertThat(cookie).isNotNull();
+ assertThat(cookie.isSecure()).isFalse();
+ }
+
+ @Test
+ public void saveTokenWhenSecureFlagFalseAndSslInfoThenNotSecure() {
+ MockServerWebExchange exchange = MockServerWebExchange.from(this.request);
+ this.request.sslInfo(new MockSslInfo());
+ this.csrfTokenRepository.setSecure(false);
+ this.csrfTokenRepository.saveToken(exchange, createToken()).block();
+ ResponseCookie cookie = exchange.getResponse().getCookies().getFirst(this.expectedCookieName);
+ assertThat(cookie).isNotNull();
+ assertThat(cookie.isSecure()).isFalse();
+ }
+
@Test
public void loadTokenWhenCookieExistThenTokenFound() {
loadAndAssertExpectedValues();
@@ -127,7 +188,8 @@ public class CookieServerCsrfTokenRepositoryTests {

@Test
public void loadTokenWhenNoCookiesThenNullToken() {
- CsrfToken csrfToken = this.csrfTokenRepository.loadToken(this.exchange).block();
+ MockServerWebExchange exchange = MockServerWebExchange.from(this.request);
+ CsrfToken csrfToken = this.csrfTokenRepository.loadToken(exchange).block();
assertThat(csrfToken).isNull();
}

@@ -180,8 +242,8 @@ public class CookieServerCsrfTokenRepositoryTests {
private void loadAndAssertExpectedValues() {
MockServerHttpRequest.BodyBuilder request = MockServerHttpRequest.post("/someUri")
.cookie(new HttpCookie(this.expectedCookieName, this.expectedCookieValue));
- this.exchange = MockServerWebExchange.from(request);
- CsrfToken csrfToken = this.csrfTokenRepository.loadToken(this.exchange).block();
+ MockServerWebExchange exchange = MockServerWebExchange.from(request);
+ CsrfToken csrfToken = this.csrfTokenRepository.loadToken(exchange).block();
if (StringUtils.hasText(this.expectedCookieValue)) {
assertThat(csrfToken).isNotNull();
assertThat(csrfToken.getHeaderName()).isEqualTo(this.expectedHeaderName);
@@ -198,8 +260,9 @@ public class CookieServerCsrfTokenRepositoryTests {
this.expectedMaxAge = Duration.ofSeconds(0);
this.expectedCookieValue = "";
}
- this.csrfTokenRepository.saveToken(this.exchange, token).block();
- ResponseCookie cookie = this.exchange.getResponse().getCookies().getFirst(this.expectedCookieName);
+ MockServerWebExchange exchange = MockServerWebExchange.from(this.request);
+ this.csrfTokenRepository.saveToken(exchange, token).block();
+ ResponseCookie cookie = exchange.getResponse().getCookies().getFirst(this.expectedCookieName);
assertThat(cookie).isNotNull();
assertThat(cookie.getMaxAge()).isEqualTo(this.expectedMaxAge);
assertThat(cookie.getDomain()).isEqualTo(this.expectedDomain);
@@ -211,7 +274,8 @@ public class CookieServerCsrfTokenRepositoryTests {
}

private void generateTokenAndAssertExpectedValues() {
- CsrfToken csrfToken = this.csrfTokenRepository.generateToken(this.exchange).block();
+ MockServerWebExchange exchange = MockServerWebExchange.from(this.request);
+ CsrfToken csrfToken = this.csrfTokenRepository.generateToken(exchange).block();
assertThat(csrfToken).isNotNull();
assertThat(csrfToken.getHeaderName()).isEqualTo(this.expectedHeaderName);
assertThat(csrfToken.getParameterName()).isEqualTo(this.expectedParameterName);
@@ -226,4 +290,18 @@ public class CookieServerCsrfTokenRepositoryTests {
return new DefaultCsrfToken(headerName, parameterName, tokenValue);
}

+ static class MockSslInfo implements SslInfo {
+
+ @Override
+ public String getSessionId() {
+ return "sessionId";
+ }
+
+ @Override
+ public X509Certificate[] getPeerCertificates() {
+ return new X509Certificate[] {};
+ }
+
+ }
+
}
--
2.24.1

Loading

0 comments on commit 9219cbf

Please sign in to comment.