Uploaded image for project: 'Geode'
  1. Geode
  2. GEODE-3951

ClassCastException in PULSE Logout - Default Configurations

    XMLWordPrintableJSON

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Trivial
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 1.4.0
    • Component/s: pulse
    • Labels:
      None

      Description

      The issue is 100% reproducible (latest develop branch) when using PULSE in embedded mode and the default configurations, the integrated security feature must not be enabled.

      Steps to reproduce:

      1. Start locator: gfsh start locator --name=locator1.
      2. Open Pulse: gfsh start pulse.
      3. Login into pulse application.
      4. Click on the logout button.
      

      At this stage, the following exception will be shown:

      HTTP ERROR 500
      Problem accessing /pulse/clusterLogout. Reason:
          Server Error
      
      Caused by:
      java.lang.ClassCastException: org.springframework.security.authentication.UsernamePasswordAuthenticationToken cannot be cast to org.apache.geode.tools.pulse.internal.security.GemFireAuthentication
      	at org.apache.geode.tools.pulse.internal.security.LogoutHandler.onLogoutSuccess(LogoutHandler.java:43)
      	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:111)
      	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
      	at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
      	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
      	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
      	at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
      	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
      	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
      	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
      	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
      	at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214)
      	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)
      	at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
      	at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
      	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1668)
      	at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:581)
      	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
      	at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
      	at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226)
      	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1180)
      	at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:511)
      	at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
      	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1112)
      	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
      	at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:119)
      	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134)
      	at org.eclipse.jetty.server.Server.handle(Server.java:524)
      	at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:319)
      	at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:253)
      	at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:273)
      	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:95)
      	at org.eclipse.jetty.io.SelectChannelEndPoint$2.run(SelectChannelEndPoint.java:93)
      	at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.executeProduceConsume(ExecuteProduceConsume.java:303)
      	at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceConsume(ExecuteProduceConsume.java:148)
      	at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:136)
      	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:671)
      	at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:589)
      	at java.lang.Thread.run(Thread.java:745)
      

      The problem is within the LogoutHandler class, it's always trying to get an instance of GemFireAuthentication through downcasting, but the Authentication object is an instance of GemFireAuthentication only when the Integrated Security feature is used. This means that the LogoutHandler will only be successful when the profile pulse.authentication.gemfire is active and the GemFireAuthenticationProvider is in charge. In the default case scenario, on the other hand, the Authentication object is populated by the default classes from spring-security and, thus, the exception is thrown.
      The fix should be quick and without major impact, anyway: the filter actually doesn't need to downcast to GemFireAuthentication since there's nothing extra on that object that needs to be used by the handler, it just needs to use the instance of Authentication as follows:

      public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
      	logger.debug("Invoked #LogoutHandler ...");
      
          if (authentication != null) {
          	Repository.get().logoutUser(authentication.getName());
          	logger.info("#LogoutHandler : Closing GemFireAuthentication JMX Connection...");
      	}
      
      	super.onLogoutSuccess(request, response, authentication);
      }
      

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                jjramos Juan Ramos
                Reporter:
                jjramos Juan Ramos
              • Votes:
                0 Vote for this issue
                Watchers:
                2 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: