-
Bug
-
Resolution: Fixed
-
Medium
-
5.0
The constructor signature of com.atlassian.confluence.event.events.security.LoginEvent changed between Confluence 4.3.x and 5.0 - an additional String parameter was added to the constructor.
From this:
public LoginEvent(Object src, String username, String sessionId, String remoteHost, String remoteIP)
To this:
public LoginEvent(Object src, String username, String sessionId, String remoteHost, String remoteIP, String loginSource)
This breaks binary compatibility for any custom Seraph authenticator that manually constructs and fires an instance of LoginEvent. This is the expected behaviour for a well-written custom authenticator as, otherwise, a user's login history is not properly recorded in the Confluence database.
The following exception is thrown at runtime:
java.lang.IllegalAccessError: tried to access method com.atlassian.confluence.event.events.security.SecurityEvent.<init>(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V from class com.pixelpark.seraph.SSOAuthenticator at com.pixelpark.seraph.SSOAuthenticator.getUser(SSOAuthenticator.java:130) at com.atlassian.seraph.auth.AbstractAuthenticator.getUser(AbstractAuthenticator.java:45) at com.atlassian.seraph.filter.BaseLoginFilter$SecurityHttpRequestWrapper.getUserPrincipal(BaseLoginFilter.java:236) at com.atlassian.seraph.filter.BaseLoginFilter$SecurityHttpRequestWrapper.getRemoteUser(BaseLoginFilter.java:224) at com.pixelpark.seraph.SSOAuthenticator.getRemoteUsername(SSOAuthenticator.java:51) at com.pixelpark.seraph.SSOAuthenticator.getUser(SSOAuthenticator.java:105) at com.atlassian.seraph.filter.SecurityFilter.doFilter(SecurityFilter.java:125) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at com.atlassian.security.auth.trustedapps.filter.TrustedApplicationsFilter.doFilter(TrustedApplicationsFilter.java:98) at com.atlassian.confluence.util.AbstractBootstrapHotSwappingFilter.doFilter(AbstractBootstrapHotSwappingFilter.java:30) at com.atlassian.core.filters.AbstractHttpFilter.doFilter(AbstractHttpFilter.java:31) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at com.atlassian.seraph.filter.BaseLoginFilter.doFilter(BaseLoginFilter.java:150) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at com.atlassian.plugin.servlet.filter.IteratingFilterChain.doFilter(IteratingFilterChain.java:46) at com.atlassian.plugin.servlet.filter.ServletFilterModuleContainerFilter.doFilter(ServletFilterModuleContainerFilter.java:77) at com.atlassian.plugin.servlet.filter.ServletFilterModuleContainerFilter.doFilter(ServletFilterModuleContainerFilter.java:63) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at com.atlassian.confluence.util.ClusterHeaderFilter.doFilter(ClusterHeaderFilter.java:37) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at com.atlassian.gzipfilter.GzipFilter.doFilterInternal(GzipFilter.java:74) at com.atlassian.gzipfilter.GzipFilter.doFilter(GzipFilter.java:51) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at com.atlassian.core.filters.cache.AbstractCachingFilter.doFilter(AbstractCachingFilter.java:33) at com.atlassian.core.filters.AbstractHttpFilter.doFilter(AbstractHttpFilter.java:31) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at com.atlassian.plugin.servlet.filter.IteratingFilterChain.doFilter(IteratingFilterChain.java:46) at com.atlassian.plugin.servlet.filter.ServletFilterModuleContainerFilter.doFilter(ServletFilterModuleContainerFilter.java:77) at com.atlassian.plugin.servlet.filter.ServletFilterModuleContainerFilter.doFilter(ServletFilterModuleContainerFilter.java:63) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
This has some pretty crappy compatibility consequences for custom authenticators. Currently it is possible to write a custom authenticator that works on any version of Confluence from 3.5.x all the way to 4.3.x. The backwards compatibility on any earlier version than 3.5 was broken by embedded crowd (which is fair enough, it was a big change). To break compatibility for something as minor as the addition of an optional constructor parameter seems a bit cruel.
The original constructor to LoginEvent should be restored and annotated with a Deprecated flag. This will allow developers to continue to write one custom authenticator jar that works with a wide range of Confluence versions.