Merge branch 'stable-3.8'
* stable-3.8:
Avoid using 'objectUnderTest' term in GitHubOAuthConfigTest
Honour the cookieDomain also for the OAuth scope selection
Revert "Build OAuth redirect URL when X-Forwarded-Host is present"
Build OAuth redirect URL when X-Forwarded-Host is present
Fix HTTP session leaks during OAuth reauthentication
Stop filtering Gerrti's static resources with OAuthFilter
Change-Id: I263195c4ced7e83bc2d62ae25543a098995706ae
diff --git a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/GitHubLogin.java b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/GitHubLogin.java
index 1aed6cf..f65ad02 100644
--- a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/GitHubLogin.java
+++ b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/GitHubLogin.java
@@ -158,6 +158,7 @@
Cookie scopeCookie = new Cookie("scope", scopeRequested);
scopeCookie.setPath("/");
scopeCookie.setMaxAge((int) SCOPE_COOKIE_NEVER_EXPIRES);
+ config.getCookieDomain().ifPresent(scopeCookie::setDomain);
response.addCookie(scopeCookie);
}
diff --git a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/GitHubOAuthConfig.java b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/GitHubOAuthConfig.java
index 7ef81d1..d86feda 100644
--- a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/GitHubOAuthConfig.java
+++ b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/GitHubOAuthConfig.java
@@ -34,6 +34,7 @@
import java.util.Comparator;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -78,6 +79,7 @@
public final long httpReadTimeout;
private final Map<String, KeyConfig> keyConfigMap;
private final KeyConfig currentKeyConfig;
+ private final Optional<String> cookieDomain;
@Inject
protected GitHubOAuthConfig(@GerritServerConfig Config config, CanonicalWebUrl canonicalWebUrl) {
@@ -110,6 +112,7 @@
logoutRedirectUrl = config.getString(CONF_SECTION, null, "logoutRedirectUrl");
enabled = config.getString("auth", null, "type").equalsIgnoreCase(AuthType.HTTP.toString());
+ cookieDomain = Optional.ofNullable(config.getString("auth", null, "cookieDomain"));
scopes = getScopes(config);
sortedScopesKeys =
scopes.keySet().stream()
@@ -207,6 +210,10 @@
return keyConfigMap.get(subsection);
}
+ public Optional<String> getCookieDomain() {
+ return cookieDomain;
+ }
+
public class KeyConfig {
public static final int PASSWORD_LENGTH_DEFAULT = 16;
diff --git a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/HttpSessionProvider.java b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/HttpSessionProvider.java
index fdde648..da840bf 100644
--- a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/HttpSessionProvider.java
+++ b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/HttpSessionProvider.java
@@ -13,12 +13,16 @@
// limitations under the License.
package com.googlesource.gerrit.plugins.github.oauth;
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
import com.google.inject.Inject;
import com.google.inject.Provider;
+import java.util.Optional;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
public abstract class HttpSessionProvider<T> implements ScopedProvider<T> {
+ private final Supplier<String> singletonKey = Suppliers.memoize(() -> getClass().getName());
@Inject private Provider<T> provider;
@@ -32,19 +36,23 @@
@Override
public T get(final HttpServletRequest req) {
HttpSession session = req.getSession();
- String singletonKey = getClass().getName();
synchronized (this) {
@SuppressWarnings("unchecked")
- T instance = (T) session.getAttribute(singletonKey);
+ T instance = (T) session.getAttribute(singletonKey.get());
if (instance == null) {
instance = provider.get();
- session.setAttribute(singletonKey, instance);
+ session.setAttribute(singletonKey.get(), instance);
}
return instance;
}
}
+ public void clear(final HttpServletRequest req) {
+ Optional.ofNullable(req.getSession(false))
+ .ifPresent((s) -> s.removeAttribute(singletonKey.get()));
+ }
+
@Override
public HttpServletRequest getScopedRequest() {
return httpRequestProvider.get();
diff --git a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/OAuthFilter.java b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/OAuthFilter.java
index 425755f..b15c8e5 100644
--- a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/OAuthFilter.java
+++ b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/OAuthFilter.java
@@ -37,7 +37,9 @@
private static final org.slf4j.Logger log = LoggerFactory.getLogger(OAuthFilter.class);
private static Pattern GIT_HTTP_REQUEST_PATTERN = Pattern.compile(GitOverHttpServlet.URL_REGEX);
private static final Set<String> GERRIT_STATIC_RESOURCES_EXTS =
- Sets.newHashSet("css", "png", "jpg", "gif", "woff", "otf", "ttf", "map", "js", "swf", "txt");
+ Sets.newHashSet(
+ "css", "gif", "ico", "jpeg", "jpg", "js", "map", "otf", "pdf", "png", "rtf", "svg", "swf",
+ "text", "tif", "tiff", "ttf", "txt", "woff", "woff2");
private static final Set<String> GERRIT_ALLOWED_PATHS = Sets.newHashSet("Documentation");
private static final Set<String> GERRIT_ALLOWED_PAGES = Sets.newHashSet("scope.html");
diff --git a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/OAuthWebFilter.java b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/OAuthWebFilter.java
index 3c72141..0bca570 100644
--- a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/OAuthWebFilter.java
+++ b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/OAuthWebFilter.java
@@ -104,7 +104,7 @@
chain.doFilter(httpRequest, httpResponse);
}
} finally {
- HttpSession httpSession = httpRequest.getSession();
+ HttpSession httpSession = httpRequest.getSession(false);
if (gerritCookie != null && httpSession != null) {
String gerritCookieValue = gerritCookie.getValue();
String gerritSessionValue = (String) httpSession.getAttribute("GerritAccount");
@@ -112,7 +112,8 @@
if (gerritSessionValue == null) {
httpSession.setAttribute("GerritAccount", gerritCookieValue);
} else if (!gerritSessionValue.equals(gerritCookieValue)) {
- httpSession.invalidate();
+ httpSession.setAttribute("GerritAccount", null);
+ loginProvider.clear(httpRequest);
}
}
}
diff --git a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/ScopedProvider.java b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/ScopedProvider.java
index 9c68dde..307a93b 100644
--- a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/ScopedProvider.java
+++ b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/ScopedProvider.java
@@ -19,5 +19,7 @@
public interface ScopedProvider<T> extends Provider<T> {
T get(HttpServletRequest request);
+ void clear(HttpServletRequest request);
+
HttpServletRequest getScopedRequest();
}
diff --git a/github-oauth/src/test/java/com/googlesource/gerrit/plugins/github/oauth/GitHubOAuthConfigTest.java b/github-oauth/src/test/java/com/googlesource/gerrit/plugins/github/oauth/GitHubOAuthConfigTest.java
index a5bf767..9f90c56 100644
--- a/github-oauth/src/test/java/com/googlesource/gerrit/plugins/github/oauth/GitHubOAuthConfigTest.java
+++ b/github-oauth/src/test/java/com/googlesource/gerrit/plugins/github/oauth/GitHubOAuthConfigTest.java
@@ -28,6 +28,7 @@
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.util.Providers;
+import java.util.Optional;
import org.eclipse.jgit.lib.Config;
import org.junit.Before;
import org.junit.Test;
@@ -70,12 +71,10 @@
config.setString(CONF_KEY_SECTION, keySubsection, CIPHER_ALGO_CONFIG_LABEL, cipherAlgorithm);
config.setString(CONF_KEY_SECTION, keySubsection, SECRET_KEY_CONFIG_LABEL, secretKeyAlgorithm);
- GitHubOAuthConfig objectUnderTest = objectUnderTest();
-
- assertEquals(objectUnderTest.getCurrentKeyConfig().isCurrent(), true);
- assertEquals(objectUnderTest.getCurrentKeyConfig().getCipherAlgorithm(), cipherAlgorithm);
- assertEquals(objectUnderTest.getCurrentKeyConfig().getSecretKeyAlgorithm(), secretKeyAlgorithm);
- assertEquals(objectUnderTest.getCurrentKeyConfig().getKeyId(), keySubsection);
+ assertEquals(githubOAuthConfig().getCurrentKeyConfig().isCurrent(), true);
+ assertEquals(githubOAuthConfig().getCurrentKeyConfig().getCipherAlgorithm(), cipherAlgorithm);
+ assertEquals(githubOAuthConfig().getCurrentKeyConfig().getSecretKeyAlgorithm(), secretKeyAlgorithm);
+ assertEquals(githubOAuthConfig().getCurrentKeyConfig().getKeyId(), keySubsection);
}
@Test
@@ -89,7 +88,7 @@
config.setString(
CONF_KEY_SECTION, someOtherKeyConfig, PASSWORD_DEVICE_CONFIG_LABEL, testPasswordDevice);
- assertEquals(objectUnderTest().getCurrentKeyConfig().getKeyId(), currentKeyConfig);
+ assertEquals(githubOAuthConfig().getCurrentKeyConfig().getKeyId(), currentKeyConfig);
}
@Test
@@ -103,16 +102,14 @@
config.setString(
CONF_KEY_SECTION, someOtherKeyConfig, PASSWORD_DEVICE_CONFIG_LABEL, testPasswordDevice);
- GitHubOAuthConfig objectUnderTest = objectUnderTest();
-
- assertEquals(objectUnderTest.getKeyConfig(currentKeyConfig).getKeyId(), currentKeyConfig);
- assertEquals(objectUnderTest.getKeyConfig(someOtherKeyConfig).getKeyId(), someOtherKeyConfig);
+ assertEquals(githubOAuthConfig().getKeyConfig(currentKeyConfig).getKeyId(), currentKeyConfig);
+ assertEquals(githubOAuthConfig().getKeyConfig(someOtherKeyConfig).getKeyId(), someOtherKeyConfig);
}
@Test
public void shouldThrowWhenNoKeyIdIsConfigured() {
IllegalStateException illegalStateException =
- assertThrows(IllegalStateException.class, this::objectUnderTest);
+ assertThrows(IllegalStateException.class, this::githubOAuthConfig);
assertEquals(
illegalStateException.getMessage(),
@@ -125,7 +122,7 @@
public void shouldThrowWhenNoKeyConfigIsSetAsCurrent() {
config.setBoolean(CONF_KEY_SECTION, "someKeyConfig", CURRENT_CONFIG_LABEL, false);
- assertThrows(IllegalStateException.class, this::objectUnderTest);
+ assertThrows(IllegalStateException.class, this::githubOAuthConfig);
}
@Test
@@ -134,7 +131,7 @@
config.setBoolean(CONF_KEY_SECTION, invalidSubsection, CURRENT_CONFIG_LABEL, false);
IllegalStateException illegalStateException =
- assertThrows(IllegalStateException.class, this::objectUnderTest);
+ assertThrows(IllegalStateException.class, this::githubOAuthConfig);
assertEquals(
illegalStateException.getMessage(),
@@ -148,7 +145,7 @@
config.setBoolean(CONF_KEY_SECTION, "someKeyConfig", CURRENT_CONFIG_LABEL, true);
config.setBoolean(CONF_KEY_SECTION, "someOtherKeyConfig", CURRENT_CONFIG_LABEL, true);
- assertThrows(IllegalStateException.class, this::objectUnderTest);
+ assertThrows(IllegalStateException.class, this::githubOAuthConfig);
}
@Test
@@ -157,7 +154,7 @@
config.setBoolean(CONF_KEY_SECTION, someKeyConfig, CURRENT_CONFIG_LABEL, true);
IllegalStateException illegalStateException =
- assertThrows(IllegalStateException.class, this::objectUnderTest);
+ assertThrows(IllegalStateException.class, this::githubOAuthConfig);
assertEquals(
String.format(
@@ -166,7 +163,33 @@
illegalStateException.getMessage());
}
- private GitHubOAuthConfig objectUnderTest() {
+ @Test
+ public void shouldReturnEmptyCookieDomainByDefault() {
+ setupEncryptionConfig();
+ assertEquals(Optional.empty(), githubOAuthConfig().getCookieDomain());
+ }
+
+ @Test
+ public void shouldReturnTheCookieDomainFromAuth() {
+ setupEncryptionConfig();
+ String myDomain = ".mydomain.com";
+ config.setString("auth", null, "cookieDomain", myDomain);
+
+ assertEquals(Optional.of(myDomain), githubOAuthConfig().getCookieDomain());
+ }
+
+ private GitHubOAuthConfig githubOAuthConfig() {
return new GitHubOAuthConfig(config, canonicalWebUrl);
}
+
+ private void setupEncryptionConfig() {
+ String keySubsection = "someKeyConfig";
+ String cipherAlgorithm = "AES/CFB8/NoPadding";
+ String secretKeyAlgorithm = "DES";
+ config.setBoolean(CONF_KEY_SECTION, keySubsection, CURRENT_CONFIG_LABEL, true);
+ config.setString(
+ CONF_KEY_SECTION, keySubsection, PASSWORD_DEVICE_CONFIG_LABEL, testPasswordDevice);
+ config.setString(CONF_KEY_SECTION, keySubsection, CIPHER_ALGO_CONFIG_LABEL, cipherAlgorithm);
+ config.setString(CONF_KEY_SECTION, keySubsection, SECRET_KEY_CONFIG_LABEL, secretKeyAlgorithm);
+ }
}