Repository: cxf-fediz Updated Branches: refs/heads/master 6732b3197 -> 978a89e25
[FEDIZ-97] Renaming (adding) plugin configuration properties. Improving Exception handling. Project: http://git-wip-us.apache.org/repos/asf/cxf-fediz/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf-fediz/commit/978a89e2 Tree: http://git-wip-us.apache.org/repos/asf/cxf-fediz/tree/978a89e2 Diff: http://git-wip-us.apache.org/repos/asf/cxf-fediz/diff/978a89e2 Branch: refs/heads/master Commit: 978a89e259f620c8a3ad232d82d57aa88a80db31 Parents: 6732b31 Author: Jan Bernhardt <[email protected]> Authored: Tue Feb 24 18:01:10 2015 +0100 Committer: Jan Bernhardt <[email protected]> Committed: Fri Feb 27 21:25:45 2015 +0100 ---------------------------------------------------------------------- .../cxf/fediz/core/processor/FedizRequest.java | 14 +- plugins/websphere/pom.xml | 66 +++++- .../websphere/src/main/assembly/assembly.xml | 18 ++ .../org/apache/cxf/fediz/was/Constants.java | 23 +- .../was/mapper/FileBasedRoleToGroupMapper.java | 83 ++++---- .../filter/SecurityContextTTLChecker.java | 12 +- .../cxf/fediz/was/tai/FedizInterceptor.java | 208 ++++++++++--------- 7 files changed, 269 insertions(+), 155 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/978a89e2/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FedizRequest.java ---------------------------------------------------------------------- diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FedizRequest.java b/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FedizRequest.java index d86b840..66fb396 100644 --- a/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FedizRequest.java +++ b/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FedizRequest.java @@ -21,6 +21,7 @@ package org.apache.cxf.fediz.core.processor; import java.io.Serializable; import java.security.cert.Certificate; +import java.util.Arrays; import javax.servlet.http.HttpServletRequest; @@ -81,5 +82,16 @@ public class FedizRequest implements Serializable { this.requestState = requestState; } - + @Override + public String toString() { + return "FedizRequest{" + + "action='" + action + '\'' + + ", responseToken='" + (responseToken == null ? null : responseToken.substring(0,15) + "..." ) + '\'' + + ", state='" + state + '\'' + + ", freshness='" + freshness + '\'' + + ", certs=" + (certs == null ? 0 : certs.length) + + ", request=" + request + '\'' + + ", requestState=" + requestState + '\'' + + '}'; + } } http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/978a89e2/plugins/websphere/pom.xml ---------------------------------------------------------------------- diff --git a/plugins/websphere/pom.xml b/plugins/websphere/pom.xml index d846fad..415c1ca 100644 --- a/plugins/websphere/pom.xml +++ b/plugins/websphere/pom.xml @@ -23,7 +23,7 @@ <parent> <groupId>org.apache.cxf.fediz</groupId> <artifactId>plugin</artifactId> - <version>1.1.0-SNAPSHOT</version> + <version>1.2.0-SNAPSHOT</version> <relativePath>../pom.xml</relativePath> </parent> <artifactId>fediz-websphere</artifactId> @@ -50,18 +50,50 @@ <!-- <dependency> <groupId>com.ibm.ws</groupId> + <artifactId>runtime</artifactId> + <version>7</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>com.ibm.ws</groupId> <artifactId>runtime</artifactId> <version>8</version> <type>jar</type> <scope>provided</scope> </dependency> - --> - <dependency> - <groupId>com.ibm.ws</groupId> - <artifactId>runtime</artifactId> - <version>7</version> - <scope>compile</scope> + --> + <dependency> + <groupId>com.ibm.websphere</groupId> + <artifactId>com.ibm.websphere.security</artifactId> + <version>1.0.3</version> + <type>jar</type> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>com.ibm.ws.security</groupId> + <artifactId>com.ibm.ws.security.authentication.tai</artifactId> + <version>1.0.3</version> + <type>jar</type> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>com.ibm.ws.security</groupId> + <artifactId>com.ibm.ws.security.token</artifactId> + <version>1.0.2</version> + <type>jar</type> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-simple</artifactId> + <version>${slf4j.version}</version> </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + <version>${slf4j.version}</version> + </dependency> </dependencies> <build> <plugins> @@ -92,6 +124,26 @@ <verbose>true</verbose> </configuration> </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-assembly-plugin</artifactId> + <version>2.2.1</version> + <executions> + <execution> + <id>zip-file</id> + <phase>package</phase> + <goals> + <goal>attached</goal> + </goals> + <configuration> + <descriptors> + <descriptor>src/main/assembly/assembly.xml</descriptor> + </descriptors> + </configuration> + </execution> + </executions> + </plugin> </plugins> </build> + </project> http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/978a89e2/plugins/websphere/src/main/assembly/assembly.xml ---------------------------------------------------------------------- diff --git a/plugins/websphere/src/main/assembly/assembly.xml b/plugins/websphere/src/main/assembly/assembly.xml new file mode 100644 index 0000000..fb0d6aa --- /dev/null +++ b/plugins/websphere/src/main/assembly/assembly.xml @@ -0,0 +1,18 @@ +<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 +http://maven.apache.org/xsd/assembly-1.1.0.xsd"> + <id>zip-with-dependencies</id> + <formats> + <format>zip</format> + </formats> + <includeBaseDirectory>false</includeBaseDirectory> + <dependencySets> + <dependencySet> + <outputDirectory>/</outputDirectory> + <useProjectArtifact>true</useProjectArtifact> + <unpack>false</unpack> + <scope>runtime</scope> + </dependencySet> + </dependencySets> +</assembly> http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/978a89e2/plugins/websphere/src/main/java/org/apache/cxf/fediz/was/Constants.java ---------------------------------------------------------------------- diff --git a/plugins/websphere/src/main/java/org/apache/cxf/fediz/was/Constants.java b/plugins/websphere/src/main/java/org/apache/cxf/fediz/was/Constants.java index b6be658..00a1d33 100644 --- a/plugins/websphere/src/main/java/org/apache/cxf/fediz/was/Constants.java +++ b/plugins/websphere/src/main/java/org/apache/cxf/fediz/was/Constants.java @@ -27,7 +27,7 @@ public interface Constants { String HTTP_POST_METHOD = "POST"; //String UTF_8_ENCODING_SCHEME = "UTF-8"; - String VERSION = "1.0.0"; + String VERSION = "1.2.0"; String TIMESTAMP_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'"; String USER_REGISTRY_JNDI_NAME = "UserRegistry"; @@ -36,7 +36,28 @@ public interface Constants { String SUBJECT_SESSION_ATTRIBUTE_KEY = "_tai.subject"; String SECURITY_TOKEN_SESSION_ATTRIBUTE_KEY = "fediz.security.token"; + /** + * @deprecated Use FEDIZ_CONFIG_LOCATION instead. + * + * Using this property causes problems on Websphere 8.5. See https://issues.apache.org/jira/browse/FEDIZ-97 for more + * details. + */ + @Deprecated String CONFIGURATION_FILE_PARAMETER = "config.file.location"; + /** + * This constant contains the name for the property to discover the location of the fediz configuration file. + */ + String FEDIZ_CONFIG_LOCATION = "fedizConfigLocation"; + + /** + * @deprecated Use FEDIZ_ROLE_MAPPER instead. + */ + @Deprecated String ROLE_GROUP_MAPPER = "role.group.mapper"; + /** + * This constant contains the name for the property to discover the class-name which should be used for role to + * group mappings. + */ + String FEDIZ_ROLE_MAPPER = "fedizRoleMapper"; } http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/978a89e2/plugins/websphere/src/main/java/org/apache/cxf/fediz/was/mapper/FileBasedRoleToGroupMapper.java ---------------------------------------------------------------------- diff --git a/plugins/websphere/src/main/java/org/apache/cxf/fediz/was/mapper/FileBasedRoleToGroupMapper.java b/plugins/websphere/src/main/java/org/apache/cxf/fediz/was/mapper/FileBasedRoleToGroupMapper.java index 19051c4..2ab406c 100644 --- a/plugins/websphere/src/main/java/org/apache/cxf/fediz/was/mapper/FileBasedRoleToGroupMapper.java +++ b/plugins/websphere/src/main/java/org/apache/cxf/fediz/was/mapper/FileBasedRoleToGroupMapper.java @@ -22,13 +22,7 @@ package org.apache.cxf.fediz.was.mapper; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Properties; +import java.util.*; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; @@ -45,13 +39,31 @@ import org.slf4j.LoggerFactory; * Reference implementation for a Federation Claim to local WAS Group Mapper */ public class FileBasedRoleToGroupMapper implements RoleToGroupMapper { - - private static final String INITIALIZATION_THREAD_NAME = "ClaimGroupMapper"; + + /** + * This constant contains the name for the property to discover the role mapping file refresh rate. The value of + * this property contains the number of seconds to wait, before changes in the file are detected and applied. + */ + public static final String FEDIZ_ROLE_MAPPING_REFRESH_TIMEOUT = "fedizRoleMappingRefreshTimeout"; + /** + * This constant contains the name for the property to discover the location of the role to group mapping file. + */ + public static final String FEDIZ_ROLE_MAPPING_LOCATION = "fedizRoleMappingLocation"; + + /** + * @deprecated Use FEDIZ_ROLE_MAPPING_REFRESH_TIMEOUT instead. + */ + @Deprecated private static final String REFRESH_TIMEOUT_PARAMETER = "groups.mapping.refresh.timeout"; + /** + * @deprecated Use FEDIZ_ROLE_MAPPING_LOCATION instead. + */ + @Deprecated private static final String MAPPING_FILE_PARAMETER = "groups.mapping.file"; + private static final String INITIALIZATION_THREAD_NAME = "ClaimGroupMapper"; private static final Logger LOG = LoggerFactory.getLogger(FileBasedRoleToGroupMapper.class); - + private String groupMappingFilename = "./mapping.xml"; private int refreshRateMillisec = 30 * 1000; private boolean doLoop = true; @@ -75,30 +87,22 @@ public class FileBasedRoleToGroupMapper implements RoleToGroupMapper { @Override public void initialize(Properties props) { if (props != null) { - - for (Entry<Object, Object> entry : props.entrySet()) { - if (MAPPING_FILE_PARAMETER.equals(entry.getKey())) { - String propertyValue = (String)entry.getValue(); - if (propertyValue != null) { - groupMappingFilename = propertyValue; - if (LOG.isInfoEnabled()) { - LOG.info("Mapping file set to " + propertyValue); - } - } - } - if (REFRESH_TIMEOUT_PARAMETER.equals(entry.getKey())) { - String propertyValue = (String)entry.getValue(); - if (propertyValue != null) { - refreshRateMillisec = Integer.parseInt(propertyValue) * 1000; - if (LOG.isInfoEnabled()) { - LOG.info("Mapping file refresh timeout (sec) set to " + propertyValue); - } - } - } - + String fileLocation = props.containsKey(FEDIZ_ROLE_MAPPING_LOCATION) + ? props.getProperty(FEDIZ_ROLE_MAPPING_LOCATION) + : props.getProperty(MAPPING_FILE_PARAMETER); + if (fileLocation != null) { + groupMappingFilename = fileLocation; + LOG.info("Mapping file set to {}", fileLocation); + } + String timeout = props.containsKey(FEDIZ_ROLE_MAPPING_REFRESH_TIMEOUT) + ? props.getProperty(FEDIZ_ROLE_MAPPING_REFRESH_TIMEOUT) + : props.getProperty(REFRESH_TIMEOUT_PARAMETER); + if (timeout != null) { + refreshRateMillisec = Integer.parseInt(timeout) * 1000; + LOG.info("Mapping file refresh timeout (sec) set to {}", timeout); } - } + // start the internal initialization thread Thread initializationThread = new Thread() { @Override @@ -116,9 +120,7 @@ public class FileBasedRoleToGroupMapper implements RoleToGroupMapper { initializationThread.setName(INITIALIZATION_THREAD_NAME); initializationThread.setPriority(Thread.MIN_PRIORITY); initializationThread.start(); - if (LOG.isInfoEnabled()) { - LOG.info("Mapping file refresher thread started"); - } + LOG.info("Mapping file refresher thread started"); } private void internalInit() { @@ -158,26 +160,25 @@ public class FileBasedRoleToGroupMapper implements RoleToGroupMapper { private Map<String, List<String>> loadMappingFile() throws FileNotFoundException, JAXBException { InputSource input = new InputSource(new FileInputStream(groupMappingFilename)); JAXBContext context = JAXBContext.newInstance(Mapping.class); - Mapping localmappings = (Mapping)context.createUnmarshaller().unmarshal(input); + Mapping localmappings = (Mapping) context.createUnmarshaller().unmarshal(input); Map<String, List<String>> map = new HashMap<String, List<String>>(10); Iterator<SamlToJ2EE> i = localmappings.getSamlToJ2EE().iterator(); while (i.hasNext()) { SamlToJ2EE mapping = i.next(); - LOG.debug("{} mapped to {} entries", mapping.getClaim(), mapping.getGroups().getJ2EeGroup().size()); + if (LOG.isDebugEnabled()) { + LOG.debug("{} mapped to {} entries", mapping.getClaim(), mapping.getGroups().getJ2EeGroup().size()); + } map.put(mapping.getClaim(), mapping.getGroups().getJ2EeGroup()); } - return map; } @Override public void cleanup() { - if (LOG.isInfoEnabled()) { - LOG.info("Stopping the mapping file refresher loop"); - } + LOG.info("Stopping the mapping file refresher loop"); doLoop = false; } http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/978a89e2/plugins/websphere/src/main/java/org/apache/cxf/fediz/was/servlet/filter/SecurityContextTTLChecker.java ---------------------------------------------------------------------- diff --git a/plugins/websphere/src/main/java/org/apache/cxf/fediz/was/servlet/filter/SecurityContextTTLChecker.java b/plugins/websphere/src/main/java/org/apache/cxf/fediz/was/servlet/filter/SecurityContextTTLChecker.java index fc08dce..7bc2abd 100644 --- a/plugins/websphere/src/main/java/org/apache/cxf/fediz/was/servlet/filter/SecurityContextTTLChecker.java +++ b/plugins/websphere/src/main/java/org/apache/cxf/fediz/was/servlet/filter/SecurityContextTTLChecker.java @@ -39,8 +39,8 @@ import org.w3c.dom.Element; import com.ibm.websphere.security.WSSecurityException; import com.ibm.websphere.security.auth.WSSubject; -import org.apache.cxf.fediz.core.FederationResponse; import org.apache.cxf.fediz.core.SecurityTokenThreadLocal; +import org.apache.cxf.fediz.core.processor.FedizResponse; import org.apache.cxf.fediz.was.Constants; import org.apache.cxf.fediz.was.tai.FedizInterceptor; @@ -81,7 +81,7 @@ public class SecurityContextTTLChecker extends HttpServlet implements Filter { throws IOException, ServletException { try { - FederationResponse fedResponse = null; + FedizResponse fedResponse = null; Subject subject = WSSubject.getCallerSubject(); boolean validSecurityTokenFound = false; if (subject != null) { @@ -115,12 +115,12 @@ public class SecurityContextTTLChecker extends HttpServlet implements Filter { } } - private boolean checkSecurityToken(FederationResponse response) { + private boolean checkSecurityToken(FedizResponse response) { long currentTime = System.currentTimeMillis(); return response.getTokenExpires().getTime() > currentTime; } - private FederationResponse getCachedFederationResponse(Subject subject) { + private FedizResponse getCachedFederationResponse(Subject subject) { Iterator<?> i = subject.getPublicCredentials().iterator(); while (i.hasNext()) { @@ -128,7 +128,7 @@ public class SecurityContextTTLChecker extends HttpServlet implements Filter { if (o instanceof Hashtable) { @SuppressWarnings("unchecked") Map<Object, Object> table = (Hashtable<Object, Object>)o; - return (FederationResponse)table.get(Constants.SUBJECT_TOKEN_KEY); + return (FedizResponse)table.get(Constants.SUBJECT_TOKEN_KEY); } } return null; @@ -145,6 +145,8 @@ public class SecurityContextTTLChecker extends HttpServlet implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { + contextPath = filterConfig.getServletContext().getContextPath(); + FedizInterceptor.registerContext(contextPath); } } http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/978a89e2/plugins/websphere/src/main/java/org/apache/cxf/fediz/was/tai/FedizInterceptor.java ---------------------------------------------------------------------- diff --git a/plugins/websphere/src/main/java/org/apache/cxf/fediz/was/tai/FedizInterceptor.java b/plugins/websphere/src/main/java/org/apache/cxf/fediz/was/tai/FedizInterceptor.java index 912be51..d33f45d 100644 --- a/plugins/websphere/src/main/java/org/apache/cxf/fediz/was/tai/FedizInterceptor.java +++ b/plugins/websphere/src/main/java/org/apache/cxf/fediz/was/tai/FedizInterceptor.java @@ -20,15 +20,17 @@ package org.apache.cxf.fediz.was.tai; import java.io.File; import java.io.IOException; -import java.net.URLEncoder; import java.rmi.RemoteException; import java.util.ArrayList; +import java.util.HashSet; import java.util.Hashtable; import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.Set; import javax.naming.InitialContext; +import javax.naming.NamingException; import javax.security.auth.Subject; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -44,33 +46,35 @@ import com.ibm.wsspi.security.tai.TrustAssociationInterceptor; import com.ibm.wsspi.security.token.AttributeNameConstants; import org.apache.cxf.fediz.core.FederationConstants; -import org.apache.cxf.fediz.core.FederationProcessor; -import org.apache.cxf.fediz.core.FederationProcessorImpl; -import org.apache.cxf.fediz.core.FederationRequest; -import org.apache.cxf.fediz.core.FederationResponse; -import org.apache.cxf.fediz.core.config.FederationConfigurator; -import org.apache.cxf.fediz.core.config.FederationContext; +import org.apache.cxf.fediz.core.RequestState; +import org.apache.cxf.fediz.core.SAMLSSOConstants; +import org.apache.cxf.fediz.core.config.FederationProtocol; +import org.apache.cxf.fediz.core.config.FedizConfigurator; +import org.apache.cxf.fediz.core.config.FedizContext; +import org.apache.cxf.fediz.core.config.SAMLProtocol; import org.apache.cxf.fediz.core.exception.ProcessingException; +import org.apache.cxf.fediz.core.processor.FederationProcessorImpl; +import org.apache.cxf.fediz.core.processor.FedizProcessor; +import org.apache.cxf.fediz.core.processor.FedizRequest; +import org.apache.cxf.fediz.core.processor.FedizResponse; +import org.apache.cxf.fediz.core.processor.RedirectionResponse; import org.apache.cxf.fediz.was.Constants; import org.apache.cxf.fediz.was.mapper.DefaultRoleToGroupMapper; import org.apache.cxf.fediz.was.mapper.RoleToGroupMapper; import org.apache.cxf.fediz.was.tai.exception.TAIConfigurationException; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; - /** - * A Trust Authentication Interceptor (TAI) that trusts a Sign-In-Response - * provided from a configured IP/STS and instantiates - * the corresponding WAS Subject + * A Trust Authentication Interceptor (TAI) that trusts a Sign-In-Response provided from a configured IP/STS + * and instantiates the corresponding WAS Subject */ public class FedizInterceptor implements TrustAssociationInterceptor { private static final Logger LOG = LoggerFactory.getLogger(FedizInterceptor.class); - private static List<String> authorizedWebApps = new ArrayList<String>(15); - + private static Set<String> authorizedWebApps = new HashSet<String>(15); + private String configFile; - private FederationConfigurator configurator; + private FedizConfigurator configurator; private RoleToGroupMapper mapper; public String getConfigFile() { @@ -110,8 +114,7 @@ public class FedizInterceptor implements TrustAssociationInterceptor { } /** - * Registers a WebApplication using its contextPath as a key. - * This method must be called by the associated + * Registers a WebApplication using its contextPath as a key. This method must be called by the associated * security ServletFilter instance of a secured application at initialization time * * @param contextPath @@ -122,10 +125,8 @@ public class FedizInterceptor implements TrustAssociationInterceptor { } /** - * Deregister a WebApplication using its contextPath as a key. - * This method must be called by the associated - * security ServletFilter instance of a secured application - * in the #destroy() method + * Deregister a WebApplication using its contextPath as a key. This method must be called by the + * associated security ServletFilter instance of a secured application in the #destroy() method * * @param contextPath */ @@ -146,7 +147,9 @@ public class FedizInterceptor implements TrustAssociationInterceptor { public int initialize(Properties props) throws WebTrustAssociationFailedException { if (props != null) { try { - String roleGroupMapper = props.getProperty(Constants.ROLE_GROUP_MAPPER); + String roleGroupMapper = props.containsKey(Constants.FEDIZ_ROLE_MAPPER) + ? props.getProperty(Constants.FEDIZ_ROLE_MAPPER) + : props.getProperty(Constants.ROLE_GROUP_MAPPER); if (roleGroupMapper != null && !roleGroupMapper.isEmpty()) { try { mapper = (RoleToGroupMapper)Class.forName(roleGroupMapper).newInstance(); @@ -163,18 +166,20 @@ public class FedizInterceptor implements TrustAssociationInterceptor { LOG.debug("Using the DefaultRoleToGroupMapper mapper class"); } - String configFileLocation = props.getProperty(Constants.CONFIGURATION_FILE_PARAMETER); + String configFileLocation = props.containsKey(Constants.FEDIZ_CONFIG_LOCATION) + ? props.getProperty(Constants.FEDIZ_CONFIG_LOCATION) + : props.getProperty(Constants.CONFIGURATION_FILE_PARAMETER); if (configFileLocation != null) { LOG.debug("Configuration file location set to {}", configFileLocation); File f = new File(configFileLocation); - configurator = new FederationConfigurator(); + configurator = new FedizConfigurator(); configurator.loadConfig(f); LOG.debug("Federation config loaded from path: {}", configFileLocation); } else { throw new WebTrustAssociationFailedException("Missing required initialization parameter " - + Constants.CONFIGURATION_FILE_PARAMETER); + + Constants.FEDIZ_CONFIG_LOCATION); } } catch (Throwable t) { LOG.warn("Failed initializing TAI", t); @@ -184,12 +189,12 @@ public class FedizInterceptor implements TrustAssociationInterceptor { return 0; } - private FederationContext getFederationContext(HttpServletRequest req) { + private FedizContext getFederationContext(HttpServletRequest req) { String contextPath = req.getContextPath(); if (contextPath == null || contextPath.isEmpty()) { contextPath = "/"; } - return configurator.getFederationContext(contextPath); + return configurator.getFedizContext(contextPath); } @@ -201,7 +206,7 @@ public class FedizInterceptor implements TrustAssociationInterceptor { @Override public boolean isTargetInterceptor(HttpServletRequest req) throws WebTrustAssociationException { LOG.debug("Request URI: {}", req.getRequestURI()); - FederationContext context = getFederationContext(req); + FedizContext context = getFederationContext(req); if (context != null) { return true; @@ -222,7 +227,7 @@ public class FedizInterceptor implements TrustAssociationInterceptor { throws WebTrustAssociationFailedException { LOG.debug("Request URI: {}", req.getRequestURI()); - FederationContext fedCtx = getFederationContext(req); + FedizContext fedCtx = getFederationContext(req); if (fedCtx == null) { LOG.warn("No Federation Context configured for context-path {}", req.getContextPath()); @@ -259,14 +264,17 @@ public class FedizInterceptor implements TrustAssociationInterceptor { if (wresult != null && wctx != null) { LOG.debug("Validating RSTR..."); // process and validate the token - FederationResponse federationResponse = processSigninRequest(req, resp); + FedizResponse federationResponse = processSigninRequest(req, resp); LOG.info("RSTR validated successfully"); - + HttpSession session = req.getSession(true); session.setAttribute(Constants.SECURITY_TOKEN_SESSION_ATTRIBUTE_KEY, federationResponse); - - LOG.info("Redirecting request to {}", wctx); - resp.sendRedirect(wctx); + RequestState requestState = (RequestState) session.getAttribute(wctx); + if (requestState != null && requestState.getTargetAddress() != null) { + LOG.info("Redirecting request to {}", requestState.getTargetAddress()); + resp.sendRedirect(requestState.getTargetAddress()); + session.removeAttribute(wctx); + } return TAIResult.create(HttpServletResponse.SC_FOUND); } else { throw new Exception("Missing required parameter [wctx or wresult]"); @@ -285,23 +293,23 @@ public class FedizInterceptor implements TrustAssociationInterceptor { return TAIResult.create(HttpServletResponse.SC_FOUND); } else { LOG.debug("Session ID is {}", session.getId()); - - FederationResponse federationResponse = (FederationResponse)session + + FedizResponse federationResponse = (FedizResponse)session .getAttribute(Constants.SECURITY_TOKEN_SESSION_ATTRIBUTE_KEY); if (federationResponse != null) { LOG.info("Security Token found in session: {}", federationResponse.getUsername()); - + TAIResult result = null; // check that the target WebApp is properly configured for Token TTL enforcement if (authorizedWebApps.contains(req.getContextPath())) { - + LOG.info("Security Filter properly configured - forwarding subject"); - + // proceed creating the JAAS Subject List<String> groupsIds = groupIdsFromTokenRoles(federationResponse); Subject subject = createSubject(federationResponse, groupsIds, session.getId()); - result = TAIResult.create(HttpServletResponse.SC_OK, "ignore", subject); + result = TAIResult.create(HttpServletResponse.SC_OK, federationResponse.getUsername(), subject); } else { result = TAIResult.create(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); LOG.warn("No Security Filter configured for {}", req.getContextPath()); @@ -319,39 +327,34 @@ public class FedizInterceptor implements TrustAssociationInterceptor { protected void redirectToIdp(HttpServletRequest request, HttpServletResponse response) throws IOException, WebTrustAssociationFailedException { - FederationProcessor processor = new FederationProcessorImpl(); + FedizProcessor processor = new FederationProcessorImpl(); String contextName = request.getContextPath(); if (contextName == null || contextName.isEmpty()) { contextName = "/"; } - FederationContext fedCtx = getFederationContext(request); - - String redirectURL = null; - StringBuilder sb = new StringBuilder(); + FedizContext fedCtx = getFederationContext(request); try { - redirectURL = processor.createSignInRequest(request, fedCtx); - if (redirectURL != null) { - sb.append(redirectURL); - - } - request.getQueryString(); - if (request.getRequestURI() != null && request.getRequestURI().length() > 0) { - sb.append('&').append(FederationConstants.PARAM_CONTEXT).append('=') - .append(URLEncoder.encode(request.getRequestURI(), "UTF-8")); - } - if (request.getQueryString() != null && !request.getQueryString().isEmpty()) { - sb.append('?'); - sb.append(URLEncoder.encode(request.getQueryString(), "UTF-8")); - } - + RedirectionResponse redirectionResponse = processor.createSignInRequest(request, fedCtx); + String redirectURL = redirectionResponse.getRedirectionURL(); if (redirectURL != null) { - response.sendRedirect(sb.toString()); + Map<String, String> headers = redirectionResponse.getHeaders(); + if (!headers.isEmpty()) { + for (String headerName : headers.keySet()) { + response.addHeader(headerName, headers.get(headerName)); + } + } + // Save request in our session before redirect to IDP + RequestState requestState = redirectionResponse.getRequestState(); + if (requestState != null) { + HttpSession session = request.getSession(true); + session.setAttribute(requestState.getState(), requestState); + } + response.sendRedirect(redirectURL); } else { LOG.error("RedirectUrl is null. Failed to create SignInRequest."); - response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, - "Failed to create SignInRequest."); + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Failed to create SignInRequest."); } } catch (ProcessingException ex) { LOG.error("Failed to create SignInRequest", ex); @@ -360,38 +363,39 @@ public class FedizInterceptor implements TrustAssociationInterceptor { } - private List<String> groupIdsFromTokenRoles(FederationResponse federationResponse) throws Exception { + private List<String> groupIdsFromTokenRoles(FedizResponse federationResponse) throws Exception { InitialContext ctx = new InitialContext(); - UserRegistry reg = (UserRegistry)ctx.lookup(Constants.USER_REGISTRY_JNDI_NAME); + try { + UserRegistry reg = (UserRegistry)ctx.lookup(Constants.USER_REGISTRY_JNDI_NAME); - List<String> localGroups = mapper.groupsFromRoles(federationResponse.getRoles()); + List<String> localGroups = mapper.groupsFromRoles(federationResponse.getRoles()); - List<String> groupIds = new ArrayList<String>(1); - if (localGroups != null) { - LOG.debug("Converting {} group names to uids", localGroups.size()); - for (String localGroup : localGroups) { - String guid = convertGroupNameToUniqueId(reg, localGroup); - LOG.debug("Group '{}' maps to guid: {}", localGroup, guid); - groupIds.add(guid); + List<String> groupIds = new ArrayList<String>(1); + if (localGroups != null) { + LOG.debug("Converting {} group names to uids", localGroups.size()); + for (String localGroup : localGroups) { + String guid = convertGroupNameToUniqueId(reg, localGroup); + LOG.debug("Group '{}' maps to guid: {}", localGroup, guid); + groupIds.add(guid); + } } + if (LOG.isInfoEnabled()) { + LOG.info("Group list: " + groupIds.toString()); + } + return groupIds; + } catch (NamingException ex) { + LOG.error("User Registry could not be loaded from JNDI context."); + LOG.warn("No groups/roles could be mapped for user: {}", federationResponse.getUsername()); + return new ArrayList<String>(); + } finally { + ctx.close(); } - if (LOG.isInfoEnabled()) { - LOG.info("Group list: " + groupIds.toString()); - } - return groupIds; } /** * Creates the JAAS Subject so that WAS Runtime will not check the local registry - * - * @param securityName - * @param uniqueid - * @param groups - * @param token - * @return */ - - private Subject createSubject(FederationResponse federationResponse, List<String> groups, String cacheKey) { + private Subject createSubject(FedizResponse federationResponse, List<String> groups, String cacheKey) { String uniqueId = "user:defaultWIMFileBasedRealm/cn=" + federationResponse.getUsername() + ",o=defaultWIMFileBasedRealm"; String completeCacheKey = uniqueId + ':' + cacheKey; @@ -413,30 +417,34 @@ public class FedizInterceptor implements TrustAssociationInterceptor { return subject; } - public FederationResponse processSigninRequest(HttpServletRequest req, HttpServletResponse resp) + public FedizResponse processSigninRequest(HttpServletRequest req, HttpServletResponse resp) throws ProcessingException { - FederationRequest federationRequest = new FederationRequest(); + FedizContext fedCtx = getFederationContext(req); + FedizRequest federationRequest = new FedizRequest(); String wa = req.getParameter(FederationConstants.PARAM_ACTION); - String wct = req.getParameter(FederationConstants.PARAM_CURRENT_TIME); - String wresult = req.getParameter(FederationConstants.PARAM_RESULT); - - if (LOG.isDebugEnabled()) { - LOG.debug("wa=" + wa); - LOG.debug("wct=" + wct); - LOG.debug("wresult=" + wresult); - } + String responseToken = getResponseToken(req, fedCtx); - federationRequest.setWa(wa); - federationRequest.setWct(wct); - federationRequest.setWresult(wresult); + federationRequest.setAction(wa); + federationRequest.setResponseToken(responseToken); + federationRequest.setState(req.getParameter("RelayState")); + federationRequest.setRequest(req); - FederationContext fedCtx = getFederationContext(req); + LOG.debug("FederationRequest: {}", federationRequest); - FederationProcessor processor = new FederationProcessorImpl(); + FedizProcessor processor = new FederationProcessorImpl(); return processor.processRequest(federationRequest, fedCtx); } + private String getResponseToken(HttpServletRequest request, FedizContext fedConfig) { + if (fedConfig.getProtocol() instanceof FederationProtocol) { + return request.getParameter(FederationConstants.PARAM_RESULT); + } else if (fedConfig.getProtocol() instanceof SAMLProtocol) { + return request.getParameter(SAMLSSOConstants.SAML_RESPONSE); + } + return null; + } + /** * Convenience method for converting a list of group names to their unique group IDs *
