Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kc change #1062

Merged
merged 18 commits into from
Jun 30, 2021
25 changes: 25 additions & 0 deletions Apromore-Core-Components/Apromore-Portal/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
org.springframework.web.context.request,
org.springframework.web.filter,
org.zkoss.zel.impl,
com.fasterxml.jackson.annotation,
org.zkoss.zk.au.http,
*
</Import-Package>
Expand Down Expand Up @@ -122,6 +123,12 @@
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.22</version>
</dependency>

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.10.5</version>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
Expand Down Expand Up @@ -378,6 +385,24 @@
<artifactId>guava</artifactId>
</dependency>

<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-servlet-filter-adapter</artifactId>
<version>14.0.0</version>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update keycloak.version in ApromoreCore/pom.xml and use ${keycloak.version}

<exclusions>
<exclusion> <!-- declare the exclusion here -->
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-osgi-adapter</artifactId>
<version>14.0.0</version>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update keycloak.version in ApromoreCore/pom.xml and use ${keycloak.version}

</dependency>

</dependencies>

</project>

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -21,158 +21,146 @@
*/
package org.apromore.portal.security;

import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apromore.plugin.portal.PortalLoggerFactory;
import org.slf4j.Logger;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Base64;
import java.util.UUID;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apromore.plugin.portal.PortalLoggerFactory;
import org.slf4j.Logger;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;

public class KeycloakLoginUrlAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoint {

private static final Logger LOGGER = PortalLoggerFactory.getLogger(KeycloakLoginUrlAuthenticationEntryPoint.class);

private static final String ENV_KEYCLOAK_REALM_NAME_KEY = "KEYCLOAK_REALM_NAME";
private static final String KEYCLOAK_REALM_PLACEHOLDER = "<keycloakRealm>";
private static final String STATE_UUID_PLACEHOLDER = "<state_uuid>";
private static final String FULL_RETURN_PATH_PLACEHOLDER = "<full_return_path>";

private String fullConfigurableReturnPath = new String(
Base64.getEncoder().encode("http://localhost:8181/".getBytes()));
private boolean utiliseKeycloakSso = false;

private String keycloakLoginFormUrl;

public void setFullProtocolHostPortUrl(final String fullProtocolHostPortUrl) {
fullConfigurableReturnPath = new String(
Base64.getEncoder().encode(fullProtocolHostPortUrl.getBytes()));
private static final Logger LOGGER =
PortalLoggerFactory.getLogger(KeycloakLoginUrlAuthenticationEntryPoint.class);

LOGGER.trace("Set fullConfigurableReturnPath to {}", fullConfigurableReturnPath);
}
private static final String ENV_KEYCLOAK_REALM_NAME_KEY = "KEYCLOAK_REALM_NAME";
private static final String KEYCLOAK_REALM_PLACEHOLDER = "<keycloakRealm>";
private static final String STATE_UUID_PLACEHOLDER = "<state_uuid>";
private static final String FULL_RETURN_PATH_PLACEHOLDER = "<full_return_path>";

public void setUseKeycloakSso(final boolean useKeycloakSso) {
utiliseKeycloakSso = useKeycloakSso;
private String fullConfigurableReturnPath =
new String(Base64.getEncoder().encode("http://localhost:8181/".getBytes()));
private boolean utiliseKeycloakSso = false;

LOGGER.trace("Set useKeycloakSso to {}", utiliseKeycloakSso);
}
private String keycloakLoginFormUrl;

public String getKeycloakLoginFormUrl() {
return keycloakLoginFormUrl;
}
public void setFullProtocolHostPortUrl(final String fullProtocolHostPortUrl) {
fullConfigurableReturnPath =
new String(Base64.getEncoder().encode(fullProtocolHostPortUrl.getBytes()));

public void setKeycloakLoginFormUrl(final String keycloakLoginFormUrl) {
if ((this.keycloakLoginFormUrl == null) ||
(this.keycloakLoginFormUrl.contains(KEYCLOAK_REALM_PLACEHOLDER))) {
final String keycloakRealm = System.getenv(ENV_KEYCLOAK_REALM_NAME_KEY);
LOGGER.trace("FROM environment property keycloakRealm[" + keycloakRealm + "]");
LOGGER.trace("Set fullConfigurableReturnPath to {}", fullConfigurableReturnPath);
}

if (keycloakRealm != null) {
String tmpUrl = keycloakLoginFormUrl;
public void setUseKeycloakSso(final boolean useKeycloakSso) {
utiliseKeycloakSso = useKeycloakSso;

final String randomStateUuid = UUID.randomUUID().toString();
LOGGER.trace("randomStateUuid: {}", randomStateUuid);
LOGGER.trace("Set useKeycloakSso to {}", utiliseKeycloakSso);
}

tmpUrl = tmpUrl.replaceFirst(KEYCLOAK_REALM_PLACEHOLDER, keycloakRealm);
tmpUrl = tmpUrl.replaceFirst(STATE_UUID_PLACEHOLDER, randomStateUuid);
tmpUrl = tmpUrl.replaceFirst(FULL_RETURN_PATH_PLACEHOLDER, fullConfigurableReturnPath);
LOGGER.trace(">>>>> >>> > tmpUrl=[" + tmpUrl + "]");
public String getKeycloakLoginFormUrl() {
return keycloakLoginFormUrl;
}

this.keycloakLoginFormUrl = tmpUrl;
} else {
LOGGER.trace("Keycloak login realm was null - maybe keycloak feature turned-off? [proceeding]");
}
}
}
public void setKeycloakLoginFormUrl(final String keycloakLoginFormUrl) {
if ((this.keycloakLoginFormUrl == null)
|| (this.keycloakLoginFormUrl.contains(KEYCLOAK_REALM_PLACEHOLDER))) {
final String keycloakRealm = System.getenv(ENV_KEYCLOAK_REALM_NAME_KEY);
LOGGER.trace("FROM environment property keycloakRealm[" + keycloakRealm + "]");

@Override
public void commence(final HttpServletRequest httpServletRequest,
final HttpServletResponse httpServletResponse,
final AuthenticationException authenticationException) throws IOException, ServletException {
final String requestServletPath = httpServletRequest.getServletPath();
final String requestURL = httpServletRequest.getRequestURL().toString();
LOGGER.trace("requestServletPath {}", requestServletPath);
LOGGER.trace("requestURL {}", requestURL);
if (keycloakRealm != null) {
String tmpUrl = keycloakLoginFormUrl;

super.commence(httpServletRequest, httpServletResponse, authenticationException);
}
final String randomStateUuid = UUID.randomUUID().toString();
LOGGER.trace("randomStateUuid: {}", randomStateUuid);

@Override
protected String buildRedirectUrlToLoginPage(
final HttpServletRequest request,
final HttpServletResponse response,
final AuthenticationException authException) {
tmpUrl = tmpUrl.replaceFirst(KEYCLOAK_REALM_PLACEHOLDER, keycloakRealm);
tmpUrl = tmpUrl.replaceFirst(STATE_UUID_PLACEHOLDER, randomStateUuid);
tmpUrl = tmpUrl.replaceFirst(FULL_RETURN_PATH_PLACEHOLDER, fullConfigurableReturnPath);
LOGGER.trace(">>>>> >>> > tmpUrl=[" + tmpUrl + "]");

return super.buildRedirectUrlToLoginPage(request, response, authException);
this.keycloakLoginFormUrl = tmpUrl;
} else {
LOGGER.trace(
"Keycloak login realm was null - maybe keycloak feature turned-off? [proceeding]");
}
}

/**
* Allows sub-classes to modify the login form URL that should be applicable for a given request.
*
* @param httpServletRequest The HTTP servlet request.
* @param httpServletResponse The HTTP servlet response.
* @param exception The exception
*
* @return The formulated URL (cannot be null or empty; defaults to {@link #getLoginFormUrl()}).
*/
@Override
protected String determineUrlToUseForThisRequest(
final HttpServletRequest httpServletRequest,
final HttpServletResponse httpServletResponse,
final AuthenticationException exception) {
if (utiliseKeycloakSso) {
LOGGER.trace("[ Utilising keycloak ]");

final String loginFormPattern = getKeycloakLoginFormUrl();
LOGGER.trace("### loginFormPattern: {}", loginFormPattern);

final String keycloakRealmOfCustomer = System.getenv(ENV_KEYCLOAK_REALM_NAME_KEY);
LOGGER.trace("keycloakRealmOfCustomer {}", keycloakRealmOfCustomer);

String loginUrl = loginFormPattern.replaceAll(KEYCLOAK_REALM_PLACEHOLDER, keycloakRealmOfCustomer);
LOGGER.trace("loginUrl[1] {}", loginUrl);
loginUrl = loginUrl.replaceAll(FULL_RETURN_PATH_PLACEHOLDER, fullConfigurableReturnPath);
LOGGER.trace("loginUrl[2] {}", loginUrl);

LOGGER.trace(">>> Resolved Keycloak loginUrl (via securityms): {}", loginUrl);

return loginUrl;
} else {
LOGGER.trace("[ Keycloak SSO turned off ]");

String requestUriStr = httpServletRequest.getRequestURL().toString().trim();
LOGGER.trace("requestUriStr: {}", requestUriStr);

try {
final URI uri = new URI(requestUriStr);

final String host = uri.getHost();
final String path = uri.getPath();
int port = (uri.getPort() == -1) ? 80 : uri.getPort();
LOGGER.trace("host {} path {} port {}", host, path, port);

if (host.endsWith("/") || ( (port == 80) || (port == 8181)) ) {
if ( (path == null) ||
( ((port == 80) || (port == 8181)) &&
((path != null) ))) {
requestUriStr = uri.resolve("/login.zul").toString();

LOGGER.trace("requestUriStr: {}", requestUriStr);
}
}
} catch (final URISyntaxException use) {
LOGGER.error("Error in parsing uri: {} - stackTrace {}", use.getMessage(),
ExceptionUtils.getStackTrace(use));
}

return requestUriStr;
}
}

@Override
public void commence(final HttpServletRequest httpServletRequest,
final HttpServletResponse httpServletResponse,
final AuthenticationException authenticationException) throws IOException, ServletException {
final String requestServletPath = httpServletRequest.getServletPath();
final String requestURL = httpServletRequest.getRequestURL().toString();
LOGGER.trace("requestServletPath {}", requestServletPath);
LOGGER.trace("requestURL {}", requestURL);

super.commence(httpServletRequest, httpServletResponse, authenticationException);
}

@Override
protected String buildRedirectUrlToLoginPage(final HttpServletRequest request,
final HttpServletResponse response, final AuthenticationException authException) {

return super.buildRedirectUrlToLoginPage(request, response, authException);
}

/**
* Allows sub-classes to modify the login form URL that should be applicable for a given request.
*
* @param httpServletRequest The HTTP servlet request.
* @param httpServletResponse The HTTP servlet response.
* @param exception The exception
*
* @return The formulated URL (cannot be null or empty; defaults to {@link #getLoginFormUrl()}).
*/
@Override
protected String determineUrlToUseForThisRequest(final HttpServletRequest httpServletRequest,
final HttpServletResponse httpServletResponse, final AuthenticationException exception) {
if (utiliseKeycloakSso) {
LOGGER.trace("[ Utilising keycloak ]");

final String loginFormPattern = getKeycloakLoginFormUrl();
LOGGER.trace("### loginFormPattern: {}", loginFormPattern);

final String keycloakRealmOfCustomer = System.getenv(ENV_KEYCLOAK_REALM_NAME_KEY);
LOGGER.trace("keycloakRealmOfCustomer {}", keycloakRealmOfCustomer);

String loginUrl =
loginFormPattern.replaceAll(KEYCLOAK_REALM_PLACEHOLDER, keycloakRealmOfCustomer);
LOGGER.trace("loginUrl[1] {}", loginUrl);
loginUrl = loginUrl.replaceAll(FULL_RETURN_PATH_PLACEHOLDER, fullConfigurableReturnPath);
LOGGER.trace("loginUrl[2] {}", loginUrl);

LOGGER.trace(">>> Resolved Keycloak loginUrl (via securityms): {}", loginUrl);

return loginUrl;
} else {
LOGGER.trace("[ Keycloak SSO turned off ]");

String requestUriStr = httpServletRequest.getRequestURL().toString().trim();
HttpSession session = httpServletRequest.getSession(false);
URI uri = null;
try {
uri = new URI(requestUriStr);
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be good to log exception as error.

}
if (session == null || session.getAttribute("USER") == null) {
requestUriStr = uri.resolve("/login.zul").toString();
} else {
requestUriStr = uri.resolve("").toString();
}

return requestUriStr;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*-
* #%L
* This file is part of "Apromore Core".
* %%
* Copyright (C) 2018 - 2021 Apromore Pty Ltd.
* %%
* 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 General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/lgpl-3.0.html>.
* #L%
*/
package org.apromore.portal.servlet.filter;

import java.util.Enumeration;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;

public class ApromoreFilterConfig implements FilterConfig {

ServletContext context;



public ApromoreFilterConfig(ServletContext context) {
this.context = context;
}

@Override
public String getFilterName() {
// TODO Auto-generated method stub
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Minor] remove auto-generated comments

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will delete this file. Not used

return null;
}

@Override
public ServletContext getServletContext() {
// TODO Auto-generated method stub
return context;
}

@Override
public String getInitParameter(String name) {
switch (name) {
case "keycloak.config.skipPattern":
return null;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Minor] remove blank lines


default:
break;
}
return null;
}

@Override
public Enumeration<String> getInitParameterNames() {
// TODO Auto-generated method stub
return null;
}

}
Loading