aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-webserver-auth
diff options
context:
space:
mode:
authorDimitris Kavvathas <dimitris.kavvathas@sonarsource.com>2022-09-14 15:21:47 +0200
committersonartech <sonartech@sonarsource.com>2022-09-15 20:03:03 +0000
commit01350017dd20b13f0b1f3c82325d1426afeb95b2 (patch)
tree034f6ad863bfd38e0b589aa5de693168ab2af8dd /server/sonar-webserver-auth
parent37226c00747bddecc291f56ec1b208984527931a (diff)
downloadsonarqube-01350017dd20b13f0b1f3c82325d1426afeb95b2.tar.gz
sonarqube-01350017dd20b13f0b1f3c82325d1426afeb95b2.zip
SONAR-17296 Add SamlValidationRedirectionFilter and SamlValidationCallbackFilter to show SAML validation status page.
Diffstat (limited to 'server/sonar-webserver-auth')
-rw-r--r--server/sonar-webserver-auth/src/main/java/org/sonar/server/authentication/AuthenticationError.java2
-rw-r--r--server/sonar-webserver-auth/src/main/java/org/sonar/server/authentication/AuthenticationModule.java1
-rw-r--r--server/sonar-webserver-auth/src/main/java/org/sonar/server/authentication/SamlValidationRedirectionFilter.java65
-rw-r--r--server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/SamlValidationRedirectionFilterTest.java81
4 files changed, 148 insertions, 1 deletions
diff --git a/server/sonar-webserver-auth/src/main/java/org/sonar/server/authentication/AuthenticationError.java b/server/sonar-webserver-auth/src/main/java/org/sonar/server/authentication/AuthenticationError.java
index f16dc2772f0..6fa2420fdd7 100644
--- a/server/sonar-webserver-auth/src/main/java/org/sonar/server/authentication/AuthenticationError.java
+++ b/server/sonar-webserver-auth/src/main/java/org/sonar/server/authentication/AuthenticationError.java
@@ -46,7 +46,7 @@ public final class AuthenticationError {
redirectToUnauthorized(request, response);
}
- static void handleError(HttpServletRequest request, HttpServletResponse response, String message) {
+ public static void handleError(HttpServletRequest request, HttpServletResponse response, String message) {
LOGGER.warn(message);
redirectToUnauthorized(request, response);
}
diff --git a/server/sonar-webserver-auth/src/main/java/org/sonar/server/authentication/AuthenticationModule.java b/server/sonar-webserver-auth/src/main/java/org/sonar/server/authentication/AuthenticationModule.java
index 2c2ca0edba4..5beed48ec0c 100644
--- a/server/sonar-webserver-auth/src/main/java/org/sonar/server/authentication/AuthenticationModule.java
+++ b/server/sonar-webserver-auth/src/main/java/org/sonar/server/authentication/AuthenticationModule.java
@@ -43,6 +43,7 @@ public class AuthenticationModule extends Module {
JwtHttpHandler.class,
JwtSerializer.class,
OAuth2AuthenticationParametersImpl.class,
+ SamlValidationRedirectionFilter.class,
OAuth2CallbackFilter.class,
OAuth2ContextFactory.class,
OAuthCsrfVerifier.class,
diff --git a/server/sonar-webserver-auth/src/main/java/org/sonar/server/authentication/SamlValidationRedirectionFilter.java b/server/sonar-webserver-auth/src/main/java/org/sonar/server/authentication/SamlValidationRedirectionFilter.java
new file mode 100644
index 00000000000..d28daf1b72a
--- /dev/null
+++ b/server/sonar-webserver-auth/src/main/java/org/sonar/server/authentication/SamlValidationRedirectionFilter.java
@@ -0,0 +1,65 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.server.authentication;
+
+import java.io.IOException;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.sonar.api.platform.Server;
+import org.sonar.api.web.ServletFilter;
+
+import static org.sonar.server.authentication.AuthenticationFilter.CALLBACK_PATH;
+
+public class SamlValidationRedirectionFilter extends ServletFilter {
+
+ public static final String VALIDATION_RELAY_STATE = "validation-query";
+ public static final String SAML_VALIDATION_URL = "/saml/validation_callback";
+ private final Server server;
+
+ public SamlValidationRedirectionFilter(Server server) {
+ this.server = server;
+ }
+
+ @Override
+ public UrlPattern doGetPattern() {
+ return UrlPattern.create(CALLBACK_PATH + "saml");
+ }
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
+ HttpServletRequest httpRequest = (HttpServletRequest) request;
+ if (isSamlValidation(httpRequest)) {
+ HttpServletResponse httpResponse = (HttpServletResponse) response;
+ httpResponse.setStatus(HttpServletResponse.SC_TEMPORARY_REDIRECT);
+ httpResponse.setHeader("Location", server.getContextPath() + SAML_VALIDATION_URL);
+ return;
+ }
+ chain.doFilter(request, response);
+ }
+
+ private static boolean isSamlValidation(HttpServletRequest request) {
+ return VALIDATION_RELAY_STATE.equals(request.getParameter("RelayState"));
+ }
+}
diff --git a/server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/SamlValidationRedirectionFilterTest.java b/server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/SamlValidationRedirectionFilterTest.java
new file mode 100644
index 00000000000..ba54dddc33a
--- /dev/null
+++ b/server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/SamlValidationRedirectionFilterTest.java
@@ -0,0 +1,81 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.server.authentication;
+
+import java.io.IOException;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.api.platform.Server;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
+
+public class SamlValidationRedirectionFilterTest {
+
+ SamlValidationRedirectionFilter underTest;
+
+ @Before
+ public void setup() {
+ Server server = mock(Server.class);
+ doReturn("").when(server).getContextPath();
+ underTest = new SamlValidationRedirectionFilter(server);
+ }
+
+ @Test
+ public void do_get_pattern() {
+ assertThat(underTest.doGetPattern().matches("/oauth2/callback/saml")).isTrue();
+ assertThat(underTest.doGetPattern().matches("/oauth2/callback/")).isFalse();
+ assertThat(underTest.doGetPattern().matches("/oauth2/callback/test")).isFalse();
+ assertThat(underTest.doGetPattern().matches("/oauth2/")).isFalse();
+ }
+
+ @Test
+ public void do_filter_validation_relay_state() throws ServletException, IOException {
+ HttpServletRequest servletRequest = mock(HttpServletRequest.class);
+ HttpServletResponse servletResponse = mock(HttpServletResponse.class);
+ FilterChain filterChain = mock(FilterChain.class);
+
+ doReturn("validation-query").when(servletRequest).getParameter("RelayState");
+ underTest.doFilter(servletRequest, servletResponse, filterChain);
+
+ verify(servletResponse).setStatus(HttpServletResponse.SC_TEMPORARY_REDIRECT);
+ verify(servletResponse).setHeader("Location", "/saml/validation_callback");
+ }
+
+ @Test
+ public void do_filter_no_validation_relay_state() throws ServletException, IOException {
+ HttpServletRequest servletRequest = mock(HttpServletRequest.class);
+ HttpServletResponse servletResponse = mock(HttpServletResponse.class);
+ FilterChain filterChain = mock(FilterChain.class);
+
+ doReturn("random_query").when(servletRequest).getParameter("RelayState");
+ underTest.doFilter(servletRequest, servletResponse, filterChain);
+
+ verifyNoInteractions(servletResponse);
+ }
+}