Skip to content

Commit

Permalink
Merge pull request #4440 from inception-project/bugfix/4439-Logout-ma…
Browse files Browse the repository at this point in the history
…y-sometimes-be-incomplete

#4439 - Logout may sometimes be incomplete
  • Loading branch information
reckart authored Jan 22, 2024
2 parents 1df6917 + 392b54f commit d74e081
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@
*/
package de.tudarmstadt.ukp.clarin.webanno.security;

import java.lang.invoke.MethodHandles;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.reflect.FieldUtils;
import org.apache.wicket.Session;
import org.apache.wicket.authroles.authentication.AuthenticatedWebSession;
import org.apache.wicket.authroles.authorization.strategies.role.Roles;
Expand All @@ -37,11 +43,15 @@
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
import org.springframework.security.web.FilterChainProxy;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;

import de.tudarmstadt.ukp.clarin.webanno.security.config.AuthenticationConfigurationHolder;
import de.tudarmstadt.ukp.inception.support.logging.Logging;
import de.tudarmstadt.ukp.inception.support.spring.ApplicationContextProvider;
import de.tudarmstadt.ukp.inception.support.spring.ApplicationEventPublisherHolder;

/**
Expand All @@ -52,7 +62,7 @@ public class SpringAuthenticatedWebSession
{
private static final long serialVersionUID = 1L;

private final Logger log = LoggerFactory.getLogger(getClass());
private final static Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

private @SpringBean AuthenticationConfigurationHolder authenticationConfigurationHolder;
private @SpringBean ApplicationEventPublisherHolder applicationEventPublisherHolder;
Expand Down Expand Up @@ -113,11 +123,11 @@ public boolean authenticate(String username, String password)
return true;
}
catch (AuthenticationException e) {
log.warn("User [{}] failed to login. Reason: {}", username, e.getMessage());
LOG.warn("User [{}] failed to login. Reason: {}", username, e.getMessage());
return false;
}
catch (Exception e) {
log.error("Unexpected error during authentication: ", e.getMessage(), e);
LOG.error("Unexpected error during authentication: ", e.getMessage(), e);
return false;
}
}
Expand Down Expand Up @@ -146,12 +156,12 @@ private void springSecuritySignIn(Authentication aAuthentication)
MDC.put(Logging.KEY_USERNAME, aAuthentication.getName());

SecurityContextHolder.getContext().setAuthentication(aAuthentication);
log.debug("Stored authentication for user [{}] in security context",
LOG.debug("Stored authentication for user [{}] in security context",
aAuthentication.getName());

setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY,
SecurityContextHolder.getContext());
log.debug("Stored security context in session");
LOG.debug("Stored security context in session");

bind();

Expand Down Expand Up @@ -184,9 +194,30 @@ public void signIn(Authentication aAuthentication)
@Override
public void signOut()
{
log.debug("Logging out");
LOG.debug("Logging out");

super.signOut();
SecurityContextHolder.clearContext();

var request = RequestCycle.get().getRequest();
var httpRequest = (HttpServletRequest) request.getContainerRequest();
var httpResponse = (HttpServletResponse) RequestCycle.get().getResponse()
.getContainerResponse();

var filterChainProxy = ApplicationContextProvider.getApplicationContext()
.getBean(FilterChainProxy.class);
var chain = filterChainProxy.getFilters(request.getFilterPath());
var logoutFilter = chain.stream().filter(f -> f instanceof LogoutFilter).findFirst().get();
try {
// We cannot simply call doFilter because the LogoutFilter is configured
// to operate only on a certain URL... so we need to emulate it the hard
// way
var handler = (LogoutHandler) FieldUtils.readField(logoutFilter, "handler", true);
var auth = SecurityContextHolder.getContext().getAuthentication();
handler.logout(httpRequest, httpResponse, auth);
}
catch (IllegalAccessException e) {
LOG.error("Error trying to log out via Spring Security LogoutHandler", e);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,13 @@ private void actionLogout()
public static void actionLogout(Component aOwner,
PreauthenticationProperties aPreauthProperties, LoginProperties aSecProperties)
{
// It would be nicer if we could just use the default Spring Security logout
// mechanism by making the logout button a link to `/logout`, but since
// we want to perform extra stuff afterwards, we currently use this way.
//
// The alternative would be to register a custom LogoutSuccessHandler with
// Spring Security which would do our special logout redirection behavior

ApplicationSession.get().signOut();

if (aPreauthProperties.getLogoutUrl().isPresent()) {
Expand Down

0 comments on commit d74e081

Please sign in to comment.