Details
-
Bug
-
Resolution: Won't Fix
-
Low
-
None
-
4.1
-
None
Description
The Siteminder authenticator is broken with Confluence 4.1 and later due to a change to Confluence's internal authentication process.
The actual error message is really unobvious:
2012-09-06 14:20:02,188 ERROR [http-8080-1] [[Catalina].[localhost].[/wiki].[action]] log Servlet.service() for servlet action threw exception java.lang.ClassCastException: com.atlassian.confluence.user.SessionSafePrincipal cannot be cast to com.atlassian.user.User at com.atlassian.confluence.user.AuthenticatedUserThreadLocal.getUser(AuthenticatedUserThreadLocal.java:25) at com.atlassian.confluence.util.UserThreadLocalFilter.doFilter(UserThreadLocalFilter.java:36) ...
It looks like all the custom authenticators expect the Principal in the session to be a com.atlassian.user.User, and return that from the Authenticator.getUser() method. If the session-bound Principal isn't a User object, the authentication still succeeds, and the failure appears in a call to AuthenticatedUserThreadLocal later in the request.
Here's the relevant code snippet which appears in all our custom authenticators:
public class SiteMinderAuthenticator extends ConfluenceAuthenticator { // ... public Principal getUser(final HttpServletRequest request, HttpServletResponse response) { // ... final HttpSession existingSession = request.getSession(false); if (existingSession != null && existingSession.getAttribute(DefaultAuthenticator.LOGGED_IN_KEY) != null) { Principal loggedInUser = (Principal) existingSession.getAttribute(DefaultAuthenticator.LOGGED_IN_KEY); log.debug("{} is already logged in.", loggedInUser.getName()); return loggedInUser; } // ... } // ... }
The simple fix is to use getUserFromSession() in the authenticator, instead of getting the principal and returning it from getUser() directly, although I'm not sure yet whether this is backwards compatible.
However, since Confluence relies on the authenticator returning a User object not just a regular Principal from getUser(), it would also be helpful to enforce at authentication time that the authenticator is returning a User object. Then this problem would have a much more obvious error message, not an obscure failure in AuthenticatorUserThreadLocal somewhere later in the request.