Commit b3042b9d authored by Gradl, Tobias's avatar Gradl, Tobias
Browse files

711: Improve logout behavior

Task-Url: https://minfba.de.dariah.eu/mantisbt/view.php?id=711
parent fd963ae1
package eu.dariah.de.dariahsp.configuration;
import org.springframework.context.annotation.ConfigurationCondition;
public abstract class ActivatableCondition implements ConfigurationCondition {
private static boolean active;
public static boolean isActive() { return active; }
protected static void setActive(boolean active) { ActivatableCondition.active = active; }
}
......@@ -3,6 +3,7 @@ package eu.dariah.de.dariahsp.configuration;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ConfigurationCondition;
import org.springframework.context.annotation.ImportResource;
import org.springframework.core.type.AnnotatedTypeMetadata;
......@@ -10,15 +11,14 @@ import org.springframework.core.type.AnnotatedTypeMetadata;
@Conditional(ConditionalLocalSecurityConfiguration.Condition.class)
@ImportResource("classpath:spring/security/security-context-local.xml")
public class ConditionalLocalSecurityConfiguration {
public static class Condition extends ActivatableCondition {
public static class Condition implements ConfigurationCondition {
@Override
public ConfigurationPhase getConfigurationPhase() {
return ConfigurationPhase.PARSE_CONFIGURATION;
}
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
setActive(System.getProperty("saml")==null || !Boolean.parseBoolean(System.getProperty("saml")));
return isActive();
return System.getProperty("saml")==null || !Boolean.parseBoolean(System.getProperty("saml"));
}
}
}
......@@ -3,6 +3,7 @@ package eu.dariah.de.dariahsp.configuration;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ConfigurationCondition;
import org.springframework.context.annotation.ImportResource;
import org.springframework.core.type.AnnotatedTypeMetadata;
......@@ -10,15 +11,14 @@ import org.springframework.core.type.AnnotatedTypeMetadata;
@Conditional(ConditionalSamlSecurityConfiguration.Condition.class)
@ImportResource("classpath:spring/security/security-context-saml.xml")
public class ConditionalSamlSecurityConfiguration {
public static class Condition extends ActivatableCondition {
public static class Condition implements ConfigurationCondition {
@Override
public ConfigurationPhase getConfigurationPhase() {
return ConfigurationPhase.PARSE_CONFIGURATION;
}
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
setActive(System.getProperty("saml")!=null && Boolean.parseBoolean(System.getProperty("saml")));
return isActive();
return System.getProperty("saml")!=null && Boolean.parseBoolean(System.getProperty("saml"));
}
}
}
\ No newline at end of file
package eu.dariah.de.dariahsp.saml;
import javax.servlet.http.HttpServletRequest;
import org.opensaml.common.xml.SAMLConstants;
import org.opensaml.saml2.metadata.IDPSSODescriptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.saml.SAMLCredential;
import org.springframework.security.saml.metadata.MetadataManager;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
public class SAMLLogoutFilter extends org.springframework.security.saml.SAMLLogoutFilter {
private static final Logger logger = LoggerFactory.getLogger(SAMLLogoutFilter.class);
@Autowired protected MetadataManager metadata;
public SAMLLogoutFilter(LogoutSuccessHandler logoutSuccessHandler, LogoutHandler[] localHandler, LogoutHandler[] globalHandlers) {
super(logoutSuccessHandler, localHandler, globalHandlers);
}
public SAMLLogoutFilter(String successUrl, LogoutHandler[] localHandler, LogoutHandler[] globalHandlers) {
super(successUrl, localHandler, globalHandlers);
}
@Override
protected boolean isGlobalLogout(HttpServletRequest request, Authentication auth) {
try {
if (auth!=null && auth.getCredentials()!=null && auth.getCredentials() instanceof SAMLCredential) {
String entityId = ((SAMLCredential)auth.getCredentials()).getRemoteEntityID().toString();
IDPSSODescriptor idp = metadata.getEntityDescriptor(entityId).getIDPSSODescriptor(SAMLConstants.SAML20P_NS);
return idp.getSingleLogoutServices()!=null && idp.getSingleLogoutServices().size()>0;
}
} catch (Exception e) {
logger.error("Failed to determine single logout capabilities for entity", e);
}
return super.isGlobalLogout(request, auth);
}
}
package eu.dariah.de.dariahsp.saml;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.saml.websso.SingleLogoutProfileImpl;
import eu.dariah.de.dariahsp.time.TimeService;
public class SAMLLogoutProfile extends SingleLogoutProfileImpl {
@Autowired
private TimeService timeService;
//@Override
protected boolean isDateTimeSkewValid(int skewInSec, DateTime time) {
long current = timeService.getNow().getMillis();
return time.isAfter(current - skewInSec * 1000) && time.isBefore(current + skewInSec * 1000);
}
}
......@@ -6,6 +6,12 @@ import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import javax.xml.namespace.QName;
import org.opensaml.common.xml.SAMLConstants;
import org.opensaml.saml2.metadata.EntityDescriptor;
import org.opensaml.saml2.metadata.IDPSSODescriptor;
import org.opensaml.saml2.metadata.SingleLogoutService;
import org.opensaml.saml2.metadata.provider.MetadataProvider;
import org.opensaml.saml2.metadata.provider.MetadataProviderException;
import org.slf4j.Logger;
......@@ -41,5 +47,4 @@ public class ConditionalMetadataManager extends CachingMetadataManager {
}
return false;
}
}
......@@ -8,6 +8,7 @@ import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.security.web.savedrequest.RequestCache;
import org.springframework.stereotype.Controller;
......@@ -17,6 +18,7 @@ import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import eu.dariah.de.dariahsp.configuration.ConditionalSamlSecurityConfiguration;
import eu.dariah.de.dariahsp.web.AuthInfoHelper;
import eu.dariah.de.dariahsp.web.RedirectCache;
@Controller
......@@ -26,6 +28,11 @@ public class HomeController {
@Autowired private RedirectCache redirectCache;
@Autowired private AuthInfoHelper authInfoHelper;
@Value("#{environment.saml?environment.saml:false}")
private boolean saml;
@RequestMapping(value = {"", "/"}, method = RequestMethod.GET)
public String getHome(HttpServletResponse response) throws IOException {
return "home";
......@@ -38,15 +45,18 @@ public class HomeController {
@RequestMapping(value = "/logout", method = RequestMethod.GET)
public String getLogout(@RequestParam(value = "error", required = false) String error, @RequestParam(value = "url", defaultValue = "/") String url, HttpServletRequest request, HttpServletResponse response, Model model) throws IOException {
if (ConditionalSamlSecurityConfiguration.Condition.isActive()) {
if (saml && authInfoHelper.getCurrentUserDetails(request).isAuth()) {
return "redirect:/saml/logout" + (!url.equals("/") ? "?loginRedirectUrl=" + url : "");
} else if (saml) {
return "common/logout";
}
// TODO What if !saml but isAuth? -> handled in filter?
return "common/logout";
}
@RequestMapping(value = "/login", method = RequestMethod.GET)
public String getLogin(@RequestParam(value = "error", required = false) String error, @RequestParam(value = "url", defaultValue = "/") String url, HttpServletRequest request, HttpServletResponse response, Model model) throws IOException {
if (ConditionalSamlSecurityConfiguration.Condition.isActive()) {
if (saml) {
return "redirect:/saml/login" + (!url.equals("/") ? "?loginRedirectUrl=" + url : "");
}
......
......@@ -64,7 +64,7 @@
<!-- Handler for successful logout -->
<bean id="successLogoutHandler" class="org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler">
<property name="defaultTargetUrl" value="/logout.jsp"/>
<property name="defaultTargetUrl" value="/logout"/>
</bean>
<security:authentication-manager alias="authenticationManager">
......@@ -302,13 +302,12 @@
</bean>
<!-- Logout handler terminating local session -->
<bean id="logoutHandler"
class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler">
<bean id="logoutHandler" class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler">
<property name="invalidateHttpSession" value="false"/>
</bean>
<!-- Override default logout processing filter with the one processing SAML messages -->
<bean id="samlLogoutFilter" class="org.springframework.security.saml.SAMLLogoutFilter">
<bean id="samlLogoutFilter" class="eu.dariah.de.dariahsp.saml.SAMLLogoutFilter">
<constructor-arg index="0" ref="successLogoutHandler"/>
<constructor-arg index="1" ref="logoutHandler"/>
<constructor-arg index="2" ref="logoutHandler"/>
......
<%@ taglib prefix="tiles" uri="http://tiles.apache.org/tags-tiles" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="s" uri="http://www.springframework.org/tags" %>
<tiles:importAttribute name="fluidLayout" />
<div class="jumbotron">
<div class="container<c:if test="${fluidLayout==true}">-fluid</c:if>">
<div class="row">
<div class="xs-hidden sm-visible col-sm-3 col-lg-2 col-sm-offset-1">
<div class="pull-right dariah-flower-white-83">DARIAHSP Test App</div>
</div>
</div>
</div>
</div>
<div class="container<c:if test="${fluidLayout==true}">-fluid</c:if>">
<div class="row">
<div id="main-content-wrapper" class="col-sm-10 col-sm-offset-1">
<ul class="breadcrumb">
<li class="active">Logout</li>
</ul>
<div id="main-content">
<h2>Logout</h2>
<p>
You have been logged out from the system. Close browser to complete
</p>
</div>
</div>
</div>
</div>
......@@ -8,9 +8,6 @@
<tiles:importAttribute name="fluidLayout" />
<s:url value="/search/simple/" var="query_url" />
<s:url value="/search/extended/" var="extended_search_url" />
<div class="jumbotron">
<div class="container<c:if test="${fluidLayout==true}">-fluid</c:if>">
<div class="row">
......
......@@ -30,4 +30,8 @@
<put-attribute name="content" value="/WEB-INF/view/jsp/common/login.jsp" />
</definition>
<definition name="common/logout" extends="template_simple">
<put-attribute name="content" value="/WEB-INF/view/jsp/common/logout.jsp" />
</definition>
</tiles-definitions>
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment