Announcement Announcement Module
Collapse
No announcement yet.
Broken Filter Chain in WebLogic in OAuth2ClientContextFilter Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Broken Filter Chain in WebLogic in OAuth2ClientContextFilter

    When I run the Sparklr/Tonr OAuth 2 example in WebLogic 10.3.5 I get the following Exception:

    Code:
    java.lang.IndexOutOfBoundsException: Index: 2, Size: 2
        at java.util.LinkedList.entry(LinkedList.java:365)
        at java.util.LinkedList.get(LinkedList.java:315)
        at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:55)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:312)
        at org.springframework.security.oauth2.consumer.filter.OAuth2ClientContextFilter.doFilter(OAuth2ClientContextFilter.java:120)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:324)
        at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:324)
        at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:101)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:324)
        at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:324)
        at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:324)
        at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:324)
        at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:182)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:324)
        at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:324)
        at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:324)
        at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:174)
        at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
        at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
        at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)
        at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.wrapRun(WebAppServletContext.java:3715)
        at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3681)
        at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
        at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:120)
        at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2277)
        at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2183)
        at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1454)
        at weblogic.work.ExecuteThread.execute(ExecuteThread.java:209)
        at weblogic.work.ExecuteThread.run(ExecuteThread.java:178)
    The same example (only changed the ports) works fine in Jetty (jetty-hightide-7.4.5) and Tomcat (apache-tomcat-6.0.33).

    The error occurs after logging in to Tonr and Sparklr and klicking on the Authorize-Button.

    The following image shows some debugging details: Attachment

    This is the relevant code excerpt from OAuth2ClientContextFilter:

    Code:
          try {
            chain.doFilter(servletRequest, servletResponse);
          }
          catch (Exception ex) {
            OAuth2ProtectedResourceDetails resourceThatNeedsAuthorization = checkForResourceThatNeedsAuthorization(ex);
            String neededResourceId = resourceThatNeedsAuthorization.getId();
            accessTokens.remove(neededResourceId);
    
            while (!accessTokens.containsKey(neededResourceId)) {
              OAuth2AccessToken accessToken;
              try {
                accessToken = getProfileManager().obtainAccessToken(resourceThatNeedsAuthorization);
                if (accessToken == null) {
                  throw new IllegalStateException("Profile manager returned a null access token, which is illegal according to the contract.");
                }
              }
              catch (UserRedirectRequiredException e) {
                redirectUser(e, request, response);
                return;
              }
    
              accessTokens.put(neededResourceId, accessToken);
    
              try {
                //try again
                if (!response.isCommitted()) {
                  chain.doFilter(request, response);
                }
                else {
                  //dang. what do we do now?
                  throw new IllegalStateException("Unable to reprocess filter chain with needed OAuth2 resources because the response is already committed.");
                }
              }
              catch (Exception e1) {
                resourceThatNeedsAuthorization = checkForResourceThatNeedsAuthorization(e1);
                neededResourceId = resourceThatNeedsAuthorization.getId();
                accessTokens.remove(neededResourceId);
              }
            }
          }
    Since no OAuth 2 security context has been established yet, a new access token is obtained and a new attempt is made by continuing to process the filter chain, calling chain.doFilter(request, response); - this is where the IndexOutOfBoundsException results from.

    Does anybody have any idea what could be the problem here? Seems like WebLogic handles the filter chain differently from Jetty and Tomcat and is not able to call the next filter correctly, but why? Is this an error in WebLogic? Is there any other way to continue processing in OAuth2ClientContextFilter to avoid this error?

    If've been debugging through this for quite a while now without result, so any help is really appreciated. Thanks in advance.
    Attached Files
    Last edited by dante; Aug 28th, 2011, 11:43 AM.

  • #2
    Indeed, that does look like a difference in the internal implementation of the filter chain in the server. I know it works fine with tomcat and jetty, but never tried with WLS. It's not a very graceful error message is it? Unfortunately I can't think of a better way to recover, so the context filter is probably never going to work in WLS. We can probably push the Spring Security features down the stack - there is some support for gobal method security already (judging by the integration tests) so that would be an option, or (probably cleaner) we can just build it into the OAuth2RestTemplate. If you like you can raise a JIRA ticket to track what we do there.

    By the way, Spring Social already has pretty good client-side support for OAuth2, so if that's the only feature you need and you are using an external provider, it might work to switch to using that instead anyway. Eventually we will try and converge, but probably not before 1.0.
    Last edited by Dave Syer; Aug 29th, 2011, 06:08 AM. Reason: Missing word

    Comment


    • #3
      Thanks for your reply, Dave.
      Since we need both, a provider and a client, Spring Social won't help us. We adressed this to WLS support now, so let's see what they tell us (maybe this is some bug in WLS and they can provide a patch or fix this in the next release). I'll update this thread as soon as I get some significant feedback from Oracle.

      Comment


      • #4
        It seems to be an error in the WebLogic FilterChainImpl, where the next filter is looked up without checking the current position in the filter list before, which causes the IndexOutOfBoundsException:

        Code:
        public void doFilter(ServletRequest req, ServletResponse rsp)
            throws java.io.IOException, javax.servlet.ServletException
        {
            Filter f = (Filter)filters.get(index++);
            f.doFilter(req, rsp, this);
        }
        In our case the filter list consists of two filters and the current index value is 2, so the IndexOutOfBoundsException is raised. In the filter list there is a DelegatingFilterProxy containing the complete Spring SecurityFilterChain and a TailFilter, which is used by WebLogic to integrate the Spring DispatcherServlet. Both filters already have been called at this time.

        Since Oracle claims that OAuth 2 is not officially supported for WLS, I implemented the following workaround in the OAuth2ClientContextFilter now (new code in red):

        Code:
                  try {
                    //try again
                    if (!response.isCommitted()) {
                      chain.doFilter(request, response);
                    }
                    else {
                      //dang. what do we do now?
                      throw new IllegalStateException("Unable to reprocess filter chain with needed OAuth2 resources because the response is already committed.");
                    }
                  }
                  catch (IndexOutOfBoundsException weblogicException) {
                      // ignore IndexOutOfBoundsException most likely caused by buggy WebLogic FilterChainImpl
                      String redirect = request.getServletPath();
                      if (request.getQueryString() != null) {
                          redirect += "?" + request.getQueryString();
                      }
                      this.redirectStrategy.sendRedirect(request, response, redirect);
                  }
                  catch (Exception e1) {
                    resourceThatNeedsAuthorization = checkForResourceThatNeedsAuthorization(e1);
                    neededResourceId = resourceThatNeedsAuthorization.getId();
                    accessTokens.remove(neededResourceId);
                  }
        I know this is not a good solution, but until Oracle resolves the bug in the WebLogic FilterChainImpl (which they claim to do when we provide an example to reproduce this error without OAuth 2) this will have to work for us.

        Comment


        • #5
          JIRA ticket: https://jira.springsource.org/browse/SECOAUTH-114

          Comment

          Working...
          X