From cff31fec2d8cc5ca2e02620889f24af4b607990d Mon Sep 17 00:00:00 2001 From: Boubaker Khanfir Date: Mon, 28 Aug 2023 14:49:09 +0100 Subject: [PATCH] feat: Upgrade To Tomcat 10 - Meeds-io/MIPs#76 --- agent/pom.xml | 11 +- .../org/gatein/sso/agent/GenericAgent.java | 2 +- .../agent/filter/AbstractLogoutFilter.java | 14 +- .../sso/agent/filter/InitiateLoginFilter.java | 8 +- .../sso/agent/filter/LoginRedirectFilter.java | 12 +- .../filter/OpenSSOCDLoginRedirectFilter.java | 2 +- .../sso/agent/filter/OpenSSOLogoutFilter.java | 2 +- .../PicketlinkSTSIntegrationFilter.java | 142 ---- .../gatein/sso/agent/filter/SPNEGOFilter.java | 96 --- .../filter/api/AbstractSSOInterceptor.java | 4 +- .../sso/agent/filter/api/SSOInterceptor.java | 2 +- .../SSOInterceptorInitializationContext.java | 2 +- .../login/SAML2IntegrationLoginModule.java | 177 ---- .../sso/agent/login/SSOLoginModule.java | 4 +- .../sso/agent/opensso/OpenSSOAgent.java | 4 +- .../sso/agent/opensso/OpenSSOAgentImpl.java | 6 +- .../agent/saml/PortalSAML2LogOutHandler.java | 137 --- .../sso/agent/tomcat/ServletAccess.java | 4 +- .../sso/agent/tomcat/ServletAccessValve.java | 4 +- .../agent/filter/InitiateLoginFilterTest.java | 57 +- .../sso/integration/SSODelegateFilter.java | 10 +- .../sso/integration/SSODelegateValve.java | 28 +- .../integration/SSODelegateFilterTest.java | 4 - pom.xml | 15 +- saml/gatein-saml-plugin/pom.xml | 90 -- .../gatein/sso/saml/plugin/SimpleGroup.java | 157 ---- .../sso/saml/plugin/SimplePrincipal.java | 77 -- .../saml/plugin/filter/EmptyFilterChain.java | 21 - .../filter/PortalIDPWebBrowserSSOFilter.java | 214 ----- .../saml/plugin/filter/SAML2LogoutFilter.java | 241 ------ .../saml/plugin/filter/SAMLFilterConfig.java | 48 -- .../plugin/filter/SAMLHTTPRequestWrapper.java | 54 -- .../filter/SAMLSPServletContextWrapper.java | 376 --------- .../listener/IDPHttpSessionListener.java | 81 -- ...ractSAML11SPRedirectFormAuthenticator.java | 140 ---- .../valve/AbstractSPFormAuthenticator.java | 787 ------------------ .../plugin/valve/BaseFormAuthenticator.java | 623 -------------- .../saml/plugin/valve/SecurityActions.java | 134 --- .../valve/ServiceProviderAuthenticator.java | 23 - .../resources/conf/portal/configuration.xml | 86 -- .../PortalIDPWebBrowserSSOFilterTest.java | 108 --- .../plugin/filter/SAML2LogoutFilterTest.java | 139 ---- .../src/test/resources/jbid_test_keystore.jks | Bin 1276 -> 0 bytes .../src/test/resources/picketlink-sp.xml | 32 - spnego/pom.xml | 53 -- .../gatein/sso/spnego/SPNEGOLoginModule.java | 116 --- spnegosso/README.md | 43 - spnegosso/pom.xml | 28 - .../security/sso/spnego/SPNEGOSSOContext.java | 32 - .../security/sso/spnego/SPNEGOSSOFilter.java | 246 ------ .../sso/spnego/SPNEGOSSOLoginModule.java | 103 --- .../resources/conf/portal/configuration.xml | 61 -- 52 files changed, 54 insertions(+), 4806 deletions(-) delete mode 100644 agent/src/main/java/org/gatein/sso/agent/filter/PicketlinkSTSIntegrationFilter.java delete mode 100644 agent/src/main/java/org/gatein/sso/agent/filter/SPNEGOFilter.java delete mode 100644 agent/src/main/java/org/gatein/sso/agent/login/SAML2IntegrationLoginModule.java delete mode 100644 agent/src/main/java/org/gatein/sso/agent/saml/PortalSAML2LogOutHandler.java delete mode 100644 saml/gatein-saml-plugin/pom.xml delete mode 100644 saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/SimpleGroup.java delete mode 100644 saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/SimplePrincipal.java delete mode 100644 saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/filter/EmptyFilterChain.java delete mode 100644 saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/filter/PortalIDPWebBrowserSSOFilter.java delete mode 100644 saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/filter/SAML2LogoutFilter.java delete mode 100644 saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/filter/SAMLFilterConfig.java delete mode 100644 saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/filter/SAMLHTTPRequestWrapper.java delete mode 100644 saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/filter/SAMLSPServletContextWrapper.java delete mode 100644 saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/listener/IDPHttpSessionListener.java delete mode 100644 saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/valve/AbstractSAML11SPRedirectFormAuthenticator.java delete mode 100644 saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/valve/AbstractSPFormAuthenticator.java delete mode 100644 saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/valve/BaseFormAuthenticator.java delete mode 100644 saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/valve/SecurityActions.java delete mode 100644 saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/valve/ServiceProviderAuthenticator.java delete mode 100644 saml/gatein-saml-plugin/src/main/resources/conf/portal/configuration.xml delete mode 100644 saml/gatein-saml-plugin/src/test/java/org/gatein/sso/saml/plugin/filter/PortalIDPWebBrowserSSOFilterTest.java delete mode 100644 saml/gatein-saml-plugin/src/test/java/org/gatein/sso/saml/plugin/filter/SAML2LogoutFilterTest.java delete mode 100644 saml/gatein-saml-plugin/src/test/resources/jbid_test_keystore.jks delete mode 100644 saml/gatein-saml-plugin/src/test/resources/picketlink-sp.xml delete mode 100644 spnego/pom.xml delete mode 100644 spnego/src/main/java/org/gatein/sso/spnego/SPNEGOLoginModule.java delete mode 100644 spnegosso/README.md delete mode 100644 spnegosso/pom.xml delete mode 100644 spnegosso/src/main/java/org/gatein/security/sso/spnego/SPNEGOSSOContext.java delete mode 100644 spnegosso/src/main/java/org/gatein/security/sso/spnego/SPNEGOSSOFilter.java delete mode 100644 spnegosso/src/main/java/org/gatein/security/sso/spnego/SPNEGOSSOLoginModule.java delete mode 100644 spnegosso/src/main/resources/conf/portal/configuration.xml diff --git a/agent/pom.xml b/agent/pom.xml index 3ba348b63..f9d1cbcee 100644 --- a/agent/pom.xml +++ b/agent/pom.xml @@ -44,15 +44,16 @@ httpclient provided - - org.jboss.security - jboss-negotiation-spnego - provided - org.picketlink picketlink-federation provided + + + org.apache.santuario + xmlsec + + org.picketlink.distribution diff --git a/agent/src/main/java/org/gatein/sso/agent/GenericAgent.java b/agent/src/main/java/org/gatein/sso/agent/GenericAgent.java index 24b52a690..fda907952 100644 --- a/agent/src/main/java/org/gatein/sso/agent/GenericAgent.java +++ b/agent/src/main/java/org/gatein/sso/agent/GenericAgent.java @@ -38,7 +38,7 @@ import org.exoplatform.container.RootContainer; import org.exoplatform.services.organization.OrganizationService; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; /** * Base agent superclass used by other SSO agents (CAS, OpenAM) diff --git a/agent/src/main/java/org/gatein/sso/agent/filter/AbstractLogoutFilter.java b/agent/src/main/java/org/gatein/sso/agent/filter/AbstractLogoutFilter.java index 71dbc2b46..25402d922 100644 --- a/agent/src/main/java/org/gatein/sso/agent/filter/AbstractLogoutFilter.java +++ b/agent/src/main/java/org/gatein/sso/agent/filter/AbstractLogoutFilter.java @@ -30,13 +30,13 @@ import java.io.UnsupportedEncodingException; import java.util.Map; -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 javax.servlet.http.HttpSession; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; /** * @author Sohil Shah diff --git a/agent/src/main/java/org/gatein/sso/agent/filter/InitiateLoginFilter.java b/agent/src/main/java/org/gatein/sso/agent/filter/InitiateLoginFilter.java index 59103b8a1..5c58d05ae 100644 --- a/agent/src/main/java/org/gatein/sso/agent/filter/InitiateLoginFilter.java +++ b/agent/src/main/java/org/gatein/sso/agent/filter/InitiateLoginFilter.java @@ -5,9 +5,9 @@ import java.io.IOException; -import javax.servlet.*; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.*; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringUtils; import org.exoplatform.services.log.ExoLogger; @@ -167,8 +167,6 @@ protected String getLoginRedirectUrl(HttpServletRequest req) { username = fakePassword; } - // Use sessionId and system millis as password (similar like spnego is - // doing) url.append("?username=").append(username).append("&password=").append(fakePassword); } diff --git a/agent/src/main/java/org/gatein/sso/agent/filter/LoginRedirectFilter.java b/agent/src/main/java/org/gatein/sso/agent/filter/LoginRedirectFilter.java index ef0563dc8..d81dd2677 100644 --- a/agent/src/main/java/org/gatein/sso/agent/filter/LoginRedirectFilter.java +++ b/agent/src/main/java/org/gatein/sso/agent/filter/LoginRedirectFilter.java @@ -27,12 +27,12 @@ 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 jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; /** diff --git a/agent/src/main/java/org/gatein/sso/agent/filter/OpenSSOCDLoginRedirectFilter.java b/agent/src/main/java/org/gatein/sso/agent/filter/OpenSSOCDLoginRedirectFilter.java index bd2d9e380..cf4c235f2 100644 --- a/agent/src/main/java/org/gatein/sso/agent/filter/OpenSSOCDLoginRedirectFilter.java +++ b/agent/src/main/java/org/gatein/sso/agent/filter/OpenSSOCDLoginRedirectFilter.java @@ -27,7 +27,7 @@ import org.exoplatform.services.log.Log; import org.gatein.sso.agent.opensso.OpenSSOAgentImpl; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.text.SimpleDateFormat; diff --git a/agent/src/main/java/org/gatein/sso/agent/filter/OpenSSOLogoutFilter.java b/agent/src/main/java/org/gatein/sso/agent/filter/OpenSSOLogoutFilter.java index fcbb36e89..d70f70e08 100644 --- a/agent/src/main/java/org/gatein/sso/agent/filter/OpenSSOLogoutFilter.java +++ b/agent/src/main/java/org/gatein/sso/agent/filter/OpenSSOLogoutFilter.java @@ -22,7 +22,7 @@ package org.gatein.sso.agent.filter; import java.net.URLEncoder; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; //Works for GateIn Portal Logout URL = {AnyURL}?portal:componentId=UIPortal&portal:action=Logout diff --git a/agent/src/main/java/org/gatein/sso/agent/filter/PicketlinkSTSIntegrationFilter.java b/agent/src/main/java/org/gatein/sso/agent/filter/PicketlinkSTSIntegrationFilter.java deleted file mode 100644 index 73ec84271..000000000 --- a/agent/src/main/java/org/gatein/sso/agent/filter/PicketlinkSTSIntegrationFilter.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * JBoss, a division of Red Hat - * Copyright 2012, Red Hat Middleware, LLC, and individual - * contributors as indicated by the @authors tag. See the - * copyright.txt in the distribution for a full listing of - * individual contributors. - * - * This 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 2.1 of - * the License, or (at your option) any later version. - * - * This software 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 software; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA, or see the FSF site: http://www.fsf.org. - */ - -package org.gatein.sso.agent.filter; - -import org.exoplatform.container.web.AbstractFilter; -import org.exoplatform.services.log.ExoLogger; -import org.exoplatform.services.log.Log; -import org.exoplatform.services.security.jaas.UserPrincipal; -import org.jboss.security.SecurityContext; -import org.jboss.security.SecurityContextAssociation; -import org.jboss.security.client.SecurityClient; -import org.jboss.security.client.SecurityClientFactory; - -import javax.security.auth.Subject; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import java.io.IOException; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.Set; -import org.picketlink.identity.federation.core.wstrust.SamlCredential; - -/** - * Filter for set {@link SamlCredential} into {@link SecurityClient}, which enables to propagate authentication from SAML2 ticket into - * underlying EJB or WS calls. - * - * @author Marek Posolda - */ -public class PicketlinkSTSIntegrationFilter extends AbstractFilter -{ - private static Log log = ExoLogger.getLogger(PicketlinkSTSIntegrationFilter.class); - - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException - { - HttpServletRequest httpRequest = (HttpServletRequest)request; - if (httpRequest.getRemoteUser() != null) - { - try - { - SamlCredential samlCredential = getSamlCredential(); - - if (log.isTraceEnabled()) - { - log.trace("Found SamlCredential inside Subject: " + samlCredential); - } - - // Now set the security context, which can be used in EJB or other calls - if (samlCredential != null) - { - SecurityClient client = SecurityClientFactory.getSecurityClient(); - // Simple login just updates the security context - client.setSimple(new UserPrincipal(httpRequest.getRemoteUser()), samlCredential); - client.login(); - - if (log.isTraceEnabled()) - { - log.trace("SecurityClient successfully updated with SAMLCredential"); - } - } - - } - catch (Exception e) - { - e.printStackTrace(); - } - } - - chain.doFilter(request, response); - } - - public void destroy() - { - } - - private SamlCredential getSamlCredential() - { - Subject subj = getCurrentSubject(); - - if (log.isTraceEnabled()) - { - log.trace("Found subject " + subj); - } - - if (subj == null) - { - return null; - } - - Set credentials = subj.getPublicCredentials(); - for (Object credential : credentials) - { - if (credential instanceof SamlCredential) - { - return (SamlCredential)credential; - } - } - - return null; - } - - /** - * JBoss specific way for obtaining a Subject. - * TODO: is JBoss specific way needed? subject should be available in ConversationState - * - * @return subject - */ - protected Subject getCurrentSubject() - { - SecurityContext securityContext = AccessController.doPrivileged(new PrivilegedAction() - { - public SecurityContext run() - { - return SecurityContextAssociation.getSecurityContext(); - } - }); - return securityContext.getSubjectInfo().getAuthenticatedSubject(); - } -} diff --git a/agent/src/main/java/org/gatein/sso/agent/filter/SPNEGOFilter.java b/agent/src/main/java/org/gatein/sso/agent/filter/SPNEGOFilter.java deleted file mode 100644 index 3616a5c66..000000000 --- a/agent/src/main/java/org/gatein/sso/agent/filter/SPNEGOFilter.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * JBoss, a division of Red Hat - * Copyright 2011, Red Hat Middleware, LLC, and individual - * contributors as indicated by the @authors tag. See the - * copyright.txt in the distribution for a full listing of - * individual contributors. - * - * This 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 2.1 of - * the License, or (at your option) any later version. - * - * This software 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 software; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA, or see the FSF site: http://www.fsf.org. - */ - -package org.gatein.sso.agent.filter; - -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 javax.servlet.http.HttpServletResponseWrapper; - -import org.exoplatform.container.web.AbstractFilter; - -/** - * Filter is needed because when fallback to FORM authentication, we don't need to redirect request to /dologin, which is secured URI, - * but we need to go directly to /initiatelogin without going again through Tomcat authenticator. - * - * TODO: Suggest removing this filter as with new GateIn (Servlet 3.0 authentication) it may not be needed anymore - * - * @author Marek Posolda - */ -public class SPNEGOFilter extends AbstractFilter -{ - - public static final String ATTR_INITIAL_URI = "SPNEGOFilter.initialURI"; - - public void doFilter(ServletRequest request, ServletResponse response, - FilterChain chain) throws IOException, ServletException - { - HttpServletRequest httpRequest = (HttpServletRequest)request; - HttpServletResponse httpResponse = (HttpServletResponse)response; - try - { - - // first save initialURI as parameter into HTTP session. We may need it later in authenticator - String initialURI = httpRequest.getParameter("initialURI"); - if (initialURI != null) - { - httpRequest.getSession().setAttribute(ATTR_INITIAL_URI, initialURI); - } - - // we need to redirect directly to initiatelogin without going through secured URL. - HttpServletResponse wrapperResponse = new IgnoreRedirectHttpResponse(httpResponse); - chain.doFilter(request, wrapperResponse); - httpResponse.sendRedirect(httpRequest.getContextPath() + "/initiatelogin"); - } - catch(Throwable t) - { - throw new RuntimeException(t); - } - } - - public void destroy() - { - } - - // Ignoring calls to response.sendRedirect, which are performed from PortalLoginController - private class IgnoreRedirectHttpResponse extends HttpServletResponseWrapper - { - - public IgnoreRedirectHttpResponse(HttpServletResponse response) - { - super(response); - } - - @Override - public void sendRedirect(String location) - { - } - - } -} diff --git a/agent/src/main/java/org/gatein/sso/agent/filter/api/AbstractSSOInterceptor.java b/agent/src/main/java/org/gatein/sso/agent/filter/api/AbstractSSOInterceptor.java index 735c93c43..304167ab8 100644 --- a/agent/src/main/java/org/gatein/sso/agent/filter/api/AbstractSSOInterceptor.java +++ b/agent/src/main/java/org/gatein/sso/agent/filter/api/AbstractSSOInterceptor.java @@ -30,8 +30,8 @@ import org.exoplatform.services.log.ExoLogger; import org.exoplatform.services.log.Log; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; +import jakarta.servlet.FilterConfig; +import jakarta.servlet.ServletException; /** * Base {@link SSOInterceptor} which adds possibility to be initialized either through Servlet API or through eXo kernel diff --git a/agent/src/main/java/org/gatein/sso/agent/filter/api/SSOInterceptor.java b/agent/src/main/java/org/gatein/sso/agent/filter/api/SSOInterceptor.java index 72117cee0..0ea02e424 100644 --- a/agent/src/main/java/org/gatein/sso/agent/filter/api/SSOInterceptor.java +++ b/agent/src/main/java/org/gatein/sso/agent/filter/api/SSOInterceptor.java @@ -26,7 +26,7 @@ import org.exoplatform.container.ExoContainerContext; import org.exoplatform.container.xml.InitParams; -import javax.servlet.Filter; +import jakarta.servlet.Filter; /** * SSOInterceptor is actually filter, which can be configured through exo kernel diff --git a/agent/src/main/java/org/gatein/sso/agent/filter/api/SSOInterceptorInitializationContext.java b/agent/src/main/java/org/gatein/sso/agent/filter/api/SSOInterceptorInitializationContext.java index fce90064d..1004ecba9 100644 --- a/agent/src/main/java/org/gatein/sso/agent/filter/api/SSOInterceptorInitializationContext.java +++ b/agent/src/main/java/org/gatein/sso/agent/filter/api/SSOInterceptorInitializationContext.java @@ -29,7 +29,7 @@ import org.exoplatform.container.xml.InitParams; import org.exoplatform.container.xml.ValueParam; -import javax.servlet.FilterConfig; +import jakarta.servlet.FilterConfig; /** * Context, which encapsulates all initialization configuration about {@link SSOInterceptor} and is able to recognize diff --git a/agent/src/main/java/org/gatein/sso/agent/login/SAML2IntegrationLoginModule.java b/agent/src/main/java/org/gatein/sso/agent/login/SAML2IntegrationLoginModule.java deleted file mode 100644 index 7d1c2cfb7..000000000 --- a/agent/src/main/java/org/gatein/sso/agent/login/SAML2IntegrationLoginModule.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * JBoss, a division of Red Hat - * Copyright 2012, Red Hat Middleware, LLC, and individual - * contributors as indicated by the @authors tag. See the - * copyright.txt in the distribution for a full listing of - * individual contributors. - * - * This 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 2.1 of - * the License, or (at your option) any later version. - * - * This software 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 software; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA, or see the FSF site: http://www.fsf.org. - */ - -package org.gatein.sso.agent.login; - -import org.exoplatform.container.ExoContainer; -import org.exoplatform.container.ExoContainerContext; -import org.exoplatform.container.PortalContainer; -import org.exoplatform.container.RootContainer; -import org.exoplatform.services.security.Authenticator; -import org.exoplatform.services.security.Identity; -import org.exoplatform.services.security.UsernameCredential; -import org.picketlink.identity.federation.bindings.jboss.auth.SAML2LoginModule; - -import javax.security.auth.Subject; -import javax.security.auth.callback.CallbackHandler; -import javax.security.auth.login.LoginException; -import java.security.Principal; -import java.util.Map; - -/** - * Login module for integration with GateIn. It's running on GateIn (SAML SP) side. - * - * @author Marek Posolda - */ -public class SAML2IntegrationLoginModule extends SAML2LoginModule -{ - // Name of security-domain (actually not used by this impl) - private static final String OPTION_REALM_NAME = "realmName"; - - // Name of portalContainer - private static final String OPTION_PORTAL_CONTAINER_NAME = "portalContainerName"; - - // If this boolean property is true, then final principal will use roles from SAML. - // If false, then we don't use roles from SAML, but we will delegate filling of "Roles" principal to next login module in stack - // (actually it is JbossLoginModule, which uses JAAS roles from GateIn database) - // Default value is false, so we are preferring delegation to JbossLoginModule and using roles from portal DB. - private static final String OPTION_USE_SAML_ROLES = "useSAMLRoles"; - - private static final String[] ALL_VALID_OPTIONS = - { - OPTION_PORTAL_CONTAINER_NAME, - OPTION_REALM_NAME, - OPTION_USE_SAML_ROLES - }; - - private String portalContainerName; - private boolean useSAMLRoles; - - @Override - public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, - Map options) - { - try - { - addValidOptions(ALL_VALID_OPTIONS); - } - catch (NoSuchMethodError ignore) - { - // Method addValidOptions is new in picketbox. Not supported on older AS 7.1.1 - } - - super.initialize(subject, callbackHandler, sharedState, options); - - // GateIn integration - this.portalContainerName = getPortalContainerName(options); - - String useSAMLRoles = (String)options.get(OPTION_USE_SAML_ROLES); - this.useSAMLRoles = useSAMLRoles != null && "true".equals(useSAMLRoles); - - if (log.isTraceEnabled()) - { - log.trace("Using options: " - + OPTION_PORTAL_CONTAINER_NAME + "=" + this.portalContainerName - + ", " + OPTION_USE_SAML_ROLES + "=" + this.useSAMLRoles); - } - } - - @Override - public boolean login() throws javax.security.auth.login.LoginException - { - if (super.login()) - { - // Username is already in sharedState thanks to superclass - String username = getUsernameFromSharedState(); - if (log.isTraceEnabled()) - { - log.trace("Found user " + username + " in shared state."); - } - - try - { - //Perform authentication by setting up the proper Application State - Authenticator authenticator = (Authenticator) getContainer().getComponentInstanceOfType(Authenticator.class); - - Identity identity = authenticator.createIdentity(username); - sharedState.put("exo.security.identity", identity); - subject.getPublicCredentials().add(new UsernameCredential(username)); - - return true; - } - catch (Exception e) - { - log.debug("Exception during login process: " + e.getMessage(), e); - throw new LoginException(e.getMessage()); - } - } - else - { - return false; - } - } - - protected String getUsernameFromSharedState() - { - Object tmp = sharedState.get("javax.security.auth.login.name"); - if (tmp == null) - { - return null; - } - else if (tmp instanceof Principal) - { - return ((Principal) tmp).getName(); - } - else - { - return (String)tmp; - } - } - - - // *********************** Helper private methods for GateIn integration ***************************** - - private String getPortalContainerName(Map options) - { - if (options != null) - { - String optionValue = (String) options.get(OPTION_PORTAL_CONTAINER_NAME); - if (optionValue != null && optionValue.length() > 0) - { - return optionValue; - } - } - return PortalContainer.DEFAULT_PORTAL_CONTAINER_NAME; - } - - private ExoContainer getContainer() throws Exception - { - ExoContainer container = ExoContainerContext.getCurrentContainer(); - if (container instanceof RootContainer) - { - container = RootContainer.getInstance().getPortalContainer(portalContainerName); - } - return container; - } - -} diff --git a/agent/src/main/java/org/gatein/sso/agent/login/SSOLoginModule.java b/agent/src/main/java/org/gatein/sso/agent/login/SSOLoginModule.java index e8abf9982..b33e03431 100644 --- a/agent/src/main/java/org/gatein/sso/agent/login/SSOLoginModule.java +++ b/agent/src/main/java/org/gatein/sso/agent/login/SSOLoginModule.java @@ -27,7 +27,7 @@ import javax.security.auth.callback.NameCallback; import javax.security.auth.callback.PasswordCallback; import javax.security.auth.login.LoginException; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.exoplatform.services.log.ExoLogger; import org.exoplatform.services.log.Log; @@ -152,7 +152,7 @@ protected HttpServletRequest getCurrentHttpServletRequest() { try { - request = (HttpServletRequest)getContextMethod.invoke(null, "javax.servlet.http.HttpServletRequest"); + request = (HttpServletRequest)getContextMethod.invoke(null, "jakarta.servlet.http.HttpServletRequest"); } catch(Throwable e) { diff --git a/agent/src/main/java/org/gatein/sso/agent/opensso/OpenSSOAgent.java b/agent/src/main/java/org/gatein/sso/agent/opensso/OpenSSOAgent.java index 8f6965857..5f4776f80 100644 --- a/agent/src/main/java/org/gatein/sso/agent/opensso/OpenSSOAgent.java +++ b/agent/src/main/java/org/gatein/sso/agent/opensso/OpenSSOAgent.java @@ -23,8 +23,8 @@ package org.gatein.sso.agent.opensso; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; /** * Contract for OpenSSO agent diff --git a/agent/src/main/java/org/gatein/sso/agent/opensso/OpenSSOAgentImpl.java b/agent/src/main/java/org/gatein/sso/agent/opensso/OpenSSOAgentImpl.java index 006223c5e..5bf9b99f4 100644 --- a/agent/src/main/java/org/gatein/sso/agent/opensso/OpenSSOAgentImpl.java +++ b/agent/src/main/java/org/gatein/sso/agent/opensso/OpenSSOAgentImpl.java @@ -35,9 +35,9 @@ import org.exoplatform.services.log.Log; import org.gatein.sso.agent.GenericAgent; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; diff --git a/agent/src/main/java/org/gatein/sso/agent/saml/PortalSAML2LogOutHandler.java b/agent/src/main/java/org/gatein/sso/agent/saml/PortalSAML2LogOutHandler.java deleted file mode 100644 index edd85d814..000000000 --- a/agent/src/main/java/org/gatein/sso/agent/saml/PortalSAML2LogOutHandler.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * JBoss, a division of Red Hat - * Copyright 2012, Red Hat Middleware, LLC, and individual - * contributors as indicated by the @authors tag. See the - * copyright.txt in the distribution for a full listing of - * individual contributors. - * - * This 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 2.1 of - * the License, or (at your option) any later version. - * - * This software 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 software; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA, or see the FSF site: http://www.fsf.org. - */ - -package org.gatein.sso.agent.saml; - -import org.exoplatform.services.log.ExoLogger; -import org.exoplatform.services.log.Log; -import org.gatein.wci.ServletContainerFactory; -import org.picketlink.identity.federation.core.saml.v2.interfaces.SAML2HandlerRequest; -import org.picketlink.identity.federation.core.saml.v2.interfaces.SAML2HandlerResponse; -import org.picketlink.identity.federation.saml.v2.protocol.LogoutRequestType; -import org.picketlink.identity.federation.saml.v2.protocol.ResponseType; -import org.picketlink.identity.federation.saml.v2.protocol.StatusResponseType; -import org.picketlink.identity.federation.web.core.HTTPContext; -import org.picketlink.identity.federation.web.handlers.saml2.SAML2LogOutHandler; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import org.picketlink.common.exceptions.ProcessingException; -import javax.servlet.http.Cookie; - -/** - * Extension of {@link SAML2LogOutHandler} because we need to enforce WCI (crossContext) logout in portal environment. - * - * @author Marek Posolda - */ -public class PortalSAML2LogOutHandler extends SAML2LogOutHandler -{ - private static final String COOKIE_NAME = "rememberme"; - - private static final String OAUTH_COOKIE_NAME = "oauth_rememberme"; - - private static Log log = ExoLogger.getLogger(PortalSAML2LogOutHandler.class); - - @Override - public void handleRequestType(SAML2HandlerRequest request, SAML2HandlerResponse response) throws ProcessingException - { - if (request.getSAML2Object() instanceof LogoutRequestType == false) - { - return; - } - - HTTPContext httpContext = (HTTPContext) request.getContext(); - HttpServletRequest servletRequest = httpContext.getRequest(); - HttpServletResponse servletResponse = httpContext.getResponse(); - - // Handle SAML logout request by superclass - super.handleRequestType(request, response); - - // Check if session has been invalidated by superclass. If yes,we need to perform "full" logout at portal level by call WCI logout. - if (servletRequest.getSession(false) == null) - { - portalLogout(servletRequest, servletResponse); - } - } - - @Override - public void handleStatusResponseType(SAML2HandlerRequest request, SAML2HandlerResponse response) - throws ProcessingException - { - //We do not handle any ResponseType (authentication etc) - if (request.getSAML2Object() instanceof ResponseType) - return; - - if (request.getSAML2Object() instanceof StatusResponseType == false) - return; - - - HTTPContext httpContext = (HTTPContext) request.getContext(); - HttpServletRequest servletRequest = httpContext.getRequest(); - HttpServletResponse servletResponse = httpContext.getResponse(); - - // Handle SAML logout response by superclass - super.handleStatusResponseType(request, response); - - // Check if session has been invalidated by superclass. If yes,we need to perform "full" logout at portal level by call WCI logout. - if (servletRequest.getSession(false) == null) - { - portalLogout(servletRequest, servletResponse); - } - - } - - /** - * Performs portal logout by calling WCI logout. - * - * @param request - * @param response - */ - protected void portalLogout(HttpServletRequest request, HttpServletResponse response) - { - // Workaround: we need to temporary "restore" session to enforce crossContext logout at WCI layer - request.getSession(true); - - try - { - ServletContainerFactory.getServletContainer().logout(request, response); - } - catch (Exception e) - { - log.warn("Session has been invalidated but WCI logout failed.", e); - } - - // Remove rememberme cookie - Cookie cookie = new Cookie(COOKIE_NAME, ""); - cookie.setPath(request.getContextPath()); - cookie.setMaxAge(0); - response.addCookie(cookie); - - // Remove oauth cookie - Cookie oauthCookie = new Cookie(OAUTH_COOKIE_NAME, ""); - oauthCookie.setPath(request.getContextPath()); - oauthCookie.setMaxAge(0); - response.addCookie(oauthCookie); - } - -} diff --git a/agent/src/main/java/org/gatein/sso/agent/tomcat/ServletAccess.java b/agent/src/main/java/org/gatein/sso/agent/tomcat/ServletAccess.java index 15c909732..c21c51ffc 100644 --- a/agent/src/main/java/org/gatein/sso/agent/tomcat/ServletAccess.java +++ b/agent/src/main/java/org/gatein/sso/agent/tomcat/ServletAccess.java @@ -22,8 +22,8 @@ package org.gatein.sso.agent.tomcat; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; /** * @author Marek Posolda diff --git a/agent/src/main/java/org/gatein/sso/agent/tomcat/ServletAccessValve.java b/agent/src/main/java/org/gatein/sso/agent/tomcat/ServletAccessValve.java index 60c3a6157..675698c6e 100644 --- a/agent/src/main/java/org/gatein/sso/agent/tomcat/ServletAccessValve.java +++ b/agent/src/main/java/org/gatein/sso/agent/tomcat/ServletAccessValve.java @@ -28,11 +28,11 @@ import org.exoplatform.services.log.ExoLogger; import org.exoplatform.services.log.Log; -import javax.servlet.ServletException; +import jakarta.servlet.ServletException; import java.io.IOException; /** - * Valve for adding {@link javax.servlet.http.HttpServletRequest} and {@link javax.servlet.http.HttpServletResponse} into threadLocal + * Valve for adding {@link jakarta.servlet.http.HttpServletRequest} and {@link jakarta.servlet.http.HttpServletResponse} into threadLocal * so that it can be accessed from Login Modules during authentication. * * @author Marek Posolda diff --git a/agent/src/test/java/org/gatein/sso/agent/filter/InitiateLoginFilterTest.java b/agent/src/test/java/org/gatein/sso/agent/filter/InitiateLoginFilterTest.java index 0b7086a48..f3a84f527 100644 --- a/agent/src/test/java/org/gatein/sso/agent/filter/InitiateLoginFilterTest.java +++ b/agent/src/test/java/org/gatein/sso/agent/filter/InitiateLoginFilterTest.java @@ -11,12 +11,12 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; +import jakarta.servlet.FilterChain; +import jakarta.servlet.FilterConfig; +import jakarta.servlet.ServletContext; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; import org.mockito.internal.verification.VerificationModeFactory; import org.mockito.invocation.InvocationOnMock; @@ -133,49 +133,4 @@ public String answer(InvocationOnMock invocation) throws Throwable { verify(response, VerificationModeFactory.times(1)).sendRedirect(eq("/portal/sso")); verify(chain, VerificationModeFactory.times(0)).doFilter(request, response); } - - public void testSendRedirectSAMLSSO() throws Exception { - // Given - HttpServletRequest request = mock(HttpServletRequest.class); - HttpServletResponse response = mock(HttpServletResponse.class); - FilterChain chain = mock(FilterChain.class); - - InitiateLoginFilter initiateLoginFilter = mock(InitiateLoginFilter.class); - FilterConfig filterConfig = mock(FilterConfig.class); - ServletContext servletContext = mock(ServletContext.class); - - // When - when(response.encodeRedirectURL(any())).thenAnswer(new Answer() { - public String answer(InvocationOnMock invocation) throws Throwable { - return (String) invocation.getArguments()[0]; - } - }); - when(filterConfig.getServletContext()).thenReturn(servletContext); - when(servletContext.getServletContextName()).thenReturn("portal"); - when(servletContext.getContextPath()).thenReturn("/portal"); - when(request.getContextPath()).thenReturn("/portal"); - - doNothing().when(initiateLoginFilter).processSSOToken(request, response); - - doCallRealMethod().when(initiateLoginFilter).doFilter(request, response, chain); - doCallRealMethod().when(initiateLoginFilter).getLoginRedirectUrl(request); - - doReturn("/portal/dologin").when(initiateLoginFilter).getInitParameter("loginUrl"); - doCallRealMethod().when(initiateLoginFilter).initImpl(); - PropertyManager.setProperty("gatein.sso.uri.suffix", "samlSSO"); - - when(response.encodeRedirectURL(any())).thenAnswer(new Answer() { - public String answer(InvocationOnMock invocation) throws Throwable { - return (String) invocation.getArguments()[0]; - } - }); - - when(request.getAttribute(eq("abort"))).thenReturn("true"); - initiateLoginFilter.init(filterConfig); - initiateLoginFilter.doFilter(request, response, chain); - - // Then - verify(response, VerificationModeFactory.times(1)).sendRedirect(eq("/portal/samlSSO")); - verify(chain, VerificationModeFactory.times(0)).doFilter(request, response); - } } diff --git a/integration/src/main/java/org/gatein/sso/integration/SSODelegateFilter.java b/integration/src/main/java/org/gatein/sso/integration/SSODelegateFilter.java index 4107bab19..158980534 100644 --- a/integration/src/main/java/org/gatein/sso/integration/SSODelegateFilter.java +++ b/integration/src/main/java/org/gatein/sso/integration/SSODelegateFilter.java @@ -28,11 +28,11 @@ import org.exoplatform.services.log.Log; import org.gatein.sso.agent.filter.api.SSOInterceptor; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; import java.io.IOException; import java.util.Iterator; import java.util.Map; diff --git a/integration/src/main/java/org/gatein/sso/integration/SSODelegateValve.java b/integration/src/main/java/org/gatein/sso/integration/SSODelegateValve.java index 138999a33..de870b0ad 100644 --- a/integration/src/main/java/org/gatein/sso/integration/SSODelegateValve.java +++ b/integration/src/main/java/org/gatein/sso/integration/SSODelegateValve.java @@ -29,7 +29,7 @@ import javax.management.MBeanRegistration; import javax.management.MBeanServer; import javax.management.ObjectName; -import javax.servlet.ServletException; +import jakarta.servlet.ServletException; import org.apache.catalina.Contained; import org.apache.catalina.Container; @@ -47,7 +47,7 @@ * Delegates work to another valve configured through option 'delegateValveClassName'. It's possible to disable * delegation by boolean parameter 'ssoDelegationEnabled'. * - * Actually delegation will be enabled only for SSO scenario, which require integration with Tomcat valves (SAML, SPNEGO) + * Actually delegation will be enabled only for SSO scenario, which require integration with Tomcat valves * * @author Marek Posolda */ @@ -64,7 +64,6 @@ public class SSODelegateValve implements Valve, Contained, MBeanRegistration, Li private String delegateValveClassName; // Delegate valve is not null only if we are in SSO mode and delegation is enabled - // Delegate will be either SAML or SPNEGO valve private Valve delegate; // This is not null only if delegation is disabled @@ -73,9 +72,6 @@ public class SSODelegateValve implements Valve, Contained, MBeanRegistration, Li // Catalina context private Container context; - // Used only for SAML2 when acting as SP - private String samlSPConfigFile; - public void setDelegateValveClassName(String delegateValve) { this.delegateValveClassName = substituteSystemProperty(delegateValve); @@ -89,11 +85,6 @@ public void setSsoDelegationEnabled(String enabled) log.debug("ssoDelegationEnabled: " + delegationEnabled); } - public void setSamlSPConfigFile(String configFile) - { - this.samlSPConfigFile = substituteSystemProperty(configFile); - } - public Valve getNext() { if (delegationEnabled) @@ -297,21 +288,6 @@ private Valve getOrLoadDelegate(String className) { throw new RuntimeException("Can't instantiate " + delegateClass, e); } - - // Update location of configFile for SAML2 SP. Little hack but sufficient for our purpose - if (this.samlSPConfigFile != null) - { - try - { - Method m = delegateClass.getMethod("setConfigFile", String.class); - m.invoke(delegate, samlSPConfigFile); - log.info("Picketlink configuration file successfully set to location: " + samlSPConfigFile); - } - catch (Exception e) - { - log.trace("Can't set SAML config file. Method 'setConfigFile' not supported on class " + delegateClass, e); - } - } } return delegate; diff --git a/integration/src/test/java/org/gatein/sso/integration/SSODelegateFilterTest.java b/integration/src/test/java/org/gatein/sso/integration/SSODelegateFilterTest.java index a581390d6..ea3cfafec 100644 --- a/integration/src/test/java/org/gatein/sso/integration/SSODelegateFilterTest.java +++ b/integration/src/test/java/org/gatein/sso/integration/SSODelegateFilterTest.java @@ -9,9 +9,5 @@ public void testIsMappedTo() { assertTrue(ssoDelegateFilter.isMappedTo("/*", "/")); assertTrue(ssoDelegateFilter.isMappedTo(".*", "/")); assertTrue(ssoDelegateFilter.isMappedTo("/sso", "/sso")); - assertFalse(ssoDelegateFilter.isMappedTo("/sso", "/samlsso")); - assertTrue(ssoDelegateFilter.isMappedTo("/.*sso", "/samlsso")); - assertTrue(ssoDelegateFilter.isMappedTo("/.*sso", "/samlsso")); - assertFalse(ssoDelegateFilter.isMappedTo("/.*sso", "/ssosaml")); } } diff --git a/pom.xml b/pom.xml index 7722ac447..1b19051ab 100644 --- a/pom.xml +++ b/pom.xml @@ -37,13 +37,10 @@ auth-callback common-plugin opensso - spnego - spnegosso - saml packaging integration - + 6.6.x-SNAPSHOT @@ -88,16 +85,6 @@ sso-opensso-plugin ${project.version} - - org.exoplatform.gatein.sso - spnego - ${project.version} - - - org.exoplatform.gatein.sso - sso-saml-plugin - ${project.version} - diff --git a/saml/gatein-saml-plugin/pom.xml b/saml/gatein-saml-plugin/pom.xml deleted file mode 100644 index 5957bff42..000000000 --- a/saml/gatein-saml-plugin/pom.xml +++ /dev/null @@ -1,90 +0,0 @@ - - - sso-saml-parent - org.exoplatform.gatein.sso - 6.6.x-SNAPSHOT - ../pom.xml - - - 4.0.0 - org.exoplatform.gatein.sso - sso-saml-plugin - jar - - GateIn SSO - SAML Identity provider plugin - - - 0.07 - - - - - org.jboss.logging - jboss-logging - provided - - - org.apache.tomcat - tomcat-catalina - provided - - - org.apache.httpcomponents - httpclient - - - org.picketlink.distribution - picketlink-wildfly8 - provided - - - org.picketlink - picketlink-common - - - org.picketlink - picketlink-config - - - javax.servlet - javax.servlet-api - - - org.exoplatform.gatein.sso - sso-common-plugin - - - - org.exoplatform.gatein.wci - wci-wci - - - - org.exoplatform.gatein.sso - sso-integration - - - org.exoplatform.gatein.sso - sso-agent - - - org.exoplatform.core - exo.core.component.organization.api - - - org.picketlink - picketlink-federation - - - org.mockito - mockito-core - test - - - junit - junit - test - - - - diff --git a/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/SimpleGroup.java b/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/SimpleGroup.java deleted file mode 100644 index a3d719ee5..000000000 --- a/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/SimpleGroup.java +++ /dev/null @@ -1,157 +0,0 @@ -/** -* JBoss, Home of Professional Open Source -* Copyright 2005, JBoss Inc., and individual contributors as indicated -* by the @authors tag. See the copyright.txt in the distribution for a -* full listing of individual contributors. -* -* This 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 2.1 of -* the License, or (at your option) any later version. -* -* This software 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 software; if not, write to the Free -* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -* 02110-1301 USA, or see the FSF site: http://www.fsf.org. -*/ -package org.gatein.sso.saml.plugin; - -import java.security.Principal; -import java.util.*; - - -/** - * Forked class because this plugin can be used on both JBoss or Tomcat and we want to be independent on AS. - * - * An implementation of Group that manages a collection of Principal - *objects based on their hashCode() and equals() methods. This class - * is not thread safe. - * @author Scott.Stark@jboss.org - * @version $Revision$ - */ -@SuppressWarnings({"rawtypes","unchecked"}) -public class SimpleGroup extends SimplePrincipal implements Cloneable -{ - /** The serialVersionUID */ - private static final long serialVersionUID = 605185963957807247L; - - private HashMap members; - - public SimpleGroup(String groupName) - { - super(groupName); - members = new HashMap(3); - } - - /** Adds the specified member to the group. - @param user the principal to add to this group. - @return true if the member was successfully added, - false if the principal was already a member. - */ - public boolean addMember(Principal user) - { - boolean isMember = members.containsKey(user); - if( isMember == false ) - members.put(user, user); - return isMember == false; - } - - /** Returns true if the passed principal is a member of the group. - This method does a recursive search, so if a principal belongs to a - group which is a member of this group, true is returned. - - A special check is made to see if the member is an instance of - org.jboss.security.AnybodyPrincipal or org.jboss.security.NobodyPrincipal - since these classes do not hash to meaningful values. - @param member the principal whose membership is to be checked. - @return true if the principal is a member of this group, - false otherwise. - */ - public boolean isMember(Principal member) - { - // First see if there is a key with the member name - boolean isMember = members.containsKey(member); - - if( isMember == false ) - { // Check any Groups for membership - Collection values = members.values(); - Iterator iter = values.iterator(); - while( isMember == false && iter.hasNext() ) - { - Object next = iter.next(); - if( next instanceof SimpleGroup ) - { - SimpleGroup group = (SimpleGroup) next; - isMember = group.isMember(member); - } - } - } - - return isMember; - } - - /** Returns an enumeration of the members in the group. - The returned objects can be instances of either Principal - or Group (which is a subinterface of Principal). - @return an enumeration of the group members. - */ - public Enumeration members() - { - return Collections.enumeration(members.values()); - } - - /** Removes the specified member from the group. - @param user the principal to remove from this group. - @return true if the principal was removed, or - false if the principal was not a member. - */ - public boolean removeMember(Principal user) - { - Object prev = members.remove(user); - return prev != null; - } - - public String toString() - { - StringBuffer tmp = new StringBuffer(getName()); - tmp.append("(members:"); - Iterator iter = members.keySet().iterator(); - while( iter.hasNext() ) - { - tmp.append(iter.next()); - tmp.append(','); - } - tmp.setCharAt(tmp.length()-1, ')'); - return tmp.toString(); - } - - public synchronized Object clone() throws CloneNotSupportedException - { - SimpleGroup clone = (SimpleGroup) super.clone(); - if(clone != null) - clone.members = (HashMap)this.members.clone(); - return clone; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (o == null || getClass() != o.getClass()) - return false; - if (!super.equals(o)) - return false; - SimpleGroup that = (SimpleGroup) o; - return Objects.equals(members, that.members); - } - - @Override - public int hashCode() { - return Objects.hash(super.hashCode(), members); - } -} \ No newline at end of file diff --git a/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/SimplePrincipal.java b/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/SimplePrincipal.java deleted file mode 100644 index 14a6cf399..000000000 --- a/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/SimplePrincipal.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * JBoss, Home of Professional Open Source - * Copyright 2005, JBoss Inc., and individual contributors as indicated - * by the @authors tag. See the copyright.txt in the distribution for a - * full listing of individual contributors. - * - * This 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 2.1 of - * the License, or (at your option) any later version. - * - * This software 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 software; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA, or see the FSF site: http://www.fsf.org. - */ -package org.gatein.sso.saml.plugin; - -import java.io.Serializable; -import java.security.Principal; - -/** - * Forked class because this plugin can be used on both JBoss or Tomcat and we want to be independent on AS. - * - * @author Oleg Nitz - * @author Scott.Stark@jboss.org - */ -public class SimplePrincipal implements Principal, Serializable -{ - private static final long serialVersionUID = 7701951188631723290L; - private final String name; - - public SimplePrincipal(String name) - { - this.name = name; - } - - /** - * Compare this SimplePrincipal's name against another Principal. If system property - * org.jboss.security.simpleprincipal.equals.override is set to true will only - * compare instances of SimplePrincipals. - * @return true if name equals another.getName(); - */ - @Override - public boolean equals(Object another) - { - String anotherName = ((Principal) another).getName(); - boolean equals = false; - if (name == null) - equals = anotherName == null; - else - equals = name.equals(anotherName); - return equals; - } - - @Override - public int hashCode() - { - return (name == null ? 0 : name.hashCode()); - } - - @Override - public String toString() - { - return name; - } - - public String getName() - { - return name; - } -} \ No newline at end of file diff --git a/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/filter/EmptyFilterChain.java b/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/filter/EmptyFilterChain.java deleted file mode 100644 index 3e02610c6..000000000 --- a/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/filter/EmptyFilterChain.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.gatein.sso.saml.plugin.filter; - -import java.io.IOException; - -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; - -/** - * Used to avoid calling chain.doFilter in parent classes when needed - * This will avoid duplicating source code to delete unnecessary code - */ -public class EmptyFilterChain implements FilterChain { - - @Override - public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { - // Nothing to do - } - -} diff --git a/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/filter/PortalIDPWebBrowserSSOFilter.java b/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/filter/PortalIDPWebBrowserSSOFilter.java deleted file mode 100644 index 7848ae465..000000000 --- a/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/filter/PortalIDPWebBrowserSSOFilter.java +++ /dev/null @@ -1,214 +0,0 @@ -package org.gatein.sso.saml.plugin.filter; - -import java.io.IOException; -import java.net.URLEncoder; -import java.security.Principal; - -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; - -import org.apache.commons.lang.StringUtils; -import org.exoplatform.services.log.ExoLogger; -import org.exoplatform.services.log.Log; -import org.gatein.sso.agent.filter.api.SSOInterceptor; -import org.gatein.sso.agent.filter.api.SSOInterceptorInitializationContext; -import org.picketlink.common.constants.GeneralConstants; -import org.picketlink.identity.federation.web.filters.IDPFilter; - -import org.exoplatform.container.ExoContainer; -import org.exoplatform.container.ExoContainerContext; -import org.exoplatform.container.PortalContainer; -import org.exoplatform.container.RootContainer; -import org.exoplatform.container.util.ContainerUtil; -import org.exoplatform.container.xml.InitParams; - -public class PortalIDPWebBrowserSSOFilter extends IDPFilter implements SSOInterceptor { - - public static final String ORIGINAL_HTTP_SERVLET_REQUEST_PARAM = "OriginalHttpServletRequest"; - - private static final Log log = - ExoLogger.getLogger(PortalIDPWebBrowserSSOFilter.class); - - /** - * The filter configuration - */ - protected FilterConfig config; - - /** - * The Servlet context name - */ - protected String servletContextName; - - /** - * Indicates if we need a portal environment. - */ - private volatile Boolean requirePortalEnvironment; - - private SSOInterceptorInitializationContext interceptorContext; - - /** - * {@inheritDoc} - */ - public final void init(FilterConfig config) throws ServletException { - this.config = getFilterConfig(config); - this.servletContextName = ContainerUtil.getServletContextName(config.getServletContext()); - afterInit(config); - } - - @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { - HttpServletRequest httpServletRequest = (HttpServletRequest) request; - HttpServletResponse httpServletResponse = (HttpServletResponse) response; - HttpSession session = httpServletRequest.getSession(true); - - // get an authenticated user or tries to authenticate if this is a - // authentication request - Principal userPrincipal = httpServletRequest.getUserPrincipal(); - String samlRequestMessage = (String) request.getParameter(GeneralConstants.SAML_REQUEST_KEY); - - // If this is a SAML Request but no user is authenticated, then redirect to - // login page - if (userPrincipal == null && StringUtils.isNotBlank(samlRequestMessage)) { - session.setAttribute(ORIGINAL_HTTP_SERVLET_REQUEST_PARAM, httpServletRequest); - - httpServletResponse.sendRedirect("/" + servletContextName + "/dologin?initialURI=" - + URLEncoder.encode(httpServletRequest.getRequestURI(), "UTF-8")); - return; - } else { - final HttpServletRequest originalHttpServletRequest = - (HttpServletRequest) session.getAttribute(ORIGINAL_HTTP_SERVLET_REQUEST_PARAM); - if (originalHttpServletRequest != null) { - request = new SAMLHTTPRequestWrapper(httpServletRequest, originalHttpServletRequest); - session.removeAttribute(ORIGINAL_HTTP_SERVLET_REQUEST_PARAM); - } - } - - super.doFilter(request, response, chain); - } - - /** - * @return Gives the {@link ExoContainer} that fits best with the current - * context - */ - private final ExoContainer getContainer() { - ExoContainer container = ExoContainerContext.getCurrentContainer(); - if (container instanceof RootContainer) { - container = interceptorContext.getExoContainer(); - } - if (container instanceof RootContainer) { - // The top container is a RootContainer, thus we assume that we are in a - // portal mode - container = PortalContainer.getInstance(); - } - // The container is a PortalContainer or a StandaloneContainer - return container; - } - - /** - * Method is invoked if we are performing initialization through servlet api - * (web filter) - */ - private final void afterInit(FilterConfig filterConfig) throws ServletException { - this.interceptorContext = new SSOInterceptorInitializationContext(filterConfig, null, null); - log.debug("Interceptor initialized with context " + interceptorContext); - try { - initImpl(); - } catch (ServletException e) { - log.error("Error initializing SAML Filter", e); - } - } - - /** - * Method is invoked if we are performing initialization through exo kernel - */ - public final void initWithParams(InitParams params, ExoContainerContext containerContext) { - this.interceptorContext = new SSOInterceptorInitializationContext(null, params, containerContext); - this.servletContextName = containerContext.getPortalContainerName(); - log.debug("Interceptor initialized with context " + interceptorContext); - try { - initImpl(); - } catch (ServletException e) { - log.error("Error initializing SAML Filter", e); - } - } - - /** - * This method needs to be implemented by conrete filter. Filter should obtain - * it's init parameters by calling {@link #getInitParameter(String)}. This - * works in both types of initialization (Case1: Filter initialization through - * kernel, Case2: initialization through servlet API) - * - * @throws ServletException an init exception happens when calling super class init method - */ - protected void initImpl() throws ServletException { - FilterConfig filterConfig = getFilterConfig(null); - if (this.servletContextName == null) { - this.servletContextName = ContainerUtil.getServletContextName(getServletContext()); - } - filterConfig.getServletContext().setInitParameter(GeneralConstants.CONFIG_FILE, - getInitParameter(GeneralConstants.CONFIG_FILE)); - super.init(filterConfig); - } - - /** - * Read init parameter (works for both kernel initialization or Servlet API - * initialization) - * - * @param paramName parameter name - * @return parameter value - */ - protected String getInitParameter(String paramName) { - return interceptorContext.getInitParameter(paramName); - } - - /** - * Indicates if it requires that a full portal environment must be set - * - * @return true if it requires the portal environment - * false otherwise. - */ - protected boolean requirePortalEnvironment() { - if (requirePortalEnvironment == null) { - synchronized (this) { - if (requirePortalEnvironment == null) { - this.requirePortalEnvironment = PortalContainer.isPortalContainerName(servletContextName); - } - } - } - return requirePortalEnvironment.booleanValue(); - } - - /** - * @return the current {@link ServletContext} - */ - protected ServletContext getServletContext() { - if (requirePortalEnvironment()) { - ExoContainer container = getContainer(); - if (container instanceof PortalContainer) { - return ((PortalContainer) container).getPortalContext(); - } - } - if (this.config != null) { - return this.config.getServletContext(); - } - return null; - } - - private FilterConfig getFilterConfig(FilterConfig config) { - if (this.config == null) { - if (config == null) { - this.config = new SAMLFilterConfig("PortalIDPWebBrowserSSOFilter", getServletContext(), interceptorContext); - } else { - this.config = config; - } - } - return this.config; - } -} diff --git a/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/filter/SAML2LogoutFilter.java b/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/filter/SAML2LogoutFilter.java deleted file mode 100644 index 58522abac..000000000 --- a/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/filter/SAML2LogoutFilter.java +++ /dev/null @@ -1,241 +0,0 @@ -package org.gatein.sso.saml.plugin.filter; - -import java.io.IOException; - -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletRequestWrapper; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.lang.StringUtils; -import org.exoplatform.services.log.ExoLogger; -import org.exoplatform.services.log.Log; -import org.gatein.sso.agent.filter.api.SSOInterceptor; -import org.gatein.sso.agent.filter.api.SSOInterceptorInitializationContext; -import org.picketlink.common.constants.GeneralConstants; -import org.picketlink.identity.federation.web.filters.SPFilter; - -import org.exoplatform.container.ExoContainer; -import org.exoplatform.container.ExoContainerContext; -import org.exoplatform.container.PortalContainer; -import org.exoplatform.container.RootContainer; -import org.exoplatform.container.util.ContainerUtil; -import org.exoplatform.container.xml.InitParams; - -public class SAML2LogoutFilter extends SPFilter implements SSOInterceptor { - - public static final String SAML_LOGOUT_ATTRIBUTE = "SAML_LOGOUT_IN_PROGRESS"; - - private static final Log log = ExoLogger.getLogger(SAML2LogoutFilter.class); - - public static final String COOKIE_NAME = "rememberme"; - - public static final String OAUTH_COOKIE_NAME = "oauth_rememberme"; - - /** - * The filter configuration - */ - protected FilterConfig config; - - /** - * The Servlet context name - */ - protected String servletContextName; - - /** - * Indicates if we need a portal environment. - */ - private volatile Boolean requirePortalEnvironment; - - private SSOInterceptorInitializationContext interceptorContext; - - /** - * {@inheritDoc} - */ - public final void init(FilterConfig config) throws ServletException { - this.config = getFilterConfig(config); - this.servletContextName = ContainerUtil.getServletContextName(config.getServletContext()); - afterInit(config); - } - - @Override - public void doFilter(ServletRequest servletRequest, - ServletResponse servletResponse, - FilterChain filterChain) throws IOException, ServletException { - HttpServletRequest request = (HttpServletRequest) servletRequest; - HttpServletResponse response = (HttpServletResponse) servletResponse; - request.setCharacterEncoding("UTF-8"); - if (isPortalLogoutInProgress(request)) { - if(StringUtils.isBlank(getPortalLogoutURLFromSession(request))) { - // Step 1 : Begin - call logout action - HttpServletRequestWrapper requestWrapper = new HttpServletRequestWrapper(request) { - @Override - public String getParameter(String name) { - if (StringUtils.equals("GLO", name)) { - return "true"; - } - return super.getParameter(name); - } - }; - // Step 1 : End - logout from the IDP (redirect to IDP logout URL) - super.doFilter(requestWrapper, servletResponse, new EmptyFilterChain()); - request.getSession().setAttribute(SAML_LOGOUT_ATTRIBUTE, request.getRequestURI() + "?" + request.getQueryString()); - } else { - // Step 3 : Call UIPortal.LogoutActionListener - filterChain.doFilter(servletRequest, servletResponse); - try { - // Step 4: Ensure that the session is invalidated - request.getSession().invalidate(); - } catch (IllegalStateException e) { - // The session may be already invalidated - } - } - } else if (isSAMLLogoutInProgress(request)) { - // Step 2 : logout local session from the SP (redirect UIPortal.LogoutActionListener) - response.sendRedirect(getPortalLogoutURLFromSession(request)); - } else { - // Regular request - filterChain.doFilter(servletRequest, servletResponse); - } - } - - private static String getPortalLogoutURLFromSession(HttpServletRequest request) { - return request.getSession().getAttribute(SAML_LOGOUT_ATTRIBUTE) == null ? null - : request.getSession() - .getAttribute(SAML_LOGOUT_ATTRIBUTE) - .toString(); - } - - public static boolean isPortalLogoutInProgress(HttpServletRequest request) { - return request.getQueryString() != null && request.getQueryString().contains("portal:action=Logout") && request.getRemoteUser() != null; - } - - public static boolean isSAMLLogoutInProgress(HttpServletRequest request) { - return request.getRemoteUser() != null && StringUtils.isNotBlank(getPortalLogoutURLFromSession(request)) - && !StringUtils.equals(getPortalLogoutURLFromSession(request), "DONE"); - } - - /** - * @return Gives the {@link ExoContainer} that fits best with the current - * context - */ - private final ExoContainer getContainer() { - ExoContainer container = ExoContainerContext.getCurrentContainer(); - if (container instanceof RootContainer) { - container = interceptorContext.getExoContainer(); - } - if (container instanceof RootContainer) { - // The top container is a RootContainer, thus we assume that we are in a - // portal mode - container = PortalContainer.getInstance(); - } - // The container is a PortalContainer or a StandaloneContainer - return container; - } - - /** - * Method is invoked if we are performing initialization through servlet api - * (web filter) - */ - private final void afterInit(FilterConfig filterConfig) throws ServletException { - this.interceptorContext = new SSOInterceptorInitializationContext(filterConfig, null, null); - log.debug("Interceptor initialized with context " + interceptorContext); - try { - initImpl(); - } catch (ServletException e) { - log.error("Error initializing SAML Filter", e); - } - } - - /** - * Method is invoked if we are performing initialization through exo kernel - */ - public final void initWithParams(InitParams params, ExoContainerContext containerContext) { - this.interceptorContext = new SSOInterceptorInitializationContext(null, params, containerContext); - this.servletContextName = containerContext.getPortalContainerName(); - log.debug("Interceptor initialized with context " + interceptorContext); - try { - initImpl(); - } catch (ServletException e) { - log.error("Error initializing SAML Filter", e); - } - } - - /** - * This method needs to be implemented by conrete filter. Filter should obtain - * it's init parameters by calling {@link #getInitParameter(String)}. This - * works in both types of initialization (Case1: Filter initialization through - * kernel, Case2: initialization through servlet API) - * - * @throws ServletException an init exception happens when calling super class init method - */ - protected void initImpl() throws ServletException { - FilterConfig filterConfig = getFilterConfig(null); - if (this.servletContextName == null) { - this.servletContextName = ContainerUtil.getServletContextName(getServletContext()); - } - this.configFile = SAMLSPServletContextWrapper.FILE_PREFIX + getInitParameter(GeneralConstants.CONFIG_FILE); - super.init(filterConfig); - } - - /** - * Read init parameter (works for both kernel initialization or Servlet API - * initialization) - * - * @param paramName parameter name - * @return parameter value - */ - protected String getInitParameter(String paramName) { - return interceptorContext.getInitParameter(paramName); - } - - /** - * Indicates if it requires that a full portal environment must be set - * - * @return true if it requires the portal environment - * false otherwise. - */ - protected boolean requirePortalEnvironment() { - if (requirePortalEnvironment == null) { - synchronized (this) { - if (requirePortalEnvironment == null) { - this.requirePortalEnvironment = PortalContainer.isPortalContainerName(servletContextName); - } - } - } - return requirePortalEnvironment.booleanValue(); - } - - /** - * @return the current {@link ServletContext} - */ - protected ServletContext getServletContext() { - if (requirePortalEnvironment()) { - ExoContainer container = getContainer(); - if (container instanceof PortalContainer) { - return ((PortalContainer) container).getPortalContext(); - } - } - if (this.config != null) { - return this.config.getServletContext(); - } - return null; - } - - private FilterConfig getFilterConfig(FilterConfig config) { - if (this.config == null) { - if (config == null) { - ServletContext servletContext = new SAMLSPServletContextWrapper(getServletContext()); - this.config = new SAMLFilterConfig("SAML2LogoutFilter", servletContext, interceptorContext); - } else { - this.config = config; - } - } - return this.config; - } -} diff --git a/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/filter/SAMLFilterConfig.java b/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/filter/SAMLFilterConfig.java deleted file mode 100644 index 07ed65984..000000000 --- a/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/filter/SAMLFilterConfig.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.gatein.sso.saml.plugin.filter; - -import java.util.Enumeration; - -import javax.servlet.FilterConfig; -import javax.servlet.ServletContext; - -import org.gatein.sso.agent.filter.api.SSOInterceptorInitializationContext; - -/** - * This HTTP FilterConfig allows to inject some eXo Kernel Init Params - * to Servlet Context Init Params - */ -public class SAMLFilterConfig implements FilterConfig { - private String filterName; - - private ServletContext servletContext; - - private SSOInterceptorInitializationContext interceptorContext; - - public SAMLFilterConfig(String filterName, - ServletContext servletContext, - SSOInterceptorInitializationContext interceptorContext) { - this.filterName = filterName; - this.servletContext = servletContext; - this.interceptorContext = interceptorContext; - } - - @Override - public ServletContext getServletContext() { - return servletContext; - } - - @Override - public Enumeration getInitParameterNames() { - return null; - } - - @Override - public String getInitParameter(String name) { - return interceptorContext.getInitParameter(name); - } - - @Override - public String getFilterName() { - return filterName; - } -} diff --git a/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/filter/SAMLHTTPRequestWrapper.java b/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/filter/SAMLHTTPRequestWrapper.java deleted file mode 100644 index df81b2405..000000000 --- a/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/filter/SAMLHTTPRequestWrapper.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.gatein.sso.saml.plugin.filter; - -import java.util.Enumeration; -import java.util.Map; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletRequestWrapper; - -/** - * This class is used to combine two HTTP Request datas - */ -public class SAMLHTTPRequestWrapper extends HttpServletRequestWrapper { - private final HttpServletRequest originalHttpServletRequest; - - public SAMLHTTPRequestWrapper(HttpServletRequest request, HttpServletRequest originalHttpServletRequest) { - super(request); - this.originalHttpServletRequest = originalHttpServletRequest; - } - - @Override - public String getParameter(String name) { - return originalHttpServletRequest.getParameter(name); - } - - @Override - public Map getParameterMap() { - return originalHttpServletRequest.getParameterMap(); - } - - @Override - public String[] getParameterValues(String name) { - return originalHttpServletRequest.getParameterValues(name); - } - - @Override - public String getMethod() { - return originalHttpServletRequest.getMethod(); - } - - @Override - public String getHeader(String name) { - return originalHttpServletRequest.getHeader(name); - } - - @Override - public Enumeration getHeaders(String name) { - return originalHttpServletRequest.getHeaders(name); - } - - @Override - public Enumeration getHeaderNames() { - return originalHttpServletRequest.getHeaderNames(); - } -} diff --git a/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/filter/SAMLSPServletContextWrapper.java b/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/filter/SAMLSPServletContextWrapper.java deleted file mode 100644 index 2f44fdce9..000000000 --- a/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/filter/SAMLSPServletContextWrapper.java +++ /dev/null @@ -1,376 +0,0 @@ -package org.gatein.sso.saml.plugin.filter; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.Enumeration; -import java.util.EventListener; -import java.util.Map; -import java.util.Set; - -import javax.servlet.Filter; -import javax.servlet.FilterRegistration; -import javax.servlet.FilterRegistration.Dynamic; -import javax.servlet.RequestDispatcher; -import javax.servlet.Servlet; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.ServletRegistration; -import javax.servlet.SessionCookieConfig; -import javax.servlet.SessionTrackingMode; -import javax.servlet.descriptor.JspConfigDescriptor; - -import org.exoplatform.services.log.ExoLogger; -import org.exoplatform.services.log.Log; - -/** - * This class wraps an HTTP ServletContext to be able to get - * a configuration file from local folder outside the webapp - */ -public class SAMLSPServletContextWrapper implements ServletContext { - public static final String FILE_PREFIX = "file:"; - - public static final Log log = ExoLogger.getLogger(PortalIDPWebBrowserSSOFilter.class); - - private ServletContext delegate; - - public SAMLSPServletContextWrapper(ServletContext delegate) { - this.delegate = delegate; - } - - @Override - public Dynamic addFilter(String arg0, String arg1) { - return delegate.addFilter(arg0, arg1); - } - - @Override - public Dynamic addFilter(String arg0, Filter arg1) { - return delegate.addFilter(arg0, arg1); - } - - @Override - public Dynamic addFilter(String arg0, Class arg1) { - return delegate.addFilter(arg0, arg1); - } - - @Override - public void addListener(String arg0) { - delegate.addListener(arg0); - } - - @Override - public void addListener(T arg0) { - delegate.addListener(arg0); - } - - @Override - public void addListener(Class arg0) { - delegate.addListener(arg0); - } - - @Override - public javax.servlet.ServletRegistration.Dynamic addServlet(String arg0, String arg1) { - return delegate.addServlet(arg0, arg1); - } - - @Override - public javax.servlet.ServletRegistration.Dynamic addServlet(String arg0, Servlet arg1) { - return delegate.addServlet(arg0, arg1); - } - - @Override - public javax.servlet.ServletRegistration.Dynamic addServlet(String arg0, Class arg1) { - return delegate.addServlet(arg0, arg1); - } - - @Override - public T createFilter(Class arg0) throws ServletException { - return delegate.createFilter(arg0); - } - - @Override - public T createListener(Class arg0) throws ServletException { - return delegate.createListener(arg0); - } - - @Override - public T createServlet(Class arg0) throws ServletException { - return delegate.createServlet(arg0); - } - - @Override - public void declareRoles(String... arg0) { - delegate.declareRoles(arg0); - } - - @Override - public Object getAttribute(String arg0) { - return delegate.getAttribute(arg0); - } - - @Override - public Enumeration getAttributeNames() { - return delegate.getAttributeNames(); - } - - @Override - public ClassLoader getClassLoader() { - return delegate.getClassLoader(); - } - - @Override - public ServletContext getContext(String arg0) { - return delegate.getContext(arg0); - } - - @Override - public String getContextPath() { - return delegate.getContextPath(); - } - - @Override - public Set getDefaultSessionTrackingModes() { - return delegate.getDefaultSessionTrackingModes(); - } - - @Override - public int getEffectiveMajorVersion() { - return delegate.getEffectiveMajorVersion(); - } - - @Override - public int getEffectiveMinorVersion() { - return delegate.getEffectiveMinorVersion(); - } - - @Override - public Set getEffectiveSessionTrackingModes() { - return delegate.getEffectiveSessionTrackingModes(); - } - - @Override - public FilterRegistration getFilterRegistration(String arg0) { - return delegate.getFilterRegistration(arg0); - } - - @Override - public Map getFilterRegistrations() { - return delegate.getFilterRegistrations(); - } - - @Override - public String getInitParameter(String arg0) { - return delegate.getInitParameter(arg0); - } - - @Override - public Enumeration getInitParameterNames() { - return delegate.getInitParameterNames(); - } - - @Override - public JspConfigDescriptor getJspConfigDescriptor() { - return delegate.getJspConfigDescriptor(); - } - - @Override - public int getMajorVersion() { - return delegate.getMajorVersion(); - } - - @Override - public String getMimeType(String arg0) { - return delegate.getMimeType(arg0); - } - - @Override - public int getMinorVersion() { - return delegate.getMinorVersion(); - } - - @Override - public RequestDispatcher getNamedDispatcher(String arg0) { - return delegate.getNamedDispatcher(arg0); - } - - @Override - public String getRealPath(String arg0) { - return delegate.getRealPath(arg0); - } - - @Override - public RequestDispatcher getRequestDispatcher(String arg0) { - return delegate.getRequestDispatcher(arg0); - } - - @Override - public URL getResource(String arg0) throws MalformedURLException { - if (isFSResolvable(arg0)) { - return getFSResource(arg0); - } - return delegate.getResource(arg0); - } - - @Override - public InputStream getResourceAsStream(String arg0) { - if (isFSResolvable(arg0)) { - try { - URL fsResource = getFSResource(arg0); - if (fsResource != null) { - return fsResource.openStream(); - } - } catch (IOException e) { - log.warn("Error occurred when retieving file" + arg0, e); - } - } - return delegate.getResourceAsStream(arg0); - } - - @Override - public Set getResourcePaths(String arg0) { - return delegate.getResourcePaths(arg0); - } - - @Override - public String getServerInfo() { - return delegate.getServerInfo(); - } - - @SuppressWarnings("deprecation") - @Override - public Servlet getServlet(String arg0) throws ServletException { - return delegate.getServlet(arg0); - } - - @Override - public String getServletContextName() { - return delegate.getServletContextName(); - } - - @SuppressWarnings("deprecation") - @Override - public Enumeration getServletNames() { - return delegate.getServletNames(); - } - - @Override - public ServletRegistration getServletRegistration(String arg0) { - return delegate.getServletRegistration(arg0); - } - - @Override - public Map getServletRegistrations() { - return delegate.getServletRegistrations(); - } - - @SuppressWarnings("deprecation") - @Override - public Enumeration getServlets() { - return delegate.getServlets(); - } - - @Override - public SessionCookieConfig getSessionCookieConfig() { - return delegate.getSessionCookieConfig(); - } - - @Override - public void log(String arg0) { - delegate.log(arg0); - } - - @SuppressWarnings("deprecation") - @Override - public void log(Exception arg0, String arg1) { - delegate.log(arg0, arg1); - } - - @Override - public void log(String arg0, Throwable arg1) { - delegate.log(arg0, arg1); - } - - @Override - public void removeAttribute(String arg0) { - delegate.removeAttribute(arg0); - } - - @Override - public void setAttribute(String arg0, Object arg1) { - delegate.setAttribute(arg0, arg1); - } - - @Override - public boolean setInitParameter(String arg0, String arg1) { - return delegate.setInitParameter(arg0, arg1); - } - - @Override - public void setSessionTrackingModes(Set arg0) { - delegate.setSessionTrackingModes(arg0); - } - - @SuppressWarnings("deprecation") - public URL getFSResource(String url) throws MalformedURLException { - String path = removeScheme(url); - File file = new File(path); - if (file.exists() && file.isFile()) - return file.toURL(); - return null; - } - - protected String removeScheme(String url) { - String scheme = FILE_PREFIX; - if (url.startsWith(scheme)) { - return url.substring(scheme.length()); - } - return url; - } - - public boolean isFSResolvable(String url) { - return url.startsWith(FILE_PREFIX); - } - - @Override - public String getVirtualServerName() { - return delegate.getVirtualServerName(); - } - - @Override - public javax.servlet.ServletRegistration.Dynamic addJspFile(String servletName, String jspFile) { - return delegate.addJspFile(servletName, jspFile); - } - - @Override - public int getSessionTimeout() { - return delegate.getSessionTimeout(); - } - - @Override - public void setSessionTimeout(int sessionTimeout) { - delegate.setSessionTimeout(sessionTimeout); - } - - @Override - public String getRequestCharacterEncoding() { - return delegate.getRequestCharacterEncoding(); - } - - @Override - public void setRequestCharacterEncoding(String encoding) { - delegate.setRequestCharacterEncoding(encoding); - } - - @Override - public String getResponseCharacterEncoding() { - return delegate.getResponseCharacterEncoding(); - } - - @Override - public void setResponseCharacterEncoding(String encoding) { - delegate.setResponseCharacterEncoding(encoding); - } - -} diff --git a/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/listener/IDPHttpSessionListener.java b/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/listener/IDPHttpSessionListener.java deleted file mode 100644 index deec0c39e..000000000 --- a/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/listener/IDPHttpSessionListener.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * JBoss, a division of Red Hat - * Copyright 2012, Red Hat Middleware, LLC, and individual - * contributors as indicated by the @authors tag. See the - * copyright.txt in the distribution for a full listing of - * individual contributors. - * - * This 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 2.1 of - * the License, or (at your option) any later version. - * - * This software 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 software; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA, or see the FSF site: http://www.fsf.org. - */ - -package org.gatein.sso.saml.plugin.listener; - -import org.exoplatform.services.log.ExoLogger; -import org.exoplatform.services.log.Log; -import org.gatein.sso.integration.SSOUtils; - -import javax.servlet.http.HttpSessionEvent; -import javax.servlet.http.HttpSessionListener; - -/** - * Class exists to avoid dependency on picketlink module from gatein.ear and use it only during SAML2 setup - * - * @author Marek Posolda - */ -public class IDPHttpSessionListener implements HttpSessionListener -{ - private static final Log log = ExoLogger.getLogger(IDPHttpSessionListener.class); - - private static final String PROPERTY_IDP_ENABLED = "gatein.sso.idp.listener.enabled"; - - private volatile HttpSessionListener delegate; - - public void sessionDestroyed(HttpSessionEvent se) - { - if ("true".equals(SSOUtils.getSystemProperty(PROPERTY_IDP_ENABLED, "false"))) - { - HttpSessionListener delegate = getOrInitDelegate(); - delegate.sessionDestroyed(se); - } - else - { - if (log.isTraceEnabled()) - { - log.trace("Portal is not acting as SAML2 IDP. Ignore this listener"); - } - } - } - - public void sessionCreated(HttpSessionEvent se) - { - } - - private HttpSessionListener getOrInitDelegate() - { - if (delegate == null) - { - synchronized (this) - { - if (delegate == null) - { - delegate = new org.picketlink.identity.federation.web.listeners.IDPHttpSessionListener(); - } - } - } - - return delegate; - } -} diff --git a/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/valve/AbstractSAML11SPRedirectFormAuthenticator.java b/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/valve/AbstractSAML11SPRedirectFormAuthenticator.java deleted file mode 100644 index b2505b45e..000000000 --- a/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/valve/AbstractSAML11SPRedirectFormAuthenticator.java +++ /dev/null @@ -1,140 +0,0 @@ -package org.gatein.sso.saml.plugin.valve; - -import static org.picketlink.common.util.StringUtil.isNotNull; - -import java.io.IOException; -import java.io.InputStream; -import java.security.Principal; -import java.util.ArrayList; -import java.util.List; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.catalina.LifecycleException; -import org.apache.catalina.Session; -import org.apache.catalina.authenticator.Constants; -import org.apache.catalina.connector.Request; -import org.apache.tomcat.util.descriptor.web.LoginConfig; -import org.picketlink.common.ErrorCodes; -import org.picketlink.common.constants.GeneralConstants; -import org.picketlink.identity.federation.bindings.tomcat.sp.SPUtil; -import org.picketlink.identity.federation.bindings.tomcat.sp.holder.ServiceProviderSAMLContext; -import org.picketlink.identity.federation.core.parsers.saml.SAMLParser; -import org.picketlink.identity.federation.core.saml.v2.util.AssertionUtil; -import org.picketlink.identity.federation.saml.v1.assertion.SAML11AssertionType; -import org.picketlink.identity.federation.saml.v1.assertion.SAML11AuthenticationStatementType; -import org.picketlink.identity.federation.saml.v1.assertion.SAML11StatementAbstractType; -import org.picketlink.identity.federation.saml.v1.assertion.SAML11SubjectType; -import org.picketlink.identity.federation.saml.v1.protocol.SAML11ResponseType; -import org.picketlink.identity.federation.web.util.RedirectBindingUtil; -import org.picketlink.identity.federation.web.util.ServerDetector; - -/** - * Authenticator for SAML 1.1 processing at the Service Provider - * forked from org.picketlink.identity.federation.bindings.tomcat.sp.AbstractSAML11SPRedirectFormAuthenticator - * and made compatible with Tomcat 8.5 since picketlink doesn't provide such a support - */ -public abstract class AbstractSAML11SPRedirectFormAuthenticator extends AbstractSPFormAuthenticator { - - @Override - public boolean authenticate(Request request, HttpServletResponse response) throws IOException { - LoginConfig loginConfig = request.getContext().getLoginConfig(); - return authenticate(request, response, loginConfig); - } - - public boolean authenticate(Request request, HttpServletResponse response, LoginConfig loginConfig) throws IOException { - if (handleSAML11UnsolicitedResponse(request, response, loginConfig, this)) { - return true; - } - - logger.trace("Falling back on local Form Authentication if available"); - // fallback - return super.authenticate(request, response); - } - - public static boolean handleSAML11UnsolicitedResponse(Request request, HttpServletResponse response, LoginConfig loginConfig, AbstractSPFormAuthenticator formAuthenticator) throws IOException { - String samlResponse = request.getParameter(GeneralConstants.SAML_RESPONSE_KEY); - - Principal principal = request.getUserPrincipal(); - - // If we have already authenticated the user and there is no request from IDP or logout from user - if (principal != null) - return true; - - Session session = request.getSessionInternal(true); - - // See if we got a response from IDP - if (isNotNull(samlResponse)) { - boolean isValid = false; - try { - isValid = formAuthenticator.validate(request); - } catch (Exception e) { - logger.samlSPHandleRequestError(e); - throw new IOException(); - } - if (!isValid) - throw new IOException(ErrorCodes.VALIDATION_CHECK_FAILED); - - try { - InputStream base64DecodedResponse = RedirectBindingUtil.base64DeflateDecode(samlResponse); - SAMLParser parser = new SAMLParser(); - SAML11ResponseType saml11Response = (SAML11ResponseType) parser.parse(base64DecodedResponse); - - List assertions = saml11Response.get(); - if (assertions.size() > 1) { - logger.trace("More than one assertion from IDP. Considering the first one."); - } - String username = null; - List roles = new ArrayList(); - SAML11AssertionType assertion = assertions.get(0); - if (assertion != null) { - // Get the subject - List statements = assertion.getStatements(); - for (SAML11StatementAbstractType statement : statements) { - if (statement instanceof SAML11AuthenticationStatementType) { - SAML11AuthenticationStatementType subStat = (SAML11AuthenticationStatementType) statement; - SAML11SubjectType subject = subStat.getSubject(); - username = subject.getChoice().getNameID().getValue(); - } - } - roles = AssertionUtil.getRoles(assertion, null); - } - - String password = ServiceProviderSAMLContext.EMPTY_PASSWORD; - - // Map to JBoss specific principal - if ((new ServerDetector()).isJboss() || formAuthenticator.jbossEnv) { - // Push a context - ServiceProviderSAMLContext.push(username, roles); - principal = formAuthenticator.getContext().getRealm().authenticate(username, password); - ServiceProviderSAMLContext.clear(); - } else { - // tomcat env - SPUtil spUtil = new SPUtil(); - principal = spUtil.createGenericPrincipal(request, username, roles); - } - - session.setNote(Constants.SESS_USERNAME_NOTE, username); - session.setNote(Constants.SESS_PASSWORD_NOTE, password); - request.setUserPrincipal(principal); - - if (formAuthenticator.saveRestoreRequest) { - formAuthenticator.restoreRequest(request, session); - } - formAuthenticator.register(request, response, principal, HttpServletRequest.FORM_AUTH, username, password); - - return true; - } catch (Exception e) { - logger.samlSPHandleRequestError(e); - } - } - - return false; - } - - protected void startPicketLink() throws LifecycleException{ - super.startPicketLink(); - this.spConfiguration.setBindingType("REDIRECT"); - } -} \ No newline at end of file diff --git a/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/valve/AbstractSPFormAuthenticator.java b/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/valve/AbstractSPFormAuthenticator.java deleted file mode 100644 index 37e42368a..000000000 --- a/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/valve/AbstractSPFormAuthenticator.java +++ /dev/null @@ -1,787 +0,0 @@ -package org.gatein.sso.saml.plugin.valve; - -import static org.gatein.sso.saml.plugin.valve.AbstractSAML11SPRedirectFormAuthenticator.handleSAML11UnsolicitedResponse; -import static org.picketlink.common.util.StringUtil.isNotNull; -import static org.picketlink.common.util.StringUtil.isNullOrEmpty; - -import java.io.IOException; -import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.net.URL; -import java.security.Principal; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Set; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.catalina.Context; -import org.apache.catalina.LifecycleException; -import org.apache.catalina.Session; -import org.apache.catalina.authenticator.Constants; -import org.apache.catalina.connector.Request; -import org.apache.catalina.connector.Response; -import org.apache.catalina.realm.GenericPrincipal; -import org.apache.tomcat.util.descriptor.web.LoginConfig; -import org.exoplatform.container.ExoContainer; -import org.exoplatform.container.ExoContainerContext; -import org.exoplatform.container.PortalContainer; -import org.exoplatform.container.RootContainer; -import org.exoplatform.services.organization.Membership; -import org.exoplatform.services.organization.OrganizationService; -import org.exoplatform.services.security.IdentityRegistry; -import org.exoplatform.services.security.MembershipEntry; -import org.exoplatform.services.security.MembershipHashSet; -import org.exoplatform.services.security.RolesExtractor; -import org.picketlink.common.ErrorCodes; -import org.picketlink.common.constants.GeneralConstants; -import org.picketlink.common.constants.JBossSAMLConstants; -import org.picketlink.common.exceptions.ConfigurationException; -import org.picketlink.common.exceptions.ParsingException; -import org.picketlink.common.exceptions.ProcessingException; -import org.picketlink.common.exceptions.TrustKeyProcessingException; -import org.picketlink.common.exceptions.fed.AssertionExpiredException; -import org.picketlink.common.util.DocumentUtil; -import org.picketlink.common.util.StringUtil; -import org.picketlink.config.federation.AuthPropertyType; -import org.picketlink.config.federation.KeyProviderType; -import org.picketlink.identity.federation.bindings.tomcat.sp.holder.ServiceProviderSAMLContext; -import org.picketlink.identity.federation.core.audit.PicketLinkAuditEvent; -import org.picketlink.identity.federation.core.audit.PicketLinkAuditEventType; -import org.picketlink.identity.federation.core.interfaces.TrustKeyManager; -import org.picketlink.identity.federation.core.saml.v2.holders.DestinationInfoHolder; -import org.picketlink.identity.federation.core.saml.v2.interfaces.SAML2Handler; -import org.picketlink.identity.federation.core.saml.v2.interfaces.SAML2HandlerResponse; -import org.picketlink.identity.federation.core.util.CoreConfigUtil; -import org.picketlink.identity.federation.web.core.HTTPContext; -import org.picketlink.identity.federation.web.process.ServiceProviderBaseProcessor; -import org.picketlink.identity.federation.web.process.ServiceProviderSAMLRequestProcessor; -import org.picketlink.identity.federation.web.process.ServiceProviderSAMLResponseProcessor; -import org.picketlink.identity.federation.web.util.HTTPRedirectUtil; -import org.picketlink.identity.federation.web.util.PostBindingUtil; -import org.picketlink.identity.federation.web.util.RedirectBindingUtil; -import org.picketlink.identity.federation.web.util.RedirectBindingUtil.RedirectBindingUtilDestHolder; -import org.picketlink.identity.federation.web.util.ServerDetector; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -/** - * Abstract class to be extended by Service Provider valves to handle SAML requests and responses. - * forked from org.picketlink.identity.federation.bindings.tomcat.sp.AbstractSPFormAuthenticator - * and made compatible with Tomcat 8.5 since picketlink doesn't provide such a support - */ -public abstract class AbstractSPFormAuthenticator extends BaseFormAuthenticator { - - protected boolean jbossEnv = false; - - public AbstractSPFormAuthenticator() { - super(); - ServerDetector detector = new ServerDetector(); - jbossEnv = detector.isJboss(); - } - - /* - * (non-Javadoc) - * - * @see org.picketlink.identity.federation.bindings.tomcat.sp.BaseFormAuthenticator#processStart() - */ - @Override - protected void startPicketLink() throws LifecycleException { - super.startPicketLink(); - initKeyProvider(context); - } - - /** - *

