This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/main by this push:
     new 7b81210bfe Fix BZ 69839 - Ensure session ID changes are promulgated to 
SSO Valve
7b81210bfe is described below

commit 7b81210bfe96c0b66ae3dc2c493e0c477a786b99
Author: Mark Thomas <[email protected]>
AuthorDate: Thu Oct 9 15:25:42 2025 +0100

    Fix BZ 69839 - Ensure session ID changes are promulgated to SSO Valve
    
    Patch provided by Kim Johan Andersson.
    
    https://bz.apache.org/bugzilla/show_bug.cgi?id=69839
---
 java/org/apache/catalina/Session.java              |  4 ++++
 .../catalina/authenticator/LocalStrings.properties |  1 +
 .../catalina/authenticator/SingleSignOn.java       | 23 ++++++++++++++++++++++
 .../catalina/authenticator/SingleSignOnEntry.java  | 12 +++++++++++
 .../authenticator/SingleSignOnListener.java        | 14 +++++++++++--
 .../authenticator/SingleSignOnSessionKey.java      |  7 +++++++
 .../apache/catalina/session/StandardSession.java   |  3 +++
 .../authenticator/TestSSOChangeSessionId.java      |  5 +----
 webapps/docs/changelog.xml                         |  6 ++++++
 9 files changed, 69 insertions(+), 6 deletions(-)

diff --git a/java/org/apache/catalina/Session.java 
b/java/org/apache/catalina/Session.java
index b49f1682a0..921b28b087 100644
--- a/java/org/apache/catalina/Session.java
+++ b/java/org/apache/catalina/Session.java
@@ -56,6 +56,10 @@ public interface Session {
      */
     String SESSION_PASSIVATED_EVENT = "passivateSession";
 
+    /**
+     * The SessionEvent event type when a session changes its sessionId.
+     */
+    String SESSION_CHANGED_ID_EVENT = "changeSessionId";
 
     // ------------------------------------------------------------- Properties
 
diff --git a/java/org/apache/catalina/authenticator/LocalStrings.properties 
b/java/org/apache/catalina/authenticator/LocalStrings.properties
index 25b9764b8c..db69c98afd 100644
--- a/java/org/apache/catalina/authenticator/LocalStrings.properties
+++ b/java/org/apache/catalina/authenticator/LocalStrings.properties
@@ -73,6 +73,7 @@ singleSignOn.debug.principalFound=SSO found cached Principal 
[{0}] with authenti
 singleSignOn.debug.principalNotFound=SSO did not find a cached Principal. 
Erasing SSO cookie for session [{0}]
 singleSignOn.debug.register=SSO registering SSO session [{0}] for user [{1}] 
with authentication type [{2}]
 singleSignOn.debug.removeSession=SSO removing application session [{0}] from 
SSO session [{1}]
+singleSignOn.debug.sessionChangedId=SSO changing sessionID in session [{0}, 
oldSessionId {1}] from SSO session [{2}]
 singleSignOn.debug.sessionLogout=SSO processing a log out for SSO session 
[{0}] and application session [{1}]
 singleSignOn.debug.sessionTimeout=SSO processing a time out for SSO session 
[{0}] and application session [{1}]
 singleSignOn.debug.update=SSO updating SSO session [{0}] to authentication 
type [{1}]
diff --git a/java/org/apache/catalina/authenticator/SingleSignOn.java 
b/java/org/apache/catalina/authenticator/SingleSignOn.java
index 1d31889965..c1ace9da25 100644
--- a/java/org/apache/catalina/authenticator/SingleSignOn.java
+++ b/java/org/apache/catalina/authenticator/SingleSignOn.java
@@ -613,4 +613,27 @@ public class SingleSignOn extends ValveBase {
         super.stopInternal();
         engine = null;
     }
+
+    protected void sessionChangedId(String ssoId, Session session, String 
oldSessionId) {
+        if (containerLog.isDebugEnabled()) {
+            
containerLog.debug(sm.getString("singleSignOn.debug.sessionChangedId", session, 
oldSessionId, ssoId));
+        }
+
+        SingleSignOnEntry entry = cache.get(ssoId);
+        if (entry == null) {
+            return;
+        }
+
+        /*
+         * Associate the new sessionId with this SingleSignOnEntry. A 
SessionListener will be registered for the new
+         * sessionID. If not, then we would not notice any subsequent 
Session.SESSION_DESTROYED_EVENT for the session.
+         */
+        entry.addSession(this, ssoId, session);
+
+        /*
+         * Remove the obsolete sessionId from the SingleSignOnEntry. The 
sessionId part of the SingleSignOnSessionKey is
+         * final.
+         */
+        entry.removeSession(session, oldSessionId);
+    }
 }
diff --git a/java/org/apache/catalina/authenticator/SingleSignOnEntry.java 
b/java/org/apache/catalina/authenticator/SingleSignOnEntry.java
index d48ba3749b..4aa6a68796 100644
--- a/java/org/apache/catalina/authenticator/SingleSignOnEntry.java
+++ b/java/org/apache/catalina/authenticator/SingleSignOnEntry.java
@@ -101,6 +101,18 @@ public class SingleSignOnEntry implements Serializable {
         sessionKeys.remove(key);
     }
 
+    /**
+     * Removes the given <code>Session</code> from the list of those 
associated with this SSO, using the previous
+     * sessionId
+     *
+     * @param session      the <code>Session</code> to remove.
+     * @param oldSessionId the previous sessionId of the <code>Session</code> 
to remove.
+     */
+    public void removeSession(Session session, String oldSessionId) {
+        SingleSignOnSessionKey key = new SingleSignOnSessionKey(session, 
oldSessionId);
+        sessionKeys.remove(key);
+    }
+
     /**
      * Returns the HTTP Session identifiers associated with this SSO.
      *
diff --git a/java/org/apache/catalina/authenticator/SingleSignOnListener.java 
b/java/org/apache/catalina/authenticator/SingleSignOnListener.java
index 243683aa32..a2fa7646e6 100644
--- a/java/org/apache/catalina/authenticator/SingleSignOnListener.java
+++ b/java/org/apache/catalina/authenticator/SingleSignOnListener.java
@@ -40,7 +40,8 @@ public class SingleSignOnListener implements SessionListener, 
Serializable {
 
     @Override
     public void sessionEvent(SessionEvent event) {
-        if (!Session.SESSION_DESTROYED_EVENT.equals(event.getType())) {
+        final String type = event.getType();
+        if (!(Session.SESSION_DESTROYED_EVENT.equals(type) || 
Session.SESSION_CHANGED_ID_EVENT.equals(type))) {
             return;
         }
 
@@ -58,6 +59,15 @@ public class SingleSignOnListener implements 
SessionListener, Serializable {
         if (sso == null) {
             return;
         }
-        sso.sessionDestroyed(ssoId, session);
+
+        switch (type) {
+            case Session.SESSION_CHANGED_ID_EVENT:
+                sso.sessionChangedId(ssoId, session, (String) event.getData());
+                break;
+
+            case Session.SESSION_DESTROYED_EVENT:
+                sso.sessionDestroyed(ssoId, session);
+                break;
+        }
     }
 }
diff --git a/java/org/apache/catalina/authenticator/SingleSignOnSessionKey.java 
b/java/org/apache/catalina/authenticator/SingleSignOnSessionKey.java
index 8e5e8a9596..5b7c9a7460 100644
--- a/java/org/apache/catalina/authenticator/SingleSignOnSessionKey.java
+++ b/java/org/apache/catalina/authenticator/SingleSignOnSessionKey.java
@@ -43,6 +43,13 @@ public class SingleSignOnSessionKey implements Serializable {
         this.hostName = context.getParent().getName();
     }
 
+    public SingleSignOnSessionKey(Session session, String sessionId) {
+        this.sessionId = sessionId;
+        Context context = session.getManager().getContext();
+        this.contextName = context.getName();
+        this.hostName = context.getParent().getName();
+    }
+
     public String getSessionId() {
         return sessionId;
     }
diff --git a/java/org/apache/catalina/session/StandardSession.java 
b/java/org/apache/catalina/session/StandardSession.java
index 9eb6164fa9..d3812da563 100644
--- a/java/org/apache/catalina/session/StandardSession.java
+++ b/java/org/apache/catalina/session/StandardSession.java
@@ -335,6 +335,9 @@ public class StandardSession implements HttpSession, 
Session, Serializable {
     @Override
     public void tellChangedSessionId(String newId, String oldId, boolean 
notifySessionListeners,
             boolean notifyContainerListeners) {
+        // Notify interested session event listeners
+        fireSessionEvent(SESSION_CHANGED_ID_EVENT, oldId);
+
         Context context = manager.getContext();
         // notify ContainerListeners
         if (notifyContainerListeners) {
diff --git a/test/org/apache/catalina/authenticator/TestSSOChangeSessionId.java 
b/test/org/apache/catalina/authenticator/TestSSOChangeSessionId.java
index 0e46c53464..6919cd1e8d 100644
--- a/test/org/apache/catalina/authenticator/TestSSOChangeSessionId.java
+++ b/test/org/apache/catalina/authenticator/TestSSOChangeSessionId.java
@@ -32,7 +32,6 @@ import jakarta.servlet.http.HttpServletResponse;
 
 import org.junit.After;
 import org.junit.Assert;
-import org.junit.Ignore;
 import org.junit.Test;
 
 import org.apache.catalina.Context;
@@ -162,7 +161,6 @@ public class TestSSOChangeSessionId extends TomcatBaseTest {
         }
     }
 
-    @Ignore // Disable until BZ 69839 is fixed
     @Test
     public void testChangeSessionId() throws Exception {
         final Map<String,SingleSignOnEntry> cache = singleSignOn.cache;
@@ -184,8 +182,7 @@ public class TestSSOChangeSessionId extends TomcatBaseTest {
         Assert.assertEquals(1, sessions.size());
 
         final SingleSignOnSessionKey singleSignOnSessionKey1 = 
sessions.iterator().next();
-        Assert.assertNotEquals("A random SessionId is expected", NOTSORANDOMID,
-                singleSignOnSessionKey1.getSessionId());
+        Assert.assertNotEquals("A random SessionId is expected", 
NOTSORANDOMID, singleSignOnSessionKey1.getSessionId());
 
         // Perform the request that changes the session id:
         doTest(CONTEXT_PATH + URI_PROTECTED, USE_COOKIES, 
HttpServletResponse.SC_OK);
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index ff3413062f..d47122aa3e 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -202,6 +202,12 @@
       <fix>
         Reject requests that map to invalid Windows file names earlier. (markt)
       </fix>
+      <fix>
+        <bug>69839</bug>: Ensure that changes to session IDs (typically after
+        authentication) are promulgated to the SSO Valve to ensure that SSO
+        entries are fully clean-up on session expiration. Patch provided by Kim
+        Johan Andersson. (markt)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="Coyote">


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to