command=samlSlo (SAML Global Log Out) responds with a 302 redirect that carries no Set-Cookie header clearing JSESSIONID/userid/sessionkey. The browser therefore keeps the session key after logout, CloudStack appears to loop during sign-out, and users have to clear the browser cache (or use an incognito window) to log in again.
Root cause
SAML2LogoutAPIAuthenticatorCmd#authenticate calls resp.sendRedirect(...), which commits the response. ApiServlet's LOGOUT_API cleanup — the loop that echoes the received cookies back with an empty value and Max-Age=0 (ApiServlet L333-340) — only runs after the authenticator returns. By then the 302 is already committed, so its Set-Cookie headers are silently dropped.
Fix
Clear the session cookies (JSESSIONID, sessionkey, userid, ...) on the response before sendRedirect(...) in all four redirect paths of SAML2LogoutAPIAuthenticatorCmd, mirroring the existing cookie-cleanup loop in ApiServlet. The committed 302 now instructs the browser to drop the session cookies, and the next login starts with a fresh session key.
Testing
New unit test testAuthenticateClearsSessionCookiesBeforeRedirect verifies the received JSESSIONID/sessionkey cookies are cleared (Max-Age=0, empty value) and added to the response before the redirect.
A standalone servlet-contract simulation confirms the mechanism: cookies added after sendRedirect are dropped from the committed 302 (bug reproduced), cookies added before sendRedirect are delivered (fix verified).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes: #13997
Problem
command=samlSlo (SAML Global Log Out) responds with a 302 redirect that carries no Set-Cookie header clearing JSESSIONID/userid/sessionkey. The browser therefore keeps the session key after logout, CloudStack appears to loop during sign-out, and users have to clear the browser cache (or use an incognito window) to log in again.
Root cause
SAML2LogoutAPIAuthenticatorCmd#authenticate calls resp.sendRedirect(...), which commits the response. ApiServlet's LOGOUT_API cleanup — the loop that echoes the received cookies back with an empty value and Max-Age=0 (ApiServlet L333-340) — only runs after the authenticator returns. By then the 302 is already committed, so its Set-Cookie headers are silently dropped.
Fix
Clear the session cookies (JSESSIONID, sessionkey, userid, ...) on the response before sendRedirect(...) in all four redirect paths of SAML2LogoutAPIAuthenticatorCmd, mirroring the existing cookie-cleanup loop in ApiServlet. The committed 302 now instructs the browser to drop the session cookies, and the next login starts with a fresh session key.
Testing