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); + } }