Repository: cxf-fediz Updated Branches: refs/heads/1.2.x-fixes 569571dec -> 38c1d9939
[FEDIZ-106] - Spring plugin support for configurable token validation - part I Project: http://git-wip-us.apache.org/repos/asf/cxf-fediz/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf-fediz/commit/38c1d993 Tree: http://git-wip-us.apache.org/repos/asf/cxf-fediz/tree/38c1d993 Diff: http://git-wip-us.apache.org/repos/asf/cxf-fediz/diff/38c1d993 Branch: refs/heads/1.2.x-fixes Commit: 38c1d99390435fdf91fb2d818e68341498dc6cdb Parents: 569571d Author: Colm O hEigeartaigh <[email protected]> Authored: Thu Sep 3 14:38:56 2015 +0100 Committer: Colm O hEigeartaigh <[email protected]> Committed: Thu Sep 3 14:39:42 2015 +0100 ---------------------------------------------------------------------- .../authentication/ExpiredTokenException.java | 35 +++++++ .../FederationAuthenticationFailureHandler.java | 102 +++++++++++++++++++ .../web/FederationAuthenticationFilter.java | 53 +++++++++- .../WEB-INF/applicationContext-security.xml | 5 +- 4 files changed, 190 insertions(+), 5 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/38c1d993/plugins/spring/src/main/java/org/apache/cxf/fediz/spring/authentication/ExpiredTokenException.java ---------------------------------------------------------------------- diff --git a/plugins/spring/src/main/java/org/apache/cxf/fediz/spring/authentication/ExpiredTokenException.java b/plugins/spring/src/main/java/org/apache/cxf/fediz/spring/authentication/ExpiredTokenException.java new file mode 100644 index 0000000..7e7b0f8 --- /dev/null +++ b/plugins/spring/src/main/java/org/apache/cxf/fediz/spring/authentication/ExpiredTokenException.java @@ -0,0 +1,35 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.cxf.fediz.spring.authentication; + +import org.springframework.security.core.AuthenticationException; + +/** + * To be called when a token has expired + */ +public class ExpiredTokenException extends AuthenticationException { + + private static final long serialVersionUID = 7639463618762010981L; + + public ExpiredTokenException(String errorMessage) { + super(errorMessage); + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/38c1d993/plugins/spring/src/main/java/org/apache/cxf/fediz/spring/web/FederationAuthenticationFailureHandler.java ---------------------------------------------------------------------- diff --git a/plugins/spring/src/main/java/org/apache/cxf/fediz/spring/web/FederationAuthenticationFailureHandler.java b/plugins/spring/src/main/java/org/apache/cxf/fediz/spring/web/FederationAuthenticationFailureHandler.java new file mode 100644 index 0000000..0b9069a --- /dev/null +++ b/plugins/spring/src/main/java/org/apache/cxf/fediz/spring/web/FederationAuthenticationFailureHandler.java @@ -0,0 +1,102 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.cxf.fediz.spring.web; + +import java.io.IOException; +import java.util.Map; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.cxf.fediz.core.config.FedizContext; +import org.apache.cxf.fediz.core.exception.ProcessingException; +import org.apache.cxf.fediz.core.processor.FedizProcessor; +import org.apache.cxf.fediz.core.processor.FedizProcessorFactory; +import org.apache.cxf.fediz.core.processor.RedirectionResponse; +import org.apache.cxf.fediz.spring.FederationConfig; +import org.apache.cxf.fediz.spring.authentication.ExpiredTokenException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; + +/** + * A AuthenticationFailureHandler which will redirect a expired user (token) back to the IdP. + */ +public class FederationAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler { + + private static final Logger LOG = LoggerFactory.getLogger(FederationAuthenticationFailureHandler.class); + + private FederationConfig federationConfig; + + public FederationAuthenticationFailureHandler() { + super(); + } + + @Override + public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, + AuthenticationException exception) throws IOException, ServletException { + + if (exception instanceof ExpiredTokenException) { + String redirectUrl = null; + try { + FedizContext fedContext = federationConfig.getFedizContext(); + FedizProcessor wfProc = + FedizProcessorFactory.newFedizProcessor(fedContext.getProtocol()); + RedirectionResponse redirectionResponse = + wfProc.createSignInRequest(request, fedContext); + redirectUrl = redirectionResponse.getRedirectionURL(); + + if (redirectUrl == null) { + LOG.warn("Failed to create SignInRequest. Redirect URL null"); + throw new ServletException("Failed to create SignInRequest. Redirect URL null"); + } + + Map<String, String> headers = redirectionResponse.getHeaders(); + if (!headers.isEmpty()) { + for (String headerName : headers.keySet()) { + response.addHeader(headerName, headers.get(headerName)); + } + } + + } catch (ProcessingException ex) { + LOG.warn("Failed to create SignInRequest", ex); + throw new ServletException("Failed to create SignInRequest: " + ex.getMessage()); + } + + if (LOG.isInfoEnabled()) { + LOG.info("Redirecting to IDP: " + redirectUrl); + } + response.sendRedirect(redirectUrl); + } + + super.onAuthenticationFailure(request, response, exception); + } + + public FederationConfig getFederationConfig() { + return federationConfig; + } + + public void setFederationConfig(FederationConfig fedConfig) { + this.federationConfig = fedConfig; + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/38c1d993/plugins/spring/src/main/java/org/apache/cxf/fediz/spring/web/FederationAuthenticationFilter.java ---------------------------------------------------------------------- diff --git a/plugins/spring/src/main/java/org/apache/cxf/fediz/spring/web/FederationAuthenticationFilter.java b/plugins/spring/src/main/java/org/apache/cxf/fediz/spring/web/FederationAuthenticationFilter.java index 906246b..1c13f18 100644 --- a/plugins/spring/src/main/java/org/apache/cxf/fediz/spring/web/FederationAuthenticationFilter.java +++ b/plugins/spring/src/main/java/org/apache/cxf/fediz/spring/web/FederationAuthenticationFilter.java @@ -21,6 +21,7 @@ package org.apache.cxf.fediz.spring.web; import java.io.IOException; import java.security.cert.X509Certificate; +import java.util.Date; import javax.servlet.ServletRequest; import javax.servlet.http.HttpServletRequest; @@ -29,15 +30,22 @@ import javax.servlet.http.HttpServletResponse; import org.apache.cxf.fediz.core.FederationConstants; import org.apache.cxf.fediz.core.SAMLSSOConstants; import org.apache.cxf.fediz.core.processor.FedizRequest; +import org.apache.cxf.fediz.spring.FederationConfig; +import org.apache.cxf.fediz.spring.authentication.ExpiredTokenException; +import org.apache.cxf.fediz.spring.authentication.FederationAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; public class FederationAuthenticationFilter extends AbstractAuthenticationProcessingFilter { + private FederationConfig federationConfig; + public FederationAuthenticationFilter() { super("/j_spring_fediz_security_check"); setAuthenticationFailureHandler(new SimpleUrlAuthenticationFailureHandler()); @@ -47,9 +55,18 @@ public class FederationAuthenticationFilter extends AbstractAuthenticationProces public Authentication attemptAuthentication(final HttpServletRequest request, final HttpServletResponse response) throws AuthenticationException, IOException { - + SecurityContext context = SecurityContextHolder.getContext(); + if (context != null) { + Authentication authentication = context.getAuthentication(); + if (authentication instanceof FederationAuthenticationToken) { + // If we reach this point then the token must be expired + throw new ExpiredTokenException("Token is expired"); + } + } + String wa = request.getParameter(FederationConstants.PARAM_ACTION); String responseToken = getResponseToken(request); + FedizRequest wfReq = new FedizRequest(); wfReq.setAction(wa); wfReq.setResponseToken(responseToken); @@ -66,6 +83,29 @@ public class FederationAuthenticationFilter extends AbstractAuthenticationProces return this.getAuthenticationManager().authenticate(authRequest); } + + private boolean isTokenExpired() { + SecurityContext context = SecurityContextHolder.getContext(); + boolean detectExpiredTokens = + federationConfig != null && federationConfig.getFedizContext().isDetectExpiredTokens(); + if (context != null && detectExpiredTokens) { + Authentication authentication = context.getAuthentication(); + if (authentication instanceof FederationAuthenticationToken) { + Date tokenExpires = + ((FederationAuthenticationToken)authentication).getResponse().getTokenExpires(); + if (tokenExpires == null) { + return false; + } + + Date currentTime = new Date(); + if (currentTime.after(tokenExpires)) { + return true; + } + } + } + + return false; + } private String getResponseToken(ServletRequest request) { if (request.getParameter(FederationConstants.PARAM_RESULT) != null) { @@ -82,13 +122,20 @@ public class FederationAuthenticationFilter extends AbstractAuthenticationProces */ @Override protected boolean requiresAuthentication(final HttpServletRequest request, final HttpServletResponse response) { - final boolean result = request.getRequestURI().contains(getFilterProcessesUrl()); - + boolean result = request.getRequestURI().contains(getFilterProcessesUrl()); + result |= isTokenExpired(); if (logger.isDebugEnabled()) { logger.debug("requiresAuthentication = " + result); } return result; } + public FederationConfig getFederationConfig() { + return federationConfig; + } + public void setFederationConfig(FederationConfig fedConfig) { + this.federationConfig = fedConfig; + } + } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/38c1d993/systests/webapps/springWebapp/src/main/webapp/WEB-INF/applicationContext-security.xml ---------------------------------------------------------------------- diff --git a/systests/webapps/springWebapp/src/main/webapp/WEB-INF/applicationContext-security.xml b/systests/webapps/springWebapp/src/main/webapp/WEB-INF/applicationContext-security.xml index b2c1a08..27dc5f6 100644 --- a/systests/webapps/springWebapp/src/main/webapp/WEB-INF/applicationContext-security.xml +++ b/systests/webapps/springWebapp/src/main/webapp/WEB-INF/applicationContext-security.xml @@ -55,10 +55,11 @@ http://www.springframework.org/schema/context http://www.springframework.org/sch <bean id="federationFilter" class="org.apache.cxf.fediz.spring.web.FederationAuthenticationFilter" - p:authenticationManager-ref="authManager"> + p:authenticationManager-ref="authManager" + p:federationConfig-ref="fedizConfig"> <property name="authenticationFailureHandler"> - <bean class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler" /> + <bean class="org.apache.cxf.fediz.spring.web.FederationAuthenticationFailureHandler" p:federationConfig-ref="fedizConfig" /> </property> </bean>