- * Send the request to the IDP. Subclasses should override this method to implement how requests must be sent to the IDP. - *

- * - * @param destination idp url - * @param samlDocument request or response document - * @param relayState used in SAML Workflow - * @param response Apache Catalina HTTP Response - * @param request Apache Catalina HTTP Request - * @param willSendRequest are we sending Request or Response to IDP - * @param destinationQueryStringWithSignature used only with Redirect binding and with signature enabled. - * @throws ProcessingException Exception to indicate a server processing error - * @throws ConfigurationException Exception indicating an issue with the configuration - * @throws IOException I/O exception - */ - protected void sendRequestToIDP(String destination, Document samlDocument, String relayState, Request request, Response response, - boolean willSendRequest, String destinationQueryStringWithSignature) throws ProcessingException, ConfigurationException, IOException { - - if (isAjaxRequest(request) && request.getUserPrincipal() == null) { - response.sendError(Response.SC_FORBIDDEN); - } else { - if (isHttpPostBinding()) { - sendHttpPostBindingRequest(destination, samlDocument, relayState, response, willSendRequest); - } else { - sendHttpRedirectRequest(destination, samlDocument, relayState, response, willSendRequest, destinationQueryStringWithSignature); - } - } - } - - /** - *

- * Sends a HTTP Redirect request to the IDP. - *

- * - * @param destination idp url - * @param samlDocument SAML request document - * @param relayState used in SAML Workflow - * @param response Apache Catalina HTTP Response - * @param willSendRequest are we sending Request or Response to IDP - * @param destinationQueryStringWithSignature used only with Redirect binding and with signature enabled. - * @throws IOException I/O exception - * @throws UnsupportedEncodingException when decoding SAML Message - * @throws ConfigurationException Exception indicating an issue with the configuration - * @throws ProcessingException Exception to indicate a server processing error - */ - protected void sendHttpRedirectRequest(String destination, Document samlDocument, String relayState, Response response, - boolean willSendRequest, String destinationQueryStringWithSignature) throws IOException, - ProcessingException, ConfigurationException { - String destinationQueryString = null; - - // We already have queryString with signature from SAML2SignatureGenerationHandler - if (destinationQueryStringWithSignature != null) { - destinationQueryString = destinationQueryStringWithSignature; - } - else { - String samlMessage = DocumentUtil.getDocumentAsString(samlDocument); - String base64Request = RedirectBindingUtil.deflateBase64URLEncode(samlMessage.getBytes("UTF-8")); - destinationQueryString = RedirectBindingUtil.getDestinationQueryString(base64Request, relayState, willSendRequest); - } - - RedirectBindingUtilDestHolder holder = new RedirectBindingUtilDestHolder(); - - holder.setDestination(destination).setDestinationQueryString(destinationQueryString); - - HTTPRedirectUtil.sendRedirectForRequestor(RedirectBindingUtil.getDestinationURL(holder), response); - } - - /** - *

- * Sends a HTTP POST request to the IDP. - *

- * - * @param destination idp url - * @param samlDocument request or response document - * @param relayState used in SAML Workflow - * @param response Apache Catalina HTTP Response - * @param willSendRequest are we sending Request or Response to IDP - * @throws ProcessingException Exception to indicate a server processing error - * @throws ConfigurationException Exception indicating an issue with the configuration - * @throws IOException I/O exception - */ - protected void sendHttpPostBindingRequest(String destination, Document samlDocument, String relayState, Response response, - boolean willSendRequest) throws ProcessingException, IOException, - ConfigurationException { - String samlMessage = PostBindingUtil.base64Encode(DocumentUtil.getDocumentAsString(samlDocument)); - - DestinationInfoHolder destinationHolder = new DestinationInfoHolder(destination, samlMessage, relayState); - - PostBindingUtil.sendPost(destinationHolder, response, willSendRequest); - } - - /** - *

- * Initialize the KeyProvider configurations. This configurations are to be used during signing and validation of SAML - * assertions. - *

- * - * @param context Apache Catalina Context - * @throws LifecycleException any exception occurred while processing key provider - */ - protected void initKeyProvider(Context context) throws LifecycleException { - if (!doSupportSignature()) { - return; - } - - KeyProviderType keyProvider = this.spConfiguration.getKeyProvider(); - - if (keyProvider == null && doSupportSignature()) - throw new LifecycleException(ErrorCodes.NULL_VALUE + "KeyProvider is null for context=" + context.getName()); - - try { - String keyManagerClassName = keyProvider.getClassName(); - if (keyManagerClassName == null) - throw new RuntimeException(ErrorCodes.NULL_VALUE + "KeyManager class name"); - - Class clazz = SecurityActions.loadClass(getClass(), keyManagerClassName); - - if (clazz == null) - throw new ClassNotFoundException(ErrorCodes.CLASS_NOT_LOADED + keyManagerClassName); - this.keyManager = (TrustKeyManager) clazz.newInstance(); - - List authProperties = CoreConfigUtil.getKeyProviderProperties(keyProvider); - - keyManager.setAuthProperties(authProperties); - keyManager.setValidatingAlias(keyProvider.getValidatingAlias()); - - String identityURL = this.spConfiguration.getIdentityURL(); - - //Special case when you need X509Data in SignedInfo - if(authProperties != null){ - for(AuthPropertyType authPropertyType: authProperties){ - String key = authPropertyType.getKey(); - if(GeneralConstants.X509CERTIFICATE.equals(key)){ - //we need X509Certificate in SignedInfo. The value is the alias name - keyManager.addAdditionalOption(GeneralConstants.X509CERTIFICATE, authPropertyType.getValue()); - break; - } - } - } - keyManager.addAdditionalOption(ServiceProviderBaseProcessor.IDP_KEY, new URL(identityURL).getHost()); - } catch (Exception e) { - logger.trustKeyManagerCreationError(e); - throw new LifecycleException(e.getLocalizedMessage()); - } - - logger.trace("Key Provider=" + keyProvider.getClassName()); - } - - @Override - protected boolean doAuthenticate(Request request, HttpServletResponse response) throws IOException { - if (response instanceof Response) { - LoginConfig loginConfig = request.getContext().getLoginConfig(); - Response catalinaResponse = (Response) response; - return authenticate(request, catalinaResponse, loginConfig); - } - throw logger.samlSPResponseNotCatalinaResponseError(response); - } - - /** - * Authenticate the request - * - * @param request Apache Catalina Request - * @param response Apache Catalina Response - * @return true if authenticated, else false - * @throws IOException any I/O exception - */ - public boolean authenticate(Request request, HttpServletResponse response) throws IOException { - if (response instanceof Response) { - LoginConfig loginConfig = request.getContext().getLoginConfig(); - Response catalinaResponse = (Response) response; - return authenticate(request, catalinaResponse, loginConfig); - } - throw logger.samlSPResponseNotCatalinaResponseError(response); - } - - /* - * (non-Javadoc) - * - * @see org.apache.catalina.authenticator.FormAuthenticator#authenticate(org.apache.catalina.connector.Request, - * org.apache.catalina.connector.Response, org.apache.catalina.deploy.LoginConfig) - */ - private boolean authenticate(Request request, Response response, LoginConfig loginConfig) throws IOException { - try { - // needs to be done first, *before* accessing any parameters. super.authenticate(..) gets called to late - String characterEncoding = getCharacterEncoding(); - if (characterEncoding != null) { - request.setCharacterEncoding(characterEncoding); - } - - Session session = request.getSessionInternal(true); - - // check if this call is resulting from the redirect after successful authentication. - // if so, make the authentication successful and continue the original request - if (saveRestoreRequest && matchRequest(request)) { - logger.trace("Restoring request from session '" + session.getIdInternal() + "'"); - Principal savedPrincipal = (Principal)session.getNote(Constants.FORM_PRINCIPAL_NOTE); - register (request, response, savedPrincipal, HttpServletRequest.FORM_AUTH, (String)session.getNote(Constants.SESS_USERNAME_NOTE), (String)session.getNote(Constants.SESS_PASSWORD_NOTE)); - - // try to restore the original request (including post data, etc...) - if (restoreRequest(request, session)) { - // success! user is authenticated; continue processing original request - logger.trace("Continuing with restored request."); - return true; - } - else { - // no saved request found... - logger.trace("Restore of original request failed!"); - response.sendError(HttpServletResponse.SC_BAD_REQUEST); - return false; - } - } - - // Eagerly look for Local LogOut - boolean localLogout = isLocalLogout(request); - - if (localLogout) { - try { - sendToLogoutPage(request, response, session); - } catch (ServletException e) { - logger.samlLogoutError(e); - throw new IOException(e); - } - return false; - } - - String samlRequest = request.getParameter(GeneralConstants.SAML_REQUEST_KEY); - String samlResponse = request.getParameter(GeneralConstants.SAML_RESPONSE_KEY); - - Principal principal = request.getUserPrincipal(); - - // If we have already authenticated the user and there is no request from IDP or logout from user - if (principal != null && !(isGlobalLogout(request) || isNotNull(samlRequest) || isNotNull(samlResponse))) - return true; - - // General User Request - if (!isNotNull(samlRequest) && !isNotNull(samlResponse)) { - return generalUserRequest(request, response, loginConfig); - } - - // Handle a SAML Response from IDP - if (isNotNull(samlResponse)) { - return handleSAMLResponse(request, response, loginConfig); - } - - // Handle SAML Requests from IDP - if (isNotNull(samlRequest)) { - return handleSAMLRequest(request, response, loginConfig); - }// end if - - return localAuthentication(request, response, loginConfig); - } catch (IOException e) { - if (StringUtil.isNotNull(spConfiguration.getErrorPage())) { - try { - request.getRequestDispatcher(spConfiguration.getErrorPage()).forward(request.getRequest(), response); - } catch (ServletException e1) { - logger.samlErrorPageForwardError(spConfiguration.getErrorPage(), e1); - } - return false; - } else { - throw e; - } - } - } - - /** - *

- * Indicates if the current request is a GlobalLogout request. - *

- * - * @param request Apache Catalina Request - * @return true if this is a global SAML logout - */ - private boolean isGlobalLogout(Request request) { - String gloStr = request.getParameter(GeneralConstants.GLOBAL_LOGOUT); - return isNotNull(gloStr) && "true".equalsIgnoreCase(gloStr); - } - - /** - *

- * Indicates if the current request is a LocalLogout request. - *

- * - * @param request Apache Catalina Request - * @return true if this is a local SAML logout - */ - private boolean isLocalLogout(Request request) { - try { - if (request.getCharacterEncoding()==null) { - request.setCharacterEncoding("UTF-8"); - } - } catch (UnsupportedEncodingException e) { - logger.error("Request have no encoding, and we are unable to set it to UTF-8"); - logger.error(e); - } - String lloStr = request.getParameter(GeneralConstants.LOCAL_LOGOUT); - return isNotNull(lloStr) && "true".equalsIgnoreCase(lloStr); - } - - /** - * Handle the IDP Request - * - * @param request Apache Catalina Request - * @param response Apache Catalina Response - * @param loginConfig Apache Catalina Login Config - * @return true if processed by SAML Workflow - * @throws IOException any I/O error while authenticating - */ - private boolean handleSAMLRequest(Request request, Response response, LoginConfig loginConfig) throws IOException { - String samlRequest = request.getParameter(GeneralConstants.SAML_REQUEST_KEY); - HTTPContext httpContext = new HTTPContext(request, response, context.getServletContext()); - Set handlers = chain.handlers(); - - try { - ServiceProviderSAMLRequestProcessor requestProcessor = new ServiceProviderSAMLRequestProcessor( - request.getMethod().equals("POST"), this.serviceURL, this.picketLinkConfiguration); - requestProcessor.setTrustKeyManager(keyManager); - boolean result = requestProcessor.process(samlRequest, httpContext, handlers, chainLock); - - if (enableAudit) { - PicketLinkAuditEvent auditEvent = new PicketLinkAuditEvent("Info"); - auditEvent.setType(PicketLinkAuditEventType.REQUEST_FROM_IDP); - auditEvent.setWhoIsAuditing(getContextPath()); - auditHelper.audit(auditEvent); - } - - // If response is already commited, we need to stop with processing of HTTP request - if (response.isCommitted() || response.isAppCommitted()) - return false; - - if (result) - return result; - } catch (Exception e) { - logger.samlSPHandleRequestError(e); - throw logger.samlSPProcessingExceptionError(e); - } - - return localAuthentication(request, response, loginConfig); - } - - private Document toSAMLResponseDocument(String samlResponse, boolean isPostBinding) throws ParsingException { - InputStream dataStream = null; - - if (isPostBinding) { - // deal with SAML response from IDP - dataStream = PostBindingUtil.base64DecodeAsStream(samlResponse); - } else { - // deal with SAML response from IDP - dataStream = RedirectBindingUtil.base64DeflateDecode(samlResponse); - } - - try { - return DocumentUtil.getDocument(dataStream); - } catch (Exception e) { - logger.samlResponseFromIDPParsingFailed(); - throw new ParsingException("", e); - } - } - - /** - * Handle IDP Response - * - * @param request Apache Catalina Request - * @param response Apache Catalina Response - * @param loginConfig Apache Catalina Login Config - * @return true if logged in in SAML SP side - * @throws IOException any I/O error in authentication process - */ - private boolean handleSAMLResponse(Request request, Response response, LoginConfig loginConfig) throws IOException { - if (!super.validate(request)) { - throw new IOException(ErrorCodes.VALIDATION_CHECK_FAILED); - } - - String samlVersion = getSAMLVersion(request); - - if (!JBossSAMLConstants.VERSION_2_0.get().equals(samlVersion)) { - return handleSAML11UnsolicitedResponse(request, response, loginConfig, this); - } - - return handleSAML2Response(request, response, loginConfig); - } - - private boolean handleSAML2Response(Request request, Response response, LoginConfig loginConfig) throws IOException { - Session session = request.getSessionInternal(true); - String samlResponse = request.getParameter(GeneralConstants.SAML_RESPONSE_KEY); - HTTPContext httpContext = new HTTPContext(request, response, context.getServletContext()); - Set handlers = chain.handlers(); - - Principal principal = request.getUserPrincipal(); - - boolean willSendRequest;// deal with SAML response from IDP - - try { - ServiceProviderSAMLResponseProcessor responseProcessor = new ServiceProviderSAMLResponseProcessor(request.getMethod().equals("POST"), serviceURL, this.picketLinkConfiguration); - if(auditHelper != null){ - responseProcessor.setAuditHelper(auditHelper); - } - - responseProcessor.setTrustKeyManager(keyManager); - - SAML2HandlerResponse saml2HandlerResponse = responseProcessor.process(samlResponse, httpContext, handlers, - chainLock); - - Document samlResponseDocument = saml2HandlerResponse.getResultingDocument(); - String relayState = saml2HandlerResponse.getRelayState(); - - String destination = saml2HandlerResponse.getDestination(); - - willSendRequest = saml2HandlerResponse.getSendRequest(); - - String destinationQueryStringWithSignature = saml2HandlerResponse.getDestinationQueryStringWithSignature(); - - if (destination != null && samlResponseDocument != null) { - sendRequestToIDP(destination, samlResponseDocument, relayState, request, response, willSendRequest, destinationQueryStringWithSignature); - } else { - // See if the session has been invalidated - - boolean sessionValidity = session.isValid(); - - if (!sessionValidity) { - sendToLogoutPage(request, response, session); - return false; - } - - // We got a response with the principal - List roles = saml2HandlerResponse.getRoles(); - - if (principal == null) { - principal = (Principal) session.getSession().getAttribute(GeneralConstants.PRINCIPAL_ID); - } - - String username = principal.getName(); - String password = ServiceProviderSAMLContext.EMPTY_PASSWORD; - - roles.addAll(extractGateinRoles(username)); - if (logger.isTraceEnabled()) { - logger.trace("Roles determined for username=" + username + "=" + Arrays.toString(roles.toArray())); - } - - // Map to JBoss specific principal - if ((new ServerDetector()).isJboss() || jbossEnv) { - // Push a context - ServiceProviderSAMLContext.push(username, roles); - principal = context.getRealm().authenticate(username, password); - ServiceProviderSAMLContext.clear(); - } else { - // tomcat env - principal = getGenericPrincipal(request, username, roles); - } - - session.setNote(Constants.SESS_USERNAME_NOTE, username); - session.setNote(Constants.SESS_PASSWORD_NOTE, password); - request.setUserPrincipal(principal); - - if (enableAudit) { - PicketLinkAuditEvent auditEvent = new PicketLinkAuditEvent("Info"); - auditEvent.setType(PicketLinkAuditEventType.RESPONSE_FROM_IDP); - auditEvent.setSubjectName(username); - auditEvent.setWhoIsAuditing(getContextPath()); - auditHelper.audit(auditEvent); - } - - // Redirect the user to the originally requested URL - if (saveRestoreRequest) { - // Store the authenticated principal in the session. - session.setNote(Constants.FORM_PRINCIPAL_NOTE, principal); - - // Redirect to the original URL. Note that this will trigger the - // authenticator again, but on resubmission we will look in the - // session notes to retrieve the authenticated principal and - // prevent reauthentication - String requestURI = savedRequestURL(session); - - if (requestURI != null) { - logger.trace("Redirecting back to original Request URI: " + requestURI); - response.sendRedirect(response.encodeRedirectURL(requestURI)); - } - } - - register(request, response, principal, HttpServletRequest.FORM_AUTH, username, password); - return true; - } - } catch (ProcessingException pe) { - Throwable t = pe.getCause(); - if (t != null && t instanceof AssertionExpiredException) { - logger.error("Assertion has expired. Asking IDP for reissue"); - if (enableAudit) { - PicketLinkAuditEvent auditEvent = new PicketLinkAuditEvent("Info"); - auditEvent.setType(PicketLinkAuditEventType.EXPIRED_ASSERTION); - auditEvent.setAssertionID(((AssertionExpiredException) t).getId()); - auditHelper.audit(auditEvent); - } - // Just issue a fresh request back to IDP - return generalUserRequest(request, response, loginConfig); - } - logger.samlSPHandleRequestError(pe); - throw logger.samlSPProcessingExceptionError(pe); - } catch (Exception e) { - logger.samlSPHandleRequestError(e); - throw logger.samlSPProcessingExceptionError(e); - } - - return localAuthentication(request, response, loginConfig); - } - - private String getSAMLVersion(Request request) { - String samlResponse = request.getParameter(GeneralConstants.SAML_RESPONSE_KEY); - String version; - - try { - Document samlDocument = toSAMLResponseDocument(samlResponse, "POST".equalsIgnoreCase(request.getMethod())); - Element element = samlDocument.getDocumentElement(); - - // let's try SAML 2.0 Version attribute first - version = element.getAttribute("Version"); - - if (isNullOrEmpty(version)) { - // fallback to SAML 1.1 Minor and Major attributes - String minorVersion = element.getAttribute("MinorVersion"); - String majorVersion = element.getAttribute("MajorVersion"); - - version = minorVersion + "." + majorVersion; - } - } catch (Exception e) { - throw new RuntimeException("Could not extract version from SAML Response.", e); - } - - return version; - } - - protected boolean isPOSTBindingResponse() { - return spConfiguration.isIdpUsesPostBinding(); - } - - - /* - * (non-Javadoc) - * - * @see org.picketlink.identity.federation.bindings.tomcat.sp.BaseFormAuthenticator#getBinding() - */ - @Override - protected String getBinding() { - return spConfiguration.getBindingType(); - } - - /** - * Handle the user invocation for the first time - * - * @param request Apache Catalina Request - * @param response Apache Catalina Response - * @param loginConfig Apache Catalina Login Config - * @return true if logged in in SAML SP side - * @throws IOException any I/O error in authentication process - */ - private boolean generalUserRequest(Request request, Response response, LoginConfig loginConfig) throws IOException { - Session session = request.getSessionInternal(true); - boolean willSendRequest = false; - HTTPContext httpContext = new HTTPContext(request, response, context.getServletContext()); - Set handlers = chain.handlers(); - - boolean postBinding = spConfiguration.getBindingType().equals("POST"); - - // Neither saml request nor response from IDP - // So this is a user request - SAML2HandlerResponse saml2HandlerResponse = null; - try { - ServiceProviderBaseProcessor baseProcessor = new ServiceProviderBaseProcessor(postBinding, serviceURL, this.picketLinkConfiguration); - if (issuerID != null) - baseProcessor.setIssuer(issuerID); - - // If the user has a different desired idp - String idp = (String) request.getAttribute(org.picketlink.identity.federation.web.constants.GeneralConstants.DESIRED_IDP); - if (StringUtil.isNotNull(idp)) { - baseProcessor.setIdentityURL(idp); - } else { - baseProcessor.setIdentityURL(identityURL); - } - baseProcessor.setAuditHelper(auditHelper); - - saml2HandlerResponse = baseProcessor.process(httpContext, handlers, chainLock); - } catch (ProcessingException pe) { - logger.samlSPHandleRequestError(pe); - throw new RuntimeException(pe); - } catch (ParsingException pe) { - logger.samlSPHandleRequestError(pe); - throw new RuntimeException(pe); - } catch (ConfigurationException pe) { - logger.samlSPHandleRequestError(pe); - throw new RuntimeException(pe); - } - - willSendRequest = saml2HandlerResponse.getSendRequest(); - - Document samlResponseDocument = saml2HandlerResponse.getResultingDocument(); - String relayState = saml2HandlerResponse.getRelayState(); - - String destination = saml2HandlerResponse.getDestination(); - String destinationQueryStringWithSignature = saml2HandlerResponse.getDestinationQueryStringWithSignature(); - - if (destination != null && samlResponseDocument != null) { - try { - if (saveRestoreRequest && !isGlobalLogout(request)) { - this.saveRequest(request, session); - } - if (enableAudit) { - PicketLinkAuditEvent auditEvent = new PicketLinkAuditEvent("Info"); - auditEvent.setType(PicketLinkAuditEventType.REQUEST_TO_IDP); - auditEvent.setWhoIsAuditing(getContextPath()); - auditHelper.audit(auditEvent); - } - sendRequestToIDP(destination, samlResponseDocument, relayState, request, response, willSendRequest, destinationQueryStringWithSignature); - return false; - } catch (Exception e) { - logger.samlSPHandleRequestError(e); - throw logger.samlSPProcessingExceptionError(e); - } - } - - return localAuthentication(request, response, loginConfig); - } - - /** - * Extract Gatein roles to put in Principal - * @param userId - * @return - */ - private List extractGateinRoles(String userId) { - OrganizationService organizationService = - PortalContainer.getInstance().getComponentInstanceOfType(OrganizationService.class); - RolesExtractor rolesExtractor=PortalContainer.getInstance().getComponentInstanceOfType(RolesExtractor.class); - List result = new ArrayList<>(); - Set entries = new MembershipHashSet(); - Collection memberships; - try { - memberships = organizationService.getMembershipHandler().findMembershipsByUser(userId); - } catch (Exception e) { - memberships = null; - } - if (memberships != null) { - for (Membership membership : memberships) - entries.add(new MembershipEntry(membership.getGroupId(), membership.getMembershipType())); - } - result.addAll(rolesExtractor.extractRoles(userId, entries)); - return result; - } - - /** - *

- * Indicates if the SP is configure with HTTP POST Binding. - *

- * - * @return true if post binding - */ - protected boolean isHttpPostBinding() { - return getBinding().equalsIgnoreCase("POST"); - } - - public Context getContext() { - return (Context) getContainer(); - } - - @Override - public boolean restoreRequest(Request request, Session session) throws IOException { - return super.restoreRequest(request, session); - } - - /** - * Subclasses need to return the context path - * based on the capability of their servlet api - * - * @return Servlet Context Path - */ - protected abstract String getContextPath(); - - protected Principal getGenericPrincipal(Request request, String username, List roles){ - //sometimes, IDP send username in assertion with capitals letters, or with inconsistent format. - //this option allows to force the username in lower case, just before creating the principal, - //so that, all operations in exo side will use a consistant format. - String forceLowerCase = System.getProperty("gatein.sso.saml.username.forcelowercase","false"); - if(forceLowerCase.equalsIgnoreCase("true")) { - username=username.toLowerCase(); - } - return new GenericPrincipal(username, null, roles); - } - - private boolean isAjaxRequest(Request request) { - String requestedWithHeader = request.getHeader(GeneralConstants.HTTP_HEADER_X_REQUESTED_WITH); - return requestedWithHeader != null && "XMLHttpRequest".equalsIgnoreCase(requestedWithHeader); - } -} diff --git a/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/valve/BaseFormAuthenticator.java b/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/valve/BaseFormAuthenticator.java deleted file mode 100644 index 8bcc5a4cd..000000000 --- a/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/valve/BaseFormAuthenticator.java +++ /dev/null @@ -1,623 +0,0 @@ -package org.gatein.sso.saml.plugin.valve; - -import static org.picketlink.common.constants.GeneralConstants.CONFIG_FILE_LOCATION; -import static org.picketlink.common.util.StringUtil.isNullOrEmpty; - -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.Method; -import java.security.cert.X509Certificate; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.Timer; -import java.util.TimerTask; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -import javax.servlet.RequestDispatcher; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.xml.crypto.dsig.CanonicalizationMethod; - -import org.apache.catalina.Context; -import org.apache.catalina.LifecycleException; -import org.apache.catalina.Session; -import org.apache.catalina.authenticator.FormAuthenticator; -import org.apache.catalina.connector.Request; -import org.apache.catalina.connector.Response; -import org.apache.tomcat.util.descriptor.web.LoginConfig; -import org.picketlink.common.ErrorCodes; -import org.picketlink.common.PicketLinkLogger; -import org.picketlink.common.PicketLinkLoggerFactory; -import org.picketlink.common.constants.GeneralConstants; -import org.picketlink.common.constants.JBossSAMLURIConstants; -import org.picketlink.common.exceptions.ConfigurationException; -import org.picketlink.common.exceptions.ParsingException; -import org.picketlink.common.exceptions.ProcessingException; -import org.picketlink.common.util.DocumentUtil; -import org.picketlink.common.util.StringUtil; -import org.picketlink.common.util.SystemPropertiesUtil; -import org.picketlink.config.federation.PicketLinkType; -import org.picketlink.config.federation.SPType; -import org.picketlink.config.federation.handler.Handlers; -import org.picketlink.identity.federation.api.saml.v2.metadata.MetaDataExtractor; -import org.picketlink.identity.federation.core.audit.PicketLinkAuditHelper; -import org.picketlink.identity.federation.core.interfaces.TrustKeyManager; -import org.picketlink.identity.federation.core.parsers.saml.SAMLParser; -import org.picketlink.identity.federation.core.saml.v2.factories.SAML2HandlerChainFactory; -import org.picketlink.identity.federation.core.saml.v2.impl.DefaultSAML2HandlerChainConfig; -import org.picketlink.identity.federation.core.saml.v2.interfaces.SAML2Handler; -import org.picketlink.identity.federation.core.saml.v2.interfaces.SAML2HandlerChain; -import org.picketlink.identity.federation.core.saml.v2.interfaces.SAML2HandlerChainConfig; -import org.picketlink.identity.federation.core.saml.v2.util.HandlerUtil; -import org.picketlink.identity.federation.core.util.CoreConfigUtil; -import org.picketlink.identity.federation.core.util.XMLSignatureUtil; -import org.picketlink.identity.federation.saml.v2.metadata.EndpointType; -import org.picketlink.identity.federation.saml.v2.metadata.EntitiesDescriptorType; -import org.picketlink.identity.federation.saml.v2.metadata.EntityDescriptorType; -import org.picketlink.identity.federation.saml.v2.metadata.IDPSSODescriptorType; -import org.picketlink.identity.federation.saml.v2.metadata.KeyDescriptorType; -import org.picketlink.identity.federation.web.config.AbstractSAMLConfigurationProvider; -import org.picketlink.identity.federation.web.util.ConfigurationUtil; -import org.picketlink.identity.federation.web.util.SAMLConfigurationProvider; -import org.w3c.dom.Document; - -/** - * Base Class for Service Provider Form Authenticators - * forked from org.picketlink.identity.federation.bindings.tomcat.sp.BaseFormAuthenticator - * and made compatible with Tomcat 8.5 since picketlink doesn't provide such a support - */ -public abstract class BaseFormAuthenticator extends FormAuthenticator { - protected static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger(); - - protected boolean enableAudit = false; - protected PicketLinkAuditHelper auditHelper = null; - - protected TrustKeyManager keyManager; - - protected SPType spConfiguration = null; - - protected PicketLinkType picketLinkConfiguration = null; - - protected String serviceURL = null; - - protected String identityURL = null; - - protected String issuerID = null; - - protected String configFile; - - /** - * If the service provider is configured with an IDP metadata file, then this certificate can be picked up from the metadata - */ - protected transient X509Certificate idpCertificate = null; - - protected transient SAML2HandlerChain chain = null; - - protected transient String samlHandlerChainClass = null; - - protected Map chainConfigOptions = new HashMap(); - - // Whether the authenticator has to to save and restore request - protected boolean saveRestoreRequest = true; - - /** - * A Lock for Handler operations in the chain - */ - protected Lock chainLock = new ReentrantLock(); - - protected String canonicalizationMethod = CanonicalizationMethod.EXCLUSIVE_WITH_COMMENTS; - - /** - * The user can inject a fully qualified name of a {@link SAMLConfigurationProvider} - */ - protected SAMLConfigurationProvider configProvider = null; - - protected int timerInterval = -1; - - protected Timer timer = null; - - public BaseFormAuthenticator() { - super(); - } - - protected String idpAddress = null; - - /** - * If the request.getRemoteAddr is not exactly the IDP address that you have keyed in your deployment descriptor for - * keystore alias, you can set it here explicitly - * - * @param idpAddress IP address of IDP - */ - public void setIdpAddress(String idpAddress) { - this.idpAddress = idpAddress; - } - - /** - * Get the name of the configuration file - * @return SAML config file path - */ - public String getConfigFile() { - return configFile; - } - - /** - * Set the name of the configuration file - * @param configFile set config file path - */ - public void setConfigFile(String configFile) { - this.configFile = configFile; - } - - /** - * Set the SAML Handler Chain Class fqn - * @param samlHandlerChainClass FQN of SAML Handler Chain - */ - public void setSamlHandlerChainClass(String samlHandlerChainClass) { - this.samlHandlerChainClass = samlHandlerChainClass; - } - - /** - * Set the service URL - * @param serviceURL Service URL - */ - public void setServiceURL(String serviceURL) { - this.serviceURL = serviceURL; - } - - /** - * Set whether the authenticator saves/restores the request - * during form authentication - * @param saveRestoreRequest saves/restores the request during authentication if true - */ - public void setSaveRestoreRequest(boolean saveRestoreRequest) { - this.saveRestoreRequest = saveRestoreRequest; - } - - /** - * Set the {@link SAMLConfigurationProvider} fqn - * @param cp fqn of a {@link SAMLConfigurationProvider} - */ - public void setConfigProvider(String cp) { - if (cp == null) - throw new IllegalStateException(ErrorCodes.NULL_ARGUMENT + cp); - Class clazz = SecurityActions.loadClass(getClass(), cp); - if (clazz == null) - throw new RuntimeException(ErrorCodes.CLASS_NOT_LOADED + cp); - try { - configProvider = (SAMLConfigurationProvider) clazz.newInstance(); - } catch (Exception e) { - throw new RuntimeException(ErrorCodes.CANNOT_CREATE_INSTANCE + cp + ":" + e.getMessage()); - } - } - - /** - * Set an instance of the {@link SAMLConfigurationProvider} - * @param configProvider SAML IDP/SP config provider - */ - public void setConfigProvider(SAMLConfigurationProvider configProvider) { - this.configProvider = configProvider; - } - - /** - * Get the {@link SPType} - * @return SAML SP configuration - */ - public SPType getConfiguration() { - return spConfiguration; - } - - /** - * Set a separate issuer id - * - * @param issuerID id of the issuer - */ - public void setIssuerID(String issuerID) { - this.issuerID = issuerID; - } - - /** - * Set the logout page - * @param logOutPage logout page URL - */ - public void setLogOutPage(String logOutPage) { - logger.warn("Option logOutPage is now configured with the PicketLinkSP element."); - - } - - /** - * Set the Timer Value to reload the configuration - * @param value an integer value that represents timer value (in miliseconds) - */ - public void setTimerInterval(String value){ - if(StringUtil.isNotNull(value)){ - timerInterval = Integer.parseInt(value); - } - } - - /** - * Perform validation os the request object - * - * @param request Apache Catalina Request - * @return true if request contains a SAML Response parameter - */ - protected boolean validate(Request request) { - return request.getParameter("SAMLResponse") != null; - } - - /** - * Get the Identity URL - * - * @return Identity URL - */ - public String getIdentityURL() { - return identityURL; - } - - /** - * Get the {@link X509Certificate} of the IDP if provided via the IDP metadata file - * - * @return {@link X509Certificate} or null - */ - public X509Certificate getIdpCertificate() { - return idpCertificate; - } - - /** - * Fall back on local authentication at the service provider side - * - * @param request Apache Catalina Request - * @param response Apache Catalina Response - * @param loginConfig Apache Catalina Login Config - * @return true if authenticated - * @throws IOException any I/O error during authentication - */ - protected boolean localAuthentication(Request request, Response response, LoginConfig loginConfig) throws IOException { - if (request.getUserPrincipal() == null) { - logger.samlSPFallingBackToLocalFormAuthentication();// fallback - try { - return super.authenticate(request, response.getResponse()); - } catch (NoSuchMethodError e) { - // Use Reflection - try { - Method method = super.getClass().getMethod("authenticate", - new Class[] { HttpServletRequest.class, HttpServletResponse.class, LoginConfig.class }); - return (Boolean) method.invoke(this, new Object[] { request.getRequest(), response.getResponse(), - loginConfig }); - } catch (Exception ex) { - throw logger.unableLocalAuthentication(ex); - } - } - } else - return true; - } - - /** - * Return the SAML Binding that this authenticator supports - * - * @return supported SAML Binding - */ - protected abstract String getBinding(); - - /** - * Attempt to process a metadata file available locally - * - * @param idpMetadataFile path of configuration file of IDP Metadata - */ - protected void processIDPMetadataFile(String idpMetadataFile) { - ServletContext servletContext = context.getServletContext(); - InputStream is = servletContext.getResourceAsStream(idpMetadataFile); - if (is == null) - return; - - Object metadata = null; - try { - Document samlDocument = DocumentUtil.getDocument(is); - SAMLParser parser = new SAMLParser(); - metadata = parser.parse(DocumentUtil.getNodeAsStream(samlDocument)); - } catch (Exception e) { - throw new RuntimeException(e); - } - IDPSSODescriptorType idpSSO = null; - if (metadata instanceof EntitiesDescriptorType) { - EntitiesDescriptorType entities = (EntitiesDescriptorType) metadata; - idpSSO = handleMetadata(entities); - } else { - idpSSO = handleMetadata((EntityDescriptorType) metadata); - } - if (idpSSO == null) { - logger.samlSPUnableToGetIDPDescriptorFromMetadata(); - return; - } - List endpoints = idpSSO.getSingleSignOnService(); - for (EndpointType endpoint : endpoints) { - String endpointBinding = endpoint.getBinding().toString(); - if (endpointBinding.contains("HTTP-POST")) - endpointBinding = "POST"; - else if (endpointBinding.contains("HTTP-Redirect")) - endpointBinding = "REDIRECT"; - if (getBinding().equals(endpointBinding)) { - identityURL = endpoint.getLocation().toString(); - break; - } - } - List keyDescriptors = idpSSO.getKeyDescriptor(); - if (keyDescriptors.size() > 0) { - this.idpCertificate = MetaDataExtractor.getCertificate(keyDescriptors.get(0)); - } - } - - /** - * Process the configuration from the configuration file - */ - @SuppressWarnings("deprecation") - protected void processConfiguration() { - ServletContext servletContext = context.getServletContext(); - InputStream is = null; - - if (isNullOrEmpty(this.configFile)) { - this.configFile = CONFIG_FILE_LOCATION; - is = servletContext.getResourceAsStream(this.configFile); - } else { - try { - is = new FileInputStream(this.configFile); - } catch (FileNotFoundException e) { - throw logger.samlIDPConfigurationError(e); - } - } - - try { - // Work on the IDP Configuration - if (configProvider != null) { - try { - if (is == null) { - // Try the older version - is = servletContext.getResourceAsStream(GeneralConstants.DEPRECATED_CONFIG_FILE_LOCATION); - - // Additionally parse the deprecated config file - if (is != null && configProvider instanceof AbstractSAMLConfigurationProvider) { - ((AbstractSAMLConfigurationProvider) configProvider).setConfigFile(is); - } - } else { - // Additionally parse the consolidated config file - if (is != null && configProvider instanceof AbstractSAMLConfigurationProvider) { - ((AbstractSAMLConfigurationProvider) configProvider).setConsolidatedConfigFile(is); - } - } - - picketLinkConfiguration = configProvider.getPicketLinkConfiguration(); - spConfiguration = configProvider.getSPConfiguration(); - } catch (ProcessingException e) { - throw logger.samlSPConfigurationError(e); - } catch (ParsingException e) { - throw logger.samlSPConfigurationError(e); - } - } else { - if (is != null) { - try { - picketLinkConfiguration = ConfigurationUtil.getConfiguration(is); - spConfiguration = (SPType) picketLinkConfiguration.getIdpOrSP(); - } catch (ParsingException e) { - logger.trace(e); - throw logger.samlSPConfigurationError(e); - } - } else { - is = servletContext.getResourceAsStream(GeneralConstants.DEPRECATED_CONFIG_FILE_LOCATION); - if (is == null) - throw logger.configurationFileMissing(configFile); - spConfiguration = ConfigurationUtil.getSPConfiguration(is); - } - } - - if (this.picketLinkConfiguration != null) { - enableAudit = picketLinkConfiguration.isEnableAudit(); - - //See if we have the system property enabled - if(!enableAudit){ - String sysProp = SecurityActions.getSystemProperty(GeneralConstants.AUDIT_ENABLE, "NULL"); - if(!"NULL".equals(sysProp)){ - enableAudit = Boolean.parseBoolean(sysProp); - } - } - - if (enableAudit) { - if (auditHelper == null) { - String securityDomainName = PicketLinkAuditHelper.getSecurityDomainName(servletContext); - - auditHelper = new PicketLinkAuditHelper(securityDomainName); - } - } - } - - if (StringUtil.isNotNull(spConfiguration.getIdpMetadataFile())) { - processIDPMetadataFile(spConfiguration.getIdpMetadataFile()); - } else { - this.identityURL = spConfiguration.getIdentityURL(); - } - this.serviceURL = spConfiguration.getServiceURL(); - this.canonicalizationMethod = spConfiguration.getCanonicalizationMethod(); - - logger.samlSPSettingCanonicalizationMethod(canonicalizationMethod); - XMLSignatureUtil.setCanonicalizationMethodType(canonicalizationMethod); - - logger.trace("Identity Provider URL=" + this.identityURL); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - protected IDPSSODescriptorType handleMetadata(EntitiesDescriptorType entities) { - IDPSSODescriptorType idpSSO = null; - - List entityDescs = entities.getEntityDescriptor(); - for (Object entityDescriptor : entityDescs) { - if (entityDescriptor instanceof EntitiesDescriptorType) { - idpSSO = getIDPSSODescriptor(entities); - } else - idpSSO = handleMetadata((EntityDescriptorType) entityDescriptor); - if (idpSSO != null) - break; - } - return idpSSO; - } - - protected IDPSSODescriptorType handleMetadata(EntityDescriptorType entityDescriptor) { - return CoreConfigUtil.getIDPDescriptor(entityDescriptor); - } - - protected IDPSSODescriptorType getIDPSSODescriptor(EntitiesDescriptorType entities) { - List entityDescs = entities.getEntityDescriptor(); - for (Object entityDescriptor : entityDescs) { - - if (entityDescriptor instanceof EntitiesDescriptorType) { - return getIDPSSODescriptor((EntitiesDescriptorType) entityDescriptor); - } - return CoreConfigUtil.getIDPDescriptor((EntityDescriptorType) entityDescriptor); - } - return null; - } - - protected void initializeHandlerChain() throws ConfigurationException, ProcessingException { - populateChainConfig(); - SAML2HandlerChainConfig handlerChainConfig = new DefaultSAML2HandlerChainConfig(chainConfigOptions); - - Set samlHandlers = chain.handlers(); - - for (SAML2Handler handler : samlHandlers) { - handler.initChainConfig(handlerChainConfig); - } - } - - protected void populateChainConfig() throws ConfigurationException, ProcessingException { - chainConfigOptions.put(GeneralConstants.CONFIGURATION, spConfiguration); - chainConfigOptions.put(GeneralConstants.ROLE_VALIDATOR_IGNORE, "false"); // No validator as tomcat realm does validn - - if (doSupportSignature()) { - chainConfigOptions.put(GeneralConstants.KEYPAIR, keyManager.getSigningKeyPair()); - //If there is a need for X509Data in signedinfo - String certificateAlias = (String)keyManager.getAdditionalOption(GeneralConstants.X509CERTIFICATE); - if(certificateAlias != null){ - chainConfigOptions.put(GeneralConstants.X509CERTIFICATE, keyManager.getCertificate(certificateAlias)); - } - } - } - - protected void sendToLogoutPage(Request request, Response response, Session session) throws IOException, ServletException { - // we are invalidated. - RequestDispatcher dispatch = context.getServletContext().getRequestDispatcher(this.getConfiguration().getLogOutPage()); - if (dispatch == null) - logger.samlSPCouldNotDispatchToLogoutPage(this.getConfiguration().getLogOutPage()); - else { - logger.trace("Forwarding request to logOutPage: " + this.getConfiguration().getLogOutPage()); - session.expire(); - try { - dispatch.forward(request, response); - } catch (Exception e) { - // JBAS5.1 and 6 quirkiness - dispatch.forward(request.getRequest(), response); - } - } - } - - // Mock test purpose - public void testStart() throws LifecycleException { - this.saveRestoreRequest = false; - if (context == null) - throw new RuntimeException("Catalina Context not set up"); - startPicketLink(); - } - - protected void startPicketLink() throws LifecycleException { - SystemPropertiesUtil.ensure(); - Handlers handlers = null; - - //Introduce a timer to reload configuration if desired - if(timerInterval > 0 ){ - if(timer == null){ - timer = new Timer(); - } - timer.scheduleAtFixedRate(new TimerTask() { - @Override - public void run() { - //Clear the configuration - picketLinkConfiguration = null; - spConfiguration = null; - - processConfiguration(); - try { - initKeyProvider(context); - } catch (LifecycleException e) { - logger.trace(e.getMessage()); - } - } - }, timerInterval, timerInterval); - } - - // Get the chain from config - if (StringUtil.isNullOrEmpty(samlHandlerChainClass)) { - chain = SAML2HandlerChainFactory.createChain(); - } else { - try { - chain = SAML2HandlerChainFactory.createChain(this.samlHandlerChainClass); - } catch (ProcessingException e1) { - throw new LifecycleException(e1); - } - } - - ServletContext servletContext = context.getServletContext(); - - this.processConfiguration(); - - try { - if (picketLinkConfiguration != null) { - handlers = picketLinkConfiguration.getHandlers(); - } else { - // Get the handlers - String handlerConfigFileName = GeneralConstants.HANDLER_CONFIG_FILE_LOCATION; - handlers = ConfigurationUtil.getHandlers(servletContext.getResourceAsStream(handlerConfigFileName)); - } - - chain.addAll(HandlerUtil.getHandlers(handlers)); - - this.initKeyProvider(context); - this.populateChainConfig(); - this.initializeHandlerChain(); - } catch (Exception e) { - throw new RuntimeException(e); - } - - if (this.picketLinkConfiguration == null) { - this.picketLinkConfiguration = new PicketLinkType(); - - this.picketLinkConfiguration.setIdpOrSP(getConfiguration()); - this.picketLinkConfiguration.setHandlers(handlers); - } - } - - /** - *

- * Indicates if digital signatures/validation of SAML assertions are enabled. Subclasses that supports signature should - * override this method. - *

- * - * @return true if SP Configuration supports signature - */ - protected boolean doSupportSignature() { - if (spConfiguration != null) { - return spConfiguration.isSupportsSignature(); - } - return false; - } - - protected abstract void initKeyProvider(Context context) throws LifecycleException; - - public void setAuditHelper(PicketLinkAuditHelper auditHelper) { - this.auditHelper = auditHelper; - } -} diff --git a/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/valve/SecurityActions.java b/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/valve/SecurityActions.java deleted file mode 100644 index 1064d9190..000000000 --- a/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/valve/SecurityActions.java +++ /dev/null @@ -1,134 +0,0 @@ -package org.gatein.sso.saml.plugin.valve; - -import java.lang.reflect.Method; -import java.security.AccessController; -import java.security.PrivilegedAction; - -/** - * Privileged Blocks - * Forked from org.picketlink.identity.federation.bindings.tomcat.sp.SecurityActions - * and made compatible with Tomcat 8.5 since picketlink doesn't provide such a support - */ -class SecurityActions { - - /** - *

- * Loads a {@link Class} using the fullQualifiedName supplied. This method tries first to load from the - * specified {@link Class}, if not found it will try to load from using TCL. - *

- * - * @param theClass - * @param fullQualifiedName - * @return - */ - static Class loadClass(final Class theClass, final String fullQualifiedName) { - SecurityManager sm = System.getSecurityManager(); - - if (sm != null) { - return AccessController.doPrivileged(new PrivilegedAction>() { - public Class run() { - ClassLoader classLoader = theClass.getClassLoader(); - - Class clazz = loadClass(classLoader, fullQualifiedName); - if (clazz == null) { - classLoader = Thread.currentThread().getContextClassLoader(); - clazz = loadClass(classLoader, fullQualifiedName); - } - return clazz; - } - }); - } else { - ClassLoader classLoader = theClass.getClassLoader(); - - Class clazz = loadClass(classLoader, fullQualifiedName); - if (clazz == null) { - classLoader = Thread.currentThread().getContextClassLoader(); - clazz = loadClass(classLoader, fullQualifiedName); - } - return clazz; - } - } - - /** - *

- * Loads a class from the specified {@link ClassLoader} using the fullQualifiedName supplied. - *

- * - * @param classLoader - * @param fullQualifiedName - * @return - */ - static Class loadClass(final ClassLoader classLoader, final String fullQualifiedName) { - SecurityManager sm = System.getSecurityManager(); - - if (sm != null) { - return AccessController.doPrivileged(new PrivilegedAction>() { - public Class run() { - try { - return classLoader.loadClass(fullQualifiedName); - } catch (ClassNotFoundException e) { - } - return null; - } - }); - } else { - try { - return classLoader.loadClass(fullQualifiedName); - } catch (ClassNotFoundException e) { - } - return null; - } - } - - /** - *

Returns a system property value using the specified key. If not found the defaultValue will be returned.

- * - * @param key - * @param defaultValue - * @return - */ - static String getSystemProperty(final String key, final String defaultValue) { - SecurityManager sm = System.getSecurityManager(); - - if (sm != null) { - return AccessController.doPrivileged(new PrivilegedAction() { - public String run() { - return System.getProperty(key, defaultValue); - } - }); - } else { - return System.getProperty(key, defaultValue); - } - } - - /** - * Use reflection to get the {@link Method} on a {@link Class} with the given parameter types - * - * @param clazz - * @param methodName - * @param parameterTypes - * @return - */ - static Method getMethod(final Class clazz, final String methodName, final Class[] parameterTypes) { - SecurityManager sm = System.getSecurityManager(); - - if (sm != null) { - return AccessController.doPrivileged(new PrivilegedAction() { - public Method run() { - try { - return clazz.getDeclaredMethod(methodName, parameterTypes); - } catch (Exception e) { - return null; - } - } - }); - } else { - try { - return clazz.getDeclaredMethod(methodName, parameterTypes); - } catch (Exception e) { - return null; - } - } - } - -} \ No newline at end of file diff --git a/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/valve/ServiceProviderAuthenticator.java b/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/valve/ServiceProviderAuthenticator.java deleted file mode 100644 index ae8afcacd..000000000 --- a/saml/gatein-saml-plugin/src/main/java/org/gatein/sso/saml/plugin/valve/ServiceProviderAuthenticator.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.gatein.sso.saml.plugin.valve; - -import org.apache.catalina.LifecycleException; - - -/** - * Unified Service Provider Authenticator - * Forked from org.picketlink.identity.federation.bindings.tomcat.sp.ServiceProviderAuthenticator - * and made compatible with Tomcat 8.5 since picketlink doesn't provide such a support - */ -public class ServiceProviderAuthenticator extends AbstractSPFormAuthenticator { - - @Override - protected synchronized void startInternal() throws LifecycleException { - super.startInternal(); - startPicketLink(); - } - - @Override - protected String getContextPath() { - return getContext().getServletContext().getContextPath(); - } -} \ No newline at end of file diff --git a/saml/gatein-saml-plugin/src/main/resources/conf/portal/configuration.xml b/saml/gatein-saml-plugin/src/main/resources/conf/portal/configuration.xml deleted file mode 100644 index 5bdaea41f..000000000 --- a/saml/gatein-saml-plugin/src/main/resources/conf/portal/configuration.xml +++ /dev/null @@ -1,86 +0,0 @@ - - - - - org.gatein.sso.integration.SSOFilterIntegrator - - PortalIDPWebBrowserSSOFilter - addPlugin - org.gatein.sso.integration.SSOFilterIntegratorPlugin - - - filterClass - org.gatein.sso.saml.plugin.filter.PortalIDPWebBrowserSSOFilter - - - enabled - ${gatein.sso.filter.saml.idp.enabled:false} - - - filterMapping - /sso - - - CONFIG_FILE - ${gatein.sso.saml.config.file} - - - IGNORE_SIGNATURES - ${gatein.sso.saml.signature.ignore:true} - - - - - PortalSPWebBrowserSSOFilter - addPlugin - org.gatein.sso.integration.SSOFilterIntegratorPlugin - - - filterClass - org.gatein.sso.saml.plugin.filter.SAML2LogoutFilter - - - enabled - ${gatein.sso.saml.sp.enabled:false} - - - filterMapping - /* - - - CONFIG_FILE - ${exo.conf.dir}/saml2/picketlink-sp.xml - - - IGNORE_SIGNATURES - ${gatein.sso.saml.signature.ignore:true} - - - ROLES - users - - - - - diff --git a/saml/gatein-saml-plugin/src/test/java/org/gatein/sso/saml/plugin/filter/PortalIDPWebBrowserSSOFilterTest.java b/saml/gatein-saml-plugin/src/test/java/org/gatein/sso/saml/plugin/filter/PortalIDPWebBrowserSSOFilterTest.java deleted file mode 100644 index 85b298ac0..000000000 --- a/saml/gatein-saml-plugin/src/test/java/org/gatein/sso/saml/plugin/filter/PortalIDPWebBrowserSSOFilterTest.java +++ /dev/null @@ -1,108 +0,0 @@ -package org.gatein.sso.saml.plugin.filter; - -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyBoolean; -import static org.mockito.Matchers.startsWith; -import static org.mockito.Mockito.doCallRealMethod; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; - -import org.mockito.internal.verification.VerificationModeFactory; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; -import org.picketlink.common.constants.GeneralConstants; -import org.picketlink.identity.federation.web.filters.IDPFilter; - -import junit.framework.TestCase; - -public class PortalIDPWebBrowserSSOFilterTest extends TestCase { - - public void testLoginRedirect() throws Exception { - // Given - HttpServletRequest request = mock(HttpServletRequest.class); - HttpServletResponse response = mock(HttpServletResponse.class); - HttpSession httpSession = mock(HttpSession.class); - FilterChain chain = mock(FilterChain.class); - - FilterConfig filterConfig = mock(FilterConfig.class); - ServletContext servletContext = mock(ServletContext.class); - - PortalIDPWebBrowserSSOFilter idpWebBrowserSSOFilter = mock(PortalIDPWebBrowserSSOFilter.class); - - // When - when(response.encodeRedirectURL(any())).thenAnswer(new Answer() { - public String answer(InvocationOnMock invocation) throws Throwable { - return (String) invocation.getArguments()[0]; - } - }); - when(request.getSession()).thenReturn(httpSession); - when(request.getSession(anyBoolean())).thenReturn(httpSession); - when(request.getParameter(GeneralConstants.SAML_REQUEST_KEY)).thenReturn("SOME SAML REQUEST"); - when(request.getRequestURI()).thenReturn("/portal"); - when(httpSession.getId()).thenReturn("fakeHttpSession"); - when(filterConfig.getServletContext()).thenReturn(servletContext); - when(servletContext.getServletContextName()).thenReturn("portal"); - when(servletContext.getContextPath()).thenReturn("/portal"); - when(request.getContextPath()).thenReturn("/portal"); - - doNothing().when(((IDPFilter)idpWebBrowserSSOFilter)).doFilter(request, response, chain); - doCallRealMethod().when(idpWebBrowserSSOFilter).doFilter(request, response, chain); - - idpWebBrowserSSOFilter.init(filterConfig); - idpWebBrowserSSOFilter.doFilter(request, response, chain); - // Then - verify(response, VerificationModeFactory.times(1)).sendRedirect(startsWith("/portal/dologin?initialURI=")); - verify(chain, VerificationModeFactory.times(0)).doFilter(request, response); - } - - public void testSAMLLogin() throws Exception { - // Given - HttpServletRequest request = mock(HttpServletRequest.class); - HttpServletRequest originalRequest = mock(HttpServletRequest.class); - HttpServletResponse response = mock(HttpServletResponse.class); - HttpSession httpSession = mock(HttpSession.class); - FilterChain chain = mock(FilterChain.class); - - FilterConfig filterConfig = mock(FilterConfig.class); - ServletContext servletContext = mock(ServletContext.class); - - PortalIDPWebBrowserSSOFilter idpWebBrowserSSOFilter = mock(PortalIDPWebBrowserSSOFilter.class); - - // When - when(response.encodeRedirectURL(any())).thenAnswer(new Answer() { - public String answer(InvocationOnMock invocation) throws Throwable { - return (String) invocation.getArguments()[0]; - } - }); - when(request.getSession()).thenReturn(httpSession); - when(request.getSession(anyBoolean())).thenReturn(httpSession); - when(httpSession.getAttribute(PortalIDPWebBrowserSSOFilter.ORIGINAL_HTTP_SERVLET_REQUEST_PARAM)).thenReturn(originalRequest); - when(request.getRequestURI()).thenReturn("/portal"); - when(httpSession.getId()).thenReturn("fakeHttpSession"); - when(filterConfig.getServletContext()).thenReturn(servletContext); - when(servletContext.getServletContextName()).thenReturn("portal"); - when(servletContext.getContextPath()).thenReturn("/portal"); - when(request.getContextPath()).thenReturn("/portal"); - when(idpWebBrowserSSOFilter.getInitParameter(GeneralConstants.ROLES)).thenReturn("users"); - - doNothing().when(((IDPFilter)idpWebBrowserSSOFilter)).doFilter(request, response, chain); - doCallRealMethod().when(idpWebBrowserSSOFilter).doFilter(request, response, chain); - - idpWebBrowserSSOFilter.init(filterConfig); - idpWebBrowserSSOFilter.doFilter(request, response, chain); - - // Then - verify(response, VerificationModeFactory.times(0)).sendRedirect(any()); - verify(chain, VerificationModeFactory.times(0)).doFilter(request, response); - verify(httpSession, VerificationModeFactory.times(1)).removeAttribute(PortalIDPWebBrowserSSOFilter.ORIGINAL_HTTP_SERVLET_REQUEST_PARAM); - } -} diff --git a/saml/gatein-saml-plugin/src/test/java/org/gatein/sso/saml/plugin/filter/SAML2LogoutFilterTest.java b/saml/gatein-saml-plugin/src/test/java/org/gatein/sso/saml/plugin/filter/SAML2LogoutFilterTest.java deleted file mode 100644 index bd71d64ed..000000000 --- a/saml/gatein-saml-plugin/src/test/java/org/gatein/sso/saml/plugin/filter/SAML2LogoutFilterTest.java +++ /dev/null @@ -1,139 +0,0 @@ -package org.gatein.sso.saml.plugin.filter; - -import static org.mockito.Matchers.eq; -import static org.mockito.Matchers.startsWith; -import static org.mockito.Mockito.doCallRealMethod; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; - -import org.mockito.internal.verification.VerificationModeFactory; -import org.picketlink.common.constants.GeneralConstants; - -import junit.framework.TestCase; - -public class SAML2LogoutFilterTest extends TestCase { - - public void testLogoutProcessStep1() throws Exception { - // Given - HttpServletRequest request = mock(HttpServletRequest.class); - HttpServletResponse response = mock(HttpServletResponse.class); - HttpSession httpSession = mock(HttpSession.class); - FilterChain chain = mock(FilterChain.class); - - FilterConfig filterConfig = mock(FilterConfig.class); - ServletContext servletContext = mock(ServletContext.class); - - SAML2LogoutFilter saml2LogoutFilter = mock(SAML2LogoutFilter.class); - - // When - when(request.getRequestURI()).thenReturn("/portal"); - when(request.getQueryString()).thenReturn("portal:action=Logout"); - when(request.getParameter("portal:action")).thenReturn("Logout"); - when(request.getRemoteUser()).thenReturn("root"); - when(request.getSession()).thenReturn(httpSession); - when(filterConfig.getServletContext()).thenReturn(servletContext); - when(servletContext.getServletContextName()).thenReturn("portal"); - when(servletContext.getContextPath()).thenReturn("/portal"); - when(saml2LogoutFilter.getInitParameter(GeneralConstants.CONFIG_FILE)).thenReturn(getClass().getResource("/picketlink-sp.xml") - .getPath()); - when(servletContext.getResourceAsStream(startsWith("file:/"))).thenReturn(getClass().getResource("/picketlink-sp.xml") - .openStream()); - when(saml2LogoutFilter.getInitParameter(GeneralConstants.ROLES)).thenReturn("users"); - when(filterConfig.getInitParameter(GeneralConstants.ROLE_VALIDATOR)).thenReturn("org.picketlink.identity.federation.web.roles.DefaultRoleValidator"); - System.setProperty("picketlink.keystore", getClass().getResource("/jbid_test_keystore.jks").getPath()); - - doCallRealMethod().when(saml2LogoutFilter).doFilter(request, response, chain); - doCallRealMethod().when(saml2LogoutFilter).initImpl(); - - saml2LogoutFilter.init(filterConfig); - saml2LogoutFilter.doFilter(request, response, chain); - - verify(httpSession, VerificationModeFactory.times(1)).setAttribute(eq(SAML2LogoutFilter.SAML_LOGOUT_ATTRIBUTE), - eq("/portal?portal:action=Logout")); - } - - public void testLogoutProcessStep2() throws Exception { - // Given - HttpServletRequest request = mock(HttpServletRequest.class); - HttpServletResponse response = mock(HttpServletResponse.class); - HttpSession httpSession = mock(HttpSession.class); - FilterChain chain = mock(FilterChain.class); - - FilterConfig filterConfig = mock(FilterConfig.class); - ServletContext servletContext = mock(ServletContext.class); - - SAML2LogoutFilter saml2LogoutFilter = mock(SAML2LogoutFilter.class); - - // When - when(request.getRequestURI()).thenReturn("/portal"); - when(httpSession.getAttribute(SAML2LogoutFilter.SAML_LOGOUT_ATTRIBUTE)).thenReturn("/portal?portal:action=Logout"); - when(request.getRemoteUser()).thenReturn("root"); - when(request.getSession()).thenReturn(httpSession); - when(filterConfig.getServletContext()).thenReturn(servletContext); - when(servletContext.getServletContextName()).thenReturn("portal"); - when(servletContext.getContextPath()).thenReturn("/portal"); - when(saml2LogoutFilter.getInitParameter(GeneralConstants.CONFIG_FILE)).thenReturn(getClass().getResource("/picketlink-sp.xml") - .getPath()); - when(servletContext.getResourceAsStream(startsWith("file:/"))).thenReturn(getClass().getResource("/picketlink-sp.xml") - .openStream()); - when(saml2LogoutFilter.getInitParameter(GeneralConstants.ROLES)).thenReturn("users"); - when(filterConfig.getInitParameter(GeneralConstants.ROLE_VALIDATOR)).thenReturn("org.picketlink.identity.federation.web.roles.DefaultRoleValidator"); - System.setProperty("picketlink.keystore", getClass().getResource("/jbid_test_keystore.jks").getPath()); - - doCallRealMethod().when(saml2LogoutFilter).doFilter(request, response, chain); - doCallRealMethod().when(saml2LogoutFilter).initImpl(); - - saml2LogoutFilter.init(filterConfig); - saml2LogoutFilter.doFilter(request, response, chain); - - verify(response, VerificationModeFactory.times(1)).sendRedirect(eq("/portal?portal:action=Logout")); - } - - public void testLogoutProcessStep3AndStep4() throws Exception { - // Given - HttpServletRequest request = mock(HttpServletRequest.class); - HttpServletResponse response = mock(HttpServletResponse.class); - HttpSession httpSession = mock(HttpSession.class); - FilterChain chain = mock(FilterChain.class); - - FilterConfig filterConfig = mock(FilterConfig.class); - ServletContext servletContext = mock(ServletContext.class); - - SAML2LogoutFilter saml2LogoutFilter = mock(SAML2LogoutFilter.class); - - // When - when(request.getRequestURI()).thenReturn("/portal"); - when(request.getQueryString()).thenReturn("portal:action=Logout"); - when(request.getParameter("portal:action")).thenReturn("Logout"); - when(httpSession.getAttribute(SAML2LogoutFilter.SAML_LOGOUT_ATTRIBUTE)).thenReturn("/portal?portal:action=Logout"); - when(request.getRemoteUser()).thenReturn("root"); - when(request.getSession()).thenReturn(httpSession); - when(filterConfig.getServletContext()).thenReturn(servletContext); - when(servletContext.getServletContextName()).thenReturn("portal"); - when(servletContext.getContextPath()).thenReturn("/portal"); - when(saml2LogoutFilter.getInitParameter(GeneralConstants.CONFIG_FILE)).thenReturn(getClass().getResource("/picketlink-sp.xml") - .getPath()); - when(servletContext.getResourceAsStream(startsWith("file:/"))).thenReturn(getClass().getResource("/picketlink-sp.xml") - .openStream()); - when(saml2LogoutFilter.getInitParameter(GeneralConstants.ROLES)).thenReturn("users"); - when(filterConfig.getInitParameter(GeneralConstants.ROLE_VALIDATOR)).thenReturn("org.picketlink.identity.federation.web.roles.DefaultRoleValidator"); - System.setProperty("picketlink.keystore", getClass().getResource("/jbid_test_keystore.jks").getPath()); - - doCallRealMethod().when(saml2LogoutFilter).doFilter(request, response, chain); - doCallRealMethod().when(saml2LogoutFilter).initImpl(); - - saml2LogoutFilter.init(filterConfig); - saml2LogoutFilter.doFilter(request, response, chain); - - verify(chain, VerificationModeFactory.times(1)).doFilter(request, response); - verify(httpSession, VerificationModeFactory.times(1)).invalidate(); - } -} diff --git a/saml/gatein-saml-plugin/src/test/resources/jbid_test_keystore.jks b/saml/gatein-saml-plugin/src/test/resources/jbid_test_keystore.jks deleted file mode 100644 index 95c597b5bb75a52663da4fc280a71298f5481d4e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1276 zcmezO_TO6u1_mY|W&~rd;?$zD)S~3nq7tBx+->vVJwWN522D&`4fxo&wAmP07`2!L z85vm_Selp?KA*qi{@0mDQ{JvN7x*AktzyhGB~qe{^L=;U^dO%dlG7e>UrpCmo&K&s z(VnB}^u*Wc4~{qmmrlRgk{kB;i}d5Ab262rmt_QA%F{H`@?;D1?BBC8t?h@2!r5tm z;{QI4T5xNb^6$;2zx}nzy0?;i!jkD40>CWQ2%_@!i~J!J}+fV*NmNaBt7r;%zq23&37qitT>b-k+S8x zcK;bGp*@-q3P zK?+~-8gs?PU#Gu3$^A-XqulKZsS{y6CqGm#Q$6%ui%B?t_5`W!t9?(GRO_wD2iI5~POs)LKUDZ+PKM=W+0(MJ*X?v`vv~h8oPDTp`uOtC8#)eq zT)b-Z{YmkG4ljXa$M+tpDlEAo5_?B`>%zvLy2**Nt3?)lJ@=&6Wr3k3=h;Pwr}-8;7b?27Bz@16TL^8;{V6=HU5ddHhI_Cf*j|G-Y(m*QT%z3zTwsy zw$6}~d!Jfoew=-*FK9B~?CHjbdm=(x;*NdcTOGP-?`lVrr@~Ty0%L0!Zhg9;pT;?@ z%W2b%_|`uvB74{jofRxHbk`X-yWL_4sL}j+dZqf3|C#Z%y7QN~UgUoPPSmUsdZq@J z!1VmXpo#Gd5XUmHc;;sX8St`kYPET^edlFlWMO46a5UsL;ACSCWnmL$3Jo^oGvEPn zxP)1~obro{VSH{FU&ufJB+o3&nU$28qEM1rTw)+6&TC+4U}$J+Xl80+ViX1Dn!vf# zu%dB3vb%v9k-4##!Jx5|sj-pa&5Bvpd&DHazfL{+N%xrfX0>YHRF~%r#limed_PqE zeqVBYr8{H7DOU4YAMSJ2AL&|o!NH_nc5cg;gQ8C=F9`g;cjGW?S2xS&AC5Qn{$Y${ zn|ene@0Qcm>N|Grn&NheEQ&nWW4FIxyIC%uk(~z&R%W2Pq7$c2Y3<7EjnNi7^RgzS;O?4kmB}}DzK^+}<7CR3yF*FgEfWi4 z@-p%KNELy3ZL>mmJZSA;opjmt)r}aA^(9m8M!$FdQ7~(X%!G>TkKa^Ym}>Jq;HLU3 z-$hwGH%g|bx3NS@O$qD$oBQabhMM(#{lX6uo-XtVS~vIFslq8U52>Hn#+i3@=KMX9 R|D;qrnc4!^aFqo20swC>AJ6~* diff --git a/saml/gatein-saml-plugin/src/test/resources/picketlink-sp.xml b/saml/gatein-saml-plugin/src/test/resources/picketlink-sp.xml deleted file mode 100644 index 04a1ff045..000000000 --- a/saml/gatein-saml-plugin/src/test/resources/picketlink-sp.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - http://localhost:8080 - http://localhost:8080 - - - - - - - - - - - - - - - - - - - - - - - diff --git a/spnego/pom.xml b/spnego/pom.xml deleted file mode 100644 index ab86d8dec..000000000 --- a/spnego/pom.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - org.exoplatform.gatein.sso - sso-parent - ../pom.xml - 6.6.x-SNAPSHOT - - - 4.0.0 - spnego - jar - GateIn SPNEGO LoginModule based on JBoss Negotiation - - - - org.exoplatform.core - exo.core.component.organization.api - - - org.jboss.security - jboss-negotiation-spnego - - - org.exoplatform.gatein.sso - sso-agent - - - - - - - - - - - run-its - - - - org.apache.maven.plugins - maven-surefire-plugin - - true - - - - - - - - diff --git a/spnego/src/main/java/org/gatein/sso/spnego/SPNEGOLoginModule.java b/spnego/src/main/java/org/gatein/sso/spnego/SPNEGOLoginModule.java deleted file mode 100644 index 7a17903ca..000000000 --- a/spnego/src/main/java/org/gatein/sso/spnego/SPNEGOLoginModule.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * JBoss, a division of Red Hat - * Copyright 2011, Red Hat Middleware, LLC, and individual - * contributors as indicated by the @authors tag. See the - * copyright.txt in the distribution for a full listing of - * individual contributors. - * - * This 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 2.1 of - * the License, or (at your option) any later version. - * - * This software 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 software; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA, or see the FSF site: http://www.fsf.org. - */ - -package org.gatein.sso.spnego; - -import org.exoplatform.services.security.jaas.UserPrincipal; -import org.jboss.security.negotiation.common.NegotiationContext; - -import javax.security.auth.Subject; -import javax.security.auth.callback.CallbackHandler; -import javax.security.auth.login.LoginContext; -import javax.security.auth.login.LoginException; -import java.security.Principal; -import java.util.Map; -import java.util.Set; - -/** - * Modified version of {@link org.jboss.security.negotiation.spnego.SPNEGOLoginModule} customized for portal purposes - * - * @author Marek Posolda - */ -public class SPNEGOLoginModule extends org.jboss.security.negotiation.spnego.SPNEGOLoginModule -{ - private String usernamePasswordDomain; - - // TODO: Workaround. Remove once getIdentityFromSubject method will be added to superclass. - @Override - public void initialize(final Subject subject, final CallbackHandler callbackHandler, final Map sharedState, - final Map options) - { - super.initialize(subject, callbackHandler, sharedState, options); - usernamePasswordDomain = (String) options.get("usernamePasswordDomain"); - } - - // TODO: Workaround. Remove once getIdentityFromSubject method will be added to superclass. - @Override - protected Object innerLogin() throws LoginException - { - NegotiationContext negotiationContext = NegotiationContext.getCurrentNegotiationContext(); - - if (negotiationContext == null) - { - if (usernamePasswordDomain == null) - { - throw new LoginException("No NegotiationContext and no usernamePasswordDomain defined."); - } - - return usernamePasswordLogin(); - } - else - { - return super.innerLogin(); - } - } - - // TODO: Workaround. Remove once getIdentityFromSubject method will be added to superclass. - private Object usernamePasswordLogin() throws LoginException - { - log.debug("Falling back to username/password authentication"); - - LoginContext lc = new LoginContext(usernamePasswordDomain, callbackHandler); - lc.login(); - - Subject userSubject = lc.getSubject(); - - Principal identity = getIdentityFromSubject(userSubject); - setIdentity(identity); - - return Boolean.TRUE; - } - - - /** - * Obtaining identity from subject. We need to find instance of {@link UserPrincipal} - * , which is added here during FORM authentication. - * - * @param userSubject subject from FORM authentication - * @return identity - * @throws javax.security.auth.login.LoginException - */ - protected Principal getIdentityFromSubject(Subject userSubject) throws LoginException - { - Set principals = userSubject.getPrincipals(UserPrincipal.class); - if (principals.isEmpty()) - { - throw new LoginException("No UserPrincipals returned after login."); - } - else if (principals.size() > 1) - { - log.warn("Multiple UserPrincipals returned, using first principal in set."); - } - - Principal identity = (Principal) principals.iterator().next(); - return identity; - } -} diff --git a/spnegosso/README.md b/spnegosso/README.md deleted file mode 100644 index 50b4ad5c9..000000000 --- a/spnegosso/README.md +++ /dev/null @@ -1,43 +0,0 @@ -This is other spnego implementation beside https://github.com/gatein/gatein-sso/tree/master/spnego -We introduce new spnego implementation because existing implementation dose not work on gatein tomcat packaging. -This implementation work well on both jboss and tomcat packaging. - -###Build and configure - -1. Configure SPNEGO Server - You configure SPNEGO server follow the guideline at gatein document: https://docs.jboss.org/author/display/GTNPORTAL37/SPNEGO - -2. Build and deploy spnegosso - - Use maven to build gatein-spnego project - - Copy spnegosso-${VERSION}.jar to $GATEIN_TOMCAT/lib folder - -3. Configure gatein - - Append this login module configuration into $GATEIN_HOME/conf/jaas.conf -``` -spnego-server { - com.sun.security.auth.module.Krb5LoginModule required - storeKey=true - doNotPrompt=true - useKeyTab=true - keyTab="/etc/krb5.keytab" - principal="HTTP/server.local.network@LOCAL.NETWORK" - useFirstPass=true - debug=true - isInitiator=false; -}; -``` - - - Change SSO section in the file $GATEIN_HOME/gatein/conf/configuration.properties to be like this: -``` -gatein.sso.enabled=true -gatein.sso.filter.spnego.enabled=true -gatein.sso.callback.enabled=false -gatein.sso.skip.jsp.redirection=false -gatein.sso.login.module.enabled=true -gatein.sso.login.module.class=org.gatein.security.sso.spnego.SPNEGOSSOLoginModule -gatein.sso.filter.login.sso.url=/@@portal.container.name@@/spnegosso -gatein.sso.filter.initiatelogin.enabled=false -gatein.sso.valve.enabled=false -gatein.sso.filter.logout.enabled=false -``` - diff --git a/spnegosso/pom.xml b/spnegosso/pom.xml deleted file mode 100644 index 61a1fef89..000000000 --- a/spnegosso/pom.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - 4.0.0 - - - org.exoplatform.gatein.sso - sso-parent - ../pom.xml - 6.6.x-SNAPSHOT - - spnegosso - - - - javax.servlet - javax.servlet-api - - - org.exoplatform.gatein.sso - sso-agent - - - org.gatein.common - common-common - - - - diff --git a/spnegosso/src/main/java/org/gatein/security/sso/spnego/SPNEGOSSOContext.java b/spnegosso/src/main/java/org/gatein/security/sso/spnego/SPNEGOSSOContext.java deleted file mode 100644 index ef93badc6..000000000 --- a/spnegosso/src/main/java/org/gatein/security/sso/spnego/SPNEGOSSOContext.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2012 eXo Platform SAS. - * - * This 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 2.1 of - * the License, or (at your option) any later version. - * - * This software 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 software; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA, or see the FSF site: http://www.fsf.org. - */ -package org.gatein.security.sso.spnego; - -import javax.servlet.http.HttpServletRequest; - -public class SPNEGOSSOContext { - private static ThreadLocal currentRequest = new ThreadLocal(); - - public static void setCurrentRequest(HttpServletRequest req) { - currentRequest.set(req); - } - public static HttpServletRequest getCurrentRequest() { - return currentRequest.get(); - } -} diff --git a/spnegosso/src/main/java/org/gatein/security/sso/spnego/SPNEGOSSOFilter.java b/spnegosso/src/main/java/org/gatein/security/sso/spnego/SPNEGOSSOFilter.java deleted file mode 100644 index 2985c0c51..000000000 --- a/spnegosso/src/main/java/org/gatein/security/sso/spnego/SPNEGOSSOFilter.java +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright (C) 2012 eXo Platform SAS. - * - * This 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 2.1 of - * the License, or (at your option) any later version. - * - * This software 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 software; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA, or see the FSF site: http://www.fsf.org. - */ -package org.gatein.security.sso.spnego; - -import java.io.IOException; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; -import java.util.UUID; -import javax.security.auth.Subject; -import javax.security.auth.login.LoginContext; -import javax.security.auth.login.LoginException; -import javax.servlet.FilterChain; -import javax.servlet.RequestDispatcher; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; - -import org.exoplatform.services.log.ExoLogger; -import org.exoplatform.services.log.Log; -import org.gatein.common.util.Base64; -import org.gatein.sso.agent.filter.api.AbstractSSOInterceptor; -import org.ietf.jgss.GSSContext; -import org.ietf.jgss.GSSCredential; -import org.ietf.jgss.GSSException; -import org.ietf.jgss.GSSManager; -import org.ietf.jgss.Oid; - -public class SPNEGOSSOFilter extends AbstractSSOInterceptor { - private static final Log log = ExoLogger.getLogger(AbstractSSOInterceptor.class); - - private static final GSSManager MANAGER = GSSManager.getInstance(); - - private LoginContext loginContext; - private String[] patterns = {"/login", "/spnegosso"}; - private String loginServletPath = "/login"; - private String securityDomain = "spnego-server"; - - public SPNEGOSSOFilter() {} - - @Override - protected void initImpl() { - String patternParam = this.getInitParameter("patterns"); - if(patternParam != null && !patternParam.isEmpty()) { - this.patterns = patternParam.split(","); - } - - String loginServlet = this.getInitParameter("loginServletPath"); - if(loginServlet != null && !loginServlet.isEmpty()) { - this.loginServletPath = loginServlet; - } - - String domain = this.getInitParameter("securityDomain"); - if(domain != null && !domain.isEmpty()) { - this.securityDomain = domain; - } - - try { - this.loginContext = new LoginContext(this.securityDomain); - } catch (LoginException ex) { - log.warn("Exception while init LoginContext, so SPNEGO SSO will not work", ex); - } - } - - @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { - final HttpServletRequest req = (HttpServletRequest)request; - final HttpServletResponse resp = (HttpServletResponse)response; - - //. Check if this is not spnego login request - if(!isSpnegoLoginRequest(req)) { - chain.doFilter(request, response); - return; - } - - SPNEGOSSOContext.setCurrentRequest(req); - final String contextPath = req.getContextPath(); - final String loginURI = contextPath + this.loginServletPath; - final String requestURI = req.getRequestURI(); - String username = req.getParameter("username"); - final String remoteUser = req.getRemoteUser(); - - if(username != null || remoteUser != null) { - if(!loginURI.equalsIgnoreCase(requestURI)) { - // Redirect to /login if current request is /spnegosso to avoid error 404 - // when user access to /spnegosso?username=username or when loggedIn user access to /spengosso - StringBuilder login = new StringBuilder(loginURI); - if(req.getQueryString() != null) { - login.append("?").append(req.getQueryString()); - } - resp.sendRedirect(login.toString()); - } else { - chain.doFilter(req, resp); - } - return; - } - - String principal = null; - final String auth = req.getHeader("Authorization"); - if(auth != null) { - try { - principal = this.login(req, resp, auth); - } catch (Exception ex) { - log.error("Exception occur when trying to login with SPNEGO", ex); - } - } - - if(principal != null && !principal.isEmpty()) { - username = principal.substring(0, principal.indexOf('@')); - // We don't need user password when he login using SSO (SPNEGO) - // But LoginServlet require password is not empty to call login action instead of display input form - // So, we need to generate a random password - String password = UUID.randomUUID().toString(); - - HttpSession session = req.getSession(); - session.setAttribute("SPNEGO_PRINCIPAL", username); - - StringBuilder login = new StringBuilder(loginURI) - .append("?username=") - .append(username) - .append("&password=") - .append(password); - String initURL = req.getParameter("initialURI"); - if(initURL != null) { - login.append("&initialURI=").append(initURL); - } - - resp.sendRedirect(login.toString()); - } else { - if(!loginURI.equals(requestURI)) { - RequestDispatcher dispatcher = req.getRequestDispatcher("/login"); - dispatcher.include(req, resp); - } else { - chain.doFilter(req, resp); - } - resp.setHeader("WWW-Authenticate", "Negotiate"); - resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED); - } - } - - private boolean isSpnegoLoginRequest(HttpServletRequest request) { - final String uri = request.getRequestURI(); - final String context = request.getContextPath(); - for(String pattern : this.patterns) { - if(uri.equals(context.concat(pattern))) { - return true; - } - } - return false; - } - - private String login(HttpServletRequest req, HttpServletResponse resp, String auth) throws Exception { - if(this.loginContext == null) { - return null; - } - this.loginContext.login(); - - final String principal; - final String tok = auth.substring("Negotiate".length() + 1); - final byte[] gss = Base64.decode(tok); - - GSSContext context = null; - byte[] token = null; - context = MANAGER.createContext(getServerCredential(loginContext.getSubject())); - token = context.acceptSecContext(gss, 0, gss.length); - - if (null == token) { - return null; - } - - resp.setHeader("WWW-Authenticate", "Negotiate" + ' ' + Base64.encodeBytes(token)); - - if (!context.isEstablished()) { - resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED); - return null; - } - - principal = context.getSrcName().toString(); - context.dispose(); - - this.loginContext.logout(); - - return principal; - } - - - /** - * Returns the {@link org.ietf.jgss.GSSCredential} the server uses for pre-authentication. - * - * @param subject account server uses for pre-authentication - * @return credential that allows server to authenticate clients - * @throws java.security.PrivilegedActionException - */ - static GSSCredential getServerCredential(final Subject subject) - throws PrivilegedActionException { - - final PrivilegedExceptionAction action = - new PrivilegedExceptionAction() { - public GSSCredential run() throws GSSException { - return MANAGER.createCredential( - null - , GSSCredential.INDEFINITE_LIFETIME - , getOid() - , GSSCredential.ACCEPT_ONLY); - } - }; - return Subject.doAs(subject, action); - } - - /** - * Returns the Universal Object Identifier representation of - * the SPNEGO mechanism. - * - * @return Object Identifier of the GSS-API mechanism - */ - private static Oid getOid() { - Oid oid = null; - try { - oid = new Oid("1.3.6.1.5.5.2"); - } catch (GSSException gsse) { - gsse.printStackTrace(); - } - return oid; - } - - @Override - public void destroy() {} -} diff --git a/spnegosso/src/main/java/org/gatein/security/sso/spnego/SPNEGOSSOLoginModule.java b/spnegosso/src/main/java/org/gatein/security/sso/spnego/SPNEGOSSOLoginModule.java deleted file mode 100644 index 0227c18ab..000000000 --- a/spnegosso/src/main/java/org/gatein/security/sso/spnego/SPNEGOSSOLoginModule.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2012 eXo Platform SAS. - * - * This 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 2.1 of - * the License, or (at your option) any later version. - * - * This software 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 software; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA, or see the FSF site: http://www.fsf.org. - */ -package org.gatein.security.sso.spnego; - -import javax.security.auth.login.LoginException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; -import org.exoplatform.container.ExoContainer; -import org.exoplatform.services.log.ExoLogger; -import org.exoplatform.services.log.Log; -import org.exoplatform.services.security.Authenticator; -import org.exoplatform.services.security.Identity; -import org.exoplatform.services.security.UsernameCredential; -import org.exoplatform.services.security.jaas.AbstractLoginModule; - -public class SPNEGOSSOLoginModule extends AbstractLoginModule { - private static final Log log = ExoLogger.getLogger(SPNEGOSSOLoginModule.class); - - public static final String OPTION_ENABLE_FALLBACK_FORM_AUTHENTICATION = "enableFormAuthentication"; - - @Override - protected Log getLogger() { - return log; - } - - @Override - public boolean login() throws LoginException { - try { - ExoContainer container = getContainer(); - - HttpServletRequest servletRequest = SPNEGOSSOContext.getCurrentRequest(); - if (servletRequest == null) { - log.debug("HttpServletRequest is null. SPNEGOLoginModule will be ignored."); - return false; - } - - HttpSession session = servletRequest.getSession(); - String username = (String)session.getAttribute("SPNEGO_PRINCIPAL"); - if(username != null) { - establishSecurityContext(container, username); - if (log.isTraceEnabled()) { - log.trace("Successfully established security context for user " + username); - } - return true; - } - - } catch (Exception ex) { - log.error("Exception when trying to login with SPNEGO", ex); - } - - // Disable fallback to FORM authentication - if("false".equalsIgnoreCase((String)this.options.get(OPTION_ENABLE_FALLBACK_FORM_AUTHENTICATION))) { - throw new LoginException("FORM authentication was disabled by SPNEGO login module."); - } - - return false; - } - - @Override - public boolean commit() throws LoginException { - return true; - } - - @Override - public boolean abort() throws LoginException { - return true; - } - - @Override - public boolean logout() throws LoginException { - return true; - } - - protected void establishSecurityContext(ExoContainer container, String username) throws Exception { - Authenticator authenticator = container.getComponentInstanceOfType(Authenticator.class); - - if (authenticator == null) { - throw new LoginException("No Authenticator component found, check your configuration"); - } - - Identity identity = authenticator.createIdentity(username); - - sharedState.put("exo.security.identity", identity); - sharedState.put("javax.security.auth.login.name", username); - subject.getPublicCredentials().add(new UsernameCredential(username)); - } -} diff --git a/spnegosso/src/main/resources/conf/portal/configuration.xml b/spnegosso/src/main/resources/conf/portal/configuration.xml deleted file mode 100644 index 6ac3b3280..000000000 --- a/spnegosso/src/main/resources/conf/portal/configuration.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - org.gatein.sso.integration.SSOFilterIntegrator - - SSOFilterIntegratorPlugin - addPlugin - org.gatein.sso.integration.SSOFilterIntegratorPlugin - - - filterClass - org.gatein.security.sso.spnego.SPNEGOSSOFilter - - - enabled - ${gatein.sso.filter.spnego.enabled:false} - - - filterMapping - /* - - - - patterns - ${gatein.sso.filter.spnego.pattern:/login,/spnegosso} - - - loginServletPath - ${gatein.sso.filter.spnego.loginServletPath:/login} - - - securityDomain - ${gatein.sso.filter.spnego.securityDomain:spnego-server} - - - - -