Skip to content

Commit

Permalink
feat(engine): add support for url redirection param (#3013)
Browse files Browse the repository at this point in the history
  • Loading branch information
Shmayro authored May 31, 2024
1 parent 23a840d commit 8fa8fdc
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* Copyright (C) 2024 Bonitasoft S.A.
* Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble
* This library 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
* version 2.1 of the License.
* This library 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.bonitasoft.console.common.server.filter;

import java.io.IOException;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.bonitasoft.console.common.server.auth.AuthenticationManager;

/**
* Filter that redirects to a URL specified as a parameter in the request.
* The URL must be relative to the current domain.
*
* @author Haroun EL ALAMI
*/
@Slf4j
public class RedirectFilter implements Filter {

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {

final HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
final HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;

String redirectUrl = httpRequest.getParameter(AuthenticationManager.REDIRECT_URL);
if (StringUtils.isNoneBlank(redirectUrl)) {
// avoid redirecting to a different domain
if (!redirectUrl.contains("//")) {
httpResponse.sendRedirect(redirectUrl);
return;
}
// If the redirectUrl is not valid
log.warn("Invalid redirect URL: {}", redirectUrl);
}

filterChain.doFilter(servletRequest, servletResponse);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.StringUtils;
import org.bonitasoft.console.common.server.auth.AuthenticationManager;
import org.bonitasoft.console.common.server.auth.AuthenticationManagerFactory;
import org.bonitasoft.console.common.server.auth.AuthenticationManagerNotFoundException;
Expand Down Expand Up @@ -259,7 +260,10 @@ protected AuthenticationManager getAuthenticationManager() throws ServletExcepti
}

protected RedirectUrl makeRedirectUrl(final HttpServletRequestAccessor httpRequest) {
final RedirectUrlBuilder builder = new RedirectUrlBuilder(httpRequest.getRequestedUri());
// if the request has a redirection URL, we use it, otherwise we use the requested URI
boolean hasRedirectionURL = StringUtils.isNotBlank(httpRequest.getRedirectUrl());
final RedirectUrlBuilder builder = new RedirectUrlBuilder(
hasRedirectionURL ? httpRequest.getRedirectUrl() : httpRequest.getRequestedUri());
builder.appendParameters(httpRequest.getParameterMap());
return builder.build();
}
Expand Down
11 changes: 11 additions & 0 deletions bpm/bonita-web-server/src/main/webapp/WEB-INF/web.xml
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,11 @@
<param-value>true</param-value>
</init-param>
</filter>
<!-- Redirect filter -->
<filter>
<filter-name>RedirectFilter</filter-name>
<filter-class>org.bonitasoft.console.common.server.filter.RedirectFilter</filter-class>
</filter>
<!-- Sanitize filter to prevent code injection -->
<filter>
<filter-name>SanitizerFilter</filter-name>
Expand Down Expand Up @@ -238,6 +243,12 @@
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
<filter-mapping>
<filter-name>RedirectFilter</filter-name>
<url-pattern>/apps/sendRedirect</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
<filter-mapping>
<filter-name>RestAPIAuthorizationFilter</filter-name>
<url-pattern>/API/*</url-pattern>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/**
* Copyright (C) 2024 Bonitasoft S.A.
* Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble
* This library 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
* version 2.1 of the License.
* This library 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.bonitasoft.console.common.server.filter;

import static org.mockito.Mockito.*;

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.mockito.Mock;
import org.mockito.MockitoAnnotations;

public class RedirectFilterTest {

@Mock
private HttpServletRequest httpRequest;

@Mock
private HttpServletResponse httpResponse;

@Mock
private FilterChain filterChain;

private RedirectFilter redirectFilter;

@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
redirectFilter = new RedirectFilter();
}

@Test
public void testDoFilterWithInternalRedirect() throws IOException, ServletException {
when(httpRequest.getParameter("redirectUrl")).thenReturn("/redirectLink");
when(httpRequest.getRequestURL()).thenReturn(new StringBuffer("http://bonita:8080/currentPath"));
when(httpRequest.getRequestURI()).thenReturn("/currentPath");

redirectFilter.doFilter(httpRequest, httpResponse, filterChain);

verify(httpResponse).sendRedirect("/redirectLink");
verify(filterChain, never()).doFilter(httpRequest, httpResponse);
}

@Test
public void testDoFilterWithExternalRedirect() throws IOException, ServletException {
// using http:// as a prefix to simulate an external redirect
when(httpRequest.getParameter("redirectUrl")).thenReturn("http://external:9090/redirectLink");
when(httpRequest.getRequestURL()).thenReturn(new StringBuffer("http://bonita:8080/currentPath"));
when(httpRequest.getRequestURI()).thenReturn("/currentPath");

redirectFilter.doFilter(httpRequest, httpResponse, filterChain);

verify(httpResponse, never()).sendRedirect(anyString());
verify(filterChain).doFilter(httpRequest, httpResponse);

// using // as a prefix to simulate an external redirect
when(httpRequest.getParameter("redirectUrl")).thenReturn("//external:9090/redirectLink");
when(httpRequest.getRequestURL()).thenReturn(new StringBuffer("http://bonita:8080/currentPath"));
when(httpRequest.getRequestURI()).thenReturn("/currentPath");

redirectFilter.doFilter(httpRequest, httpResponse, filterChain);

verify(httpResponse, never()).sendRedirect(anyString());
verify(filterChain, times(2)).doFilter(httpRequest, httpResponse);
}

@Test
public void testDoFilterWithoutRedirect() throws IOException, ServletException {
when(httpRequest.getParameter("redirectUrl")).thenReturn(null);

redirectFilter.doFilter(httpRequest, httpResponse, filterChain);

verify(httpResponse, never()).sendRedirect(anyString());
verify(filterChain).doFilter(httpRequest, httpResponse);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,14 @@ public void testMakeRedirectUrl() {
assertThat(redirectUrl.getUrl()).isEqualToIgnoringCase("/apps/appDirectoryBonita");
}

@Test
public void testMakeRedirectUrlWithRedirectUrlIncluded() {
when(httpRequest.getRequestURI()).thenReturn("/apps/appDirectoryBonita");
when(request.getRedirectUrl()).thenReturn("/redirectLink");
final RedirectUrl redirectUrl = authenticationFilter.makeRedirectUrl(request);
assertThat(redirectUrl.getUrl()).isEqualToIgnoringCase("/redirectLink");
}

@Test
public void testCompileNullPattern() {
assertThat(authenticationFilter.compilePattern(null)).isNull();
Expand Down

0 comments on commit 8fa8fdc

Please sign in to comment.