diff --git a/web/src/main/java/org/springframework/security/web/context/HttpSessionSecurityContextRepository.java b/web/src/main/java/org/springframework/security/web/context/HttpSessionSecurityContextRepository.java index c8a0b58cef..a5818d6abf 100644 --- a/web/src/main/java/org/springframework/security/web/context/HttpSessionSecurityContextRepository.java +++ b/web/src/main/java/org/springframework/security/web/context/HttpSessionSecurityContextRepository.java @@ -233,6 +233,9 @@ public class HttpSessionSecurityContextRepository implements SecurityContextRepo } private boolean isTransientAuthentication(Authentication authentication) { + if (authentication == null) { + return false; + } return AnnotationUtils.getAnnotation(authentication.getClass(), Transient.class) != null; } @@ -327,6 +330,9 @@ public class HttpSessionSecurityContextRepository implements SecurityContextRepo @Override protected void saveContext(SecurityContext context) { final Authentication authentication = context.getAuthentication(); + if (isTransientAuthentication(authentication)) { + return; + } HttpSession httpSession = this.request.getSession(false); String springSecurityContextKey = HttpSessionSecurityContextRepository.this.springSecurityContextKey; // See SEC-776 @@ -348,7 +354,7 @@ public class HttpSessionSecurityContextRepository implements SecurityContextRepo } return; } - httpSession = (httpSession != null) ? httpSession : createNewSessionIfAllowed(context, authentication); + httpSession = (httpSession != null) ? httpSession : createNewSessionIfAllowed(context); // If HttpSession exists, store current SecurityContext but only if it has // actually changed in this thread (see SEC-37, SEC-1307, SEC-1528) if (httpSession != null) { @@ -369,10 +375,7 @@ public class HttpSessionSecurityContextRepository implements SecurityContextRepo || context.getAuthentication() != this.authBeforeExecution; } - private HttpSession createNewSessionIfAllowed(SecurityContext context, Authentication authentication) { - if (isTransientAuthentication(authentication)) { - return null; - } + private HttpSession createNewSessionIfAllowed(SecurityContext context) { if (this.httpSessionExistedAtStartOfRequest) { this.logger.debug("HttpSession is now null, but was not null at start of request; " + "session was invalidated, so do not create a new session"); diff --git a/web/src/test/java/org/springframework/security/web/context/HttpSessionSecurityContextRepositoryTests.java b/web/src/test/java/org/springframework/security/web/context/HttpSessionSecurityContextRepositoryTests.java index 45c78003db..add6c00e8c 100644 --- a/web/src/test/java/org/springframework/security/web/context/HttpSessionSecurityContextRepositoryTests.java +++ b/web/src/test/java/org/springframework/security/web/context/HttpSessionSecurityContextRepositoryTests.java @@ -21,6 +21,7 @@ import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import java.util.Collections; import jakarta.servlet.Filter; import jakarta.servlet.ServletException; @@ -614,6 +615,21 @@ public class HttpSessionSecurityContextRepositoryTests { assertThat(session).isNull(); } + @Test + public void saveContextWhenTransientAuthenticationAndSessionExistsThenSkipped() { + HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository(); + MockHttpServletRequest request = new MockHttpServletRequest(); + request.getSession(); // ensure the session exists + MockHttpServletResponse response = new MockHttpServletResponse(); + HttpRequestResponseHolder holder = new HttpRequestResponseHolder(request, response); + SecurityContext context = repo.loadContext(holder); + SomeTransientAuthentication authentication = new SomeTransientAuthentication(); + context.setAuthentication(authentication); + repo.saveContext(context, holder.getRequest(), holder.getResponse()); + MockHttpSession session = (MockHttpSession) request.getSession(false); + assertThat(Collections.list(session.getAttributeNames())).isEmpty(); + } + @Test public void saveContextWhenTransientAuthenticationWithCustomAnnotationThenSkipped() { HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();