]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-8413 Take into account context path during authentication error 1580/head
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Fri, 27 Jan 2017 12:40:53 +0000 (13:40 +0100)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Mon, 30 Jan 2017 11:34:55 +0000 (12:34 +0100)
server/sonar-server/src/main/java/org/sonar/server/authentication/AuthenticationError.java
server/sonar-server/src/main/java/org/sonar/server/authentication/AuthenticationFilter.java
server/sonar-server/src/main/java/org/sonar/server/authentication/InitFilter.java
server/sonar-server/src/main/java/org/sonar/server/authentication/OAuth2CallbackFilter.java
server/sonar-server/src/main/java/org/sonar/server/authentication/UserSessionInitializer.java
server/sonar-server/src/test/java/org/sonar/server/authentication/InitFilterTest.java
server/sonar-server/src/test/java/org/sonar/server/authentication/OAuth2CallbackFilterTest.java
server/sonar-server/src/test/java/org/sonar/server/authentication/UserSessionInitializerTest.java

index dc830b0ad731a9cb218fda6ad115a3381a1c5700..33088d6b161617cbef59a30a5c73f8423f6ead92 100644 (file)
@@ -50,16 +50,16 @@ final class AuthenticationError {
     redirectToUnauthorized(response);
   }
 
-  static void handleAuthenticationError(AuthenticationException e, HttpServletResponse response) {
-    redirectTo(response, getPath(e));
+  static void handleAuthenticationError(AuthenticationException e, HttpServletResponse response, String contextPath) {
+    redirectTo(response, getPath(e, contextPath));
   }
 
-  private static String getPath(AuthenticationException e) {
+  private static String getPath(AuthenticationException e, String contextPath) {
     String publicMessage = e.getPublicMessage();
     if (publicMessage == null || publicMessage.isEmpty()) {
       return UNAUTHORIZED_PATH;
     }
-    return format(UNAUTHORIZED_PATH_WITH_MESSAGE, encodeMessage(publicMessage));
+    return contextPath + format(UNAUTHORIZED_PATH_WITH_MESSAGE, encodeMessage(publicMessage));
   }
 
   private static String encodeMessage(String message) {
index 7ff858199b36a58382c8247726cf8411260f82d4..176ed27a903564ec4c57d9a7da0887209411d84c 100644 (file)
@@ -70,4 +70,8 @@ public abstract class AuthenticationFilter extends ServletFilter {
     }
     return null;
   }
+
+  String getContextPath() {
+    return server.getContextPath();
+  }
 }
index b848bed77d74f0f05f835a99c41f5a93e11a57e5..ec78f3b90fa95dfb469f2590eb89c13cc1139484 100644 (file)
@@ -83,7 +83,7 @@ public class InitFilter extends AuthenticationFilter {
       }
     } catch (AuthenticationException e) {
       authenticationEvent.loginFailure(request, e);
-      handleAuthenticationError(e, response);
+      handleAuthenticationError(e, response, getContextPath());
     } catch (Exception e) {
       handleError(e, response, format("Fail to initialize authentication with provider '%s'", provider.getKey()));
     }
index 5ab992fd4e062b0afa28b98680f04ccb82ee40c8..de8f18e07c5a8a345f268e262a6c56390338737f 100644 (file)
@@ -78,7 +78,7 @@ public class OAuth2CallbackFilter extends AuthenticationFilter {
       }
     } catch (AuthenticationException e) {
       authenticationEvent.loginFailure(request, e);
-      handleAuthenticationError(e, response);
+      handleAuthenticationError(e, response, getContextPath());
     } catch (Exception e) {
       handleError(e, response, format("Fail to callback authentication with '%s'", provider.getKey()));
     }
index b9c8957dee21203666959fd4be9965e3ed3d8718..4ed5d460dd818c0b01e5ac7cfd8d0d880ab54d82 100644 (file)
@@ -110,7 +110,7 @@ public class UserSessionInitializer {
       }
       if (isNotLocalOrJwt(e.getSource())) {
         // redirect to Unauthorized error page
-        handleAuthenticationError(e, response);
+        handleAuthenticationError(e, response, request.getContextPath());
         return false;
       }
       // Rails will redirect to login page
index 242ee37d75f7fc94d72ae110ac916d79053d137b..5ac9b75efdd29b804344eb640fb97c8ea2c30e9e 100644 (file)
@@ -173,6 +173,18 @@ public class InitFilterTest {
     assertThat(authenticationException.getPublicMessage()).isEqualTo("Email john@email.com is already used");
   }
 
+  @Test
+  public void redirect_with_context_path_when_failing_because_of_UnauthorizedException() throws Exception {
+    when(server.getContextPath()).thenReturn("/sonarqube");
+    IdentityProvider identityProvider = new FailWithUnauthorizedExceptionIdProvider("failing");
+    when(request.getRequestURI()).thenReturn("/sonarqube/sessions/init/" + identityProvider.getKey());
+    identityProviderRepository.addIdentityProvider(identityProvider);
+
+    underTest.doFilter(request, response, chain);
+
+    verify(response).sendRedirect("/sonarqube/sessions/unauthorized?message=Email+john%40email.com+is+already+used");
+  }
+
   private void assertOAuth2InitCalled() {
     assertThat(logTester.logs(LoggerLevel.ERROR)).isEmpty();
     assertThat(oAuth2IdentityProvider.isInitCalled()).isTrue();
@@ -227,10 +239,10 @@ public class InitFilterTest {
     public boolean isEnabled() {
       return true;
     }
-
     @Override
     public boolean allowsUsersToSignUp() {
       return false;
     }
+
   }
 }
index 8bd1d69fbc62495d71ccb62e2ff5f08167af3e18..e1ce060c789516c0b6346ef08d1688be230cd37c 100644 (file)
@@ -166,6 +166,22 @@ public class OAuth2CallbackFilterTest {
     assertThat(authenticationException.getPublicMessage()).isEqualTo("Email john@email.com is already used");
   }
 
+  @Test
+  public void redirect_with_context_path_when_failing_because_of_UnauthorizedExceptionException() throws Exception {
+    when(server.getContextPath()).thenReturn("/sonarqube");
+    FailWithUnauthorizedExceptionIdProvider identityProvider = new FailWithUnauthorizedExceptionIdProvider();
+    identityProvider
+      .setKey("failing")
+      .setName("name of failing")
+      .setEnabled(true);
+    when(request.getRequestURI()).thenReturn("/sonarqube/oauth2/callback/" + identityProvider.getKey());
+    identityProviderRepository.addIdentityProvider(identityProvider);
+
+    underTest.doFilter(request, response, chain);
+
+    verify(response).sendRedirect("/sonarqube/sessions/unauthorized?message=Email+john%40email.com+is+already+used");
+  }
+
   @Test
   public void fail_when_no_oauth2_provider_provided() throws Exception {
     when(request.getRequestURI()).thenReturn("/oauth2/callback");
index 9f36ee7dc6b495c29b102e48060d746f00ee4535..9b6bc45bcacee21e09eec58c1097438cfd6cc378 100644 (file)
@@ -29,6 +29,7 @@ import org.junit.Test;
 import org.mockito.ArgumentCaptor;
 import org.sonar.api.config.MapSettings;
 import org.sonar.api.config.Settings;
+import org.sonar.api.server.authentication.BaseIdentityProvider;
 import org.sonar.api.utils.System2;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
@@ -220,6 +221,29 @@ public class UserSessionInitializerTest {
     verifyZeroInteractions(userSession);
   }
 
+  @Test
+  public void return_to_session_unauthorized_when_error_on_from_external_provider() throws Exception {
+    when(ssoAuthenticator.authenticate(request, response)).thenReturn(Optional.empty());
+    doThrow(AuthenticationException.newBuilder().setSource(Source.external(newBasicIdentityProvider("failing"))).setPublicMessage("Token id hasn't been found").build())
+      .when(jwtHttpHandler).validateToken(request, response);
+
+    assertThat(underTest.initUserSession(request, response)).isFalse();
+
+    verify(response).sendRedirect("/sessions/unauthorized?message=Token+id+hasn%27t+been+found");
+  }
+
+  @Test
+  public void return_to_session_unauthorized_when_error_on_from_external_provider_with_context_path() throws Exception {
+    when(request.getContextPath()).thenReturn("/sonarqube");
+    when(ssoAuthenticator.authenticate(request, response)).thenReturn(Optional.empty());
+    doThrow(AuthenticationException.newBuilder().setSource(Source.external(newBasicIdentityProvider("failing"))).setPublicMessage("Token id hasn't been found").build())
+      .when(jwtHttpHandler).validateToken(request, response);
+
+    assertThat(underTest.initUserSession(request, response)).isFalse();
+
+    verify(response).sendRedirect("/sonarqube/sessions/unauthorized?message=Token+id+hasn%27t+been+found");
+  }
+
   private void assertPathIsIgnored(String path) {
     when(request.getRequestURI()).thenReturn(path);
 
@@ -239,4 +263,10 @@ public class UserSessionInitializerTest {
     verify(userSession).set(any(UserSession.class));
     reset(userSession, jwtHttpHandler, basicAuthenticator);
   }
+
+  private static BaseIdentityProvider newBasicIdentityProvider(String name) {
+    BaseIdentityProvider mock = mock(BaseIdentityProvider.class);
+    when(mock.getName()).thenReturn(name);
+    return mock;
+  }
 }