4 Replies Latest reply on Nov 16, 2010 10:19 AM by jeanluc

    Accessing a server by IP/localhost with Internet Explorer bypasses PicketLink

    jeanluc

      We have the following problem.

       

      Environment: JBoss 5.1, Seam 2.2.1.CR2, PL 1.0.4 (configured to authenticate against an Active Directory), OpenAM (Snapshot Build 9.5.1_RC2)

       

      Until recently, we used the JPA identity store (i.e. let Seam authenticate users and fetch their roles from db). We now delegate to an OpenAM server for authentication and we let Seam retrieve the roles as before.

       

      That works fine as long as I access the application by its fully qualified name.

       

      If I try the IP (developers running the code locally also report this when using "localhost") with Internet Explorer however, PicketLink doesn't kick in and the users can login with database credentials. If I do the same with Firefox or Chrome, a loop of redirections occurs between Seam and the SSO server (the loop is stopped by the server).

       

      I suspect this is caused by PicketLink not matching the URL with a defined Service Provider.

       

      Any suggestions are very appreciated.

       

       

       

      Relevant part from components.xml:

       

      <import>org.picketlink.identity.seam.federation</import>
          <security:identity />
          <security:jpa-identity-store user-class="org.myapp.model.security.User"
                                       role-class="org.myapp.model.security.Role"/>
          <!-- JBID IDP -->
          <component name="urlToRedirectToAfterLogin" class="java.lang.String" />

       

      external-authentication-config.xml

       

      <?xml version="1.0" encoding="UTF-8"?>
      <ExternalAuthenticationConfig xmlns="urn:picketlink:identity-federation:seam:config:1.0" xmlns:tns="urn:picketlink:identity-federation:seam:config:1.0">

       

          <ServiceProvider
                  protocol="http"
                  hostname="${web.server.hostname}"
                  port="${web.server.port}"
                  unsolicitedAuthenticationUrl="${application.url}"
                  loggedOutUrl="${application.url}"
                  failedAuthenticationUrl="${application.url}/FailedAuthenticationPage.seam"
                  internalAuthenticationMethod="#{authenticator.internalAuthenticate}">

       


              <SamlConfig
                      serviceProviderEntityId="${application.url}"
                      defaultIdentityProvider="${sso.server.url}"
                      keyStoreUrl="${sso.keystore.url}"
                      keyStorePass="${sso.keystore.password}"
                      signingKeyAlias="${sso.signingkey.alias}"
                      signingKeyPass="${sso.signingkey.password}">
                  <SamlIdentityProvider entityId="${sso.server.url}"/>
              </SamlConfig>
          </ServiceProvider>
      </ExternalAuthenticationConfig>

        • 1. Re: Accessing a server by IP/localhost with Internet Explorer bypasses PicketLink
          marcelkolsteren

          The behaviour of PicketLink Seam when the hostname doesn't match any hostname of a configured service provider is unspecified until so far. I tried the seam-sp test application (from the PicketLink distribution) to see what happens in that situation. The behaviour that I observed when accessing a page that has login-required is that an exception occurs during execution of the PagesSupportingExternalAuthentication component (because the service provider factory in the Configuration component returns null). The user is not redirected, and the exception is swallowed by Seam. The result is that the user will just see the requested page, although she is not logged in. That's undesired behaviour. If the login-required would be the only security restriction on the page (like in the sample application), it's even a security leak. So I created a major JIRA issue for that. I think that the desired behaviour in this case would be to redirect the user to the login view that is specified in pages.xml. What do you think?

           

          Maybe this already gave you some hints about what is going on in your environment. At this time, I cannot explain the behaviour that you see in your test and development environments. I would need some more information:


          • What's in your pages.xml (at least I would need to know what is the login-view-id, and the configuration of the page that the user tries to access in the sample scenario).
          • The value of ${web.server.hostname} in your development and test environment. Maybe it is localhost in development?
          • What your login page looks like. Is it just a page for locally logging in? Any redirections taking place there?
          • Do developers remove the defaultIdentityProvider attribute from external-authentication-config.xml when running locally? That's what I suggested to you in an earlier forum thread in order to be able to login locally in a development environment.

           

          In particular, two things that happen in your environment are quite strange:

           

          • The difference between IE and Chrome/Firefox.
          • The fact that it is possible (using Firefox/Chrome) to trigger a redirect to the SSO server, although the hostname doesn't match with any configured service provider.
          1 of 1 people found this helpful
          • 2. Re: Accessing a server by IP/localhost with Internet Explorer bypasses PicketLink
            jeanluc

            Hi Marcel,

             

            Sorry for the delay, things have been pretty hectic.

             

            I got back to work on this problem and, rather strangely, it's gone. It was there until Friday. When I built the app again on Monday morning, Maven fetched a number of updated libraries and the behaviour was gone. I've seen it on 4 machines with my own eyes so I swear it happened but now I cannot reproduce it anymore.

             

            However, there's still a problem left: when I accees the server by any other hostname than the one configured as a service provider (say, by IP or by a name I made up in hosts), then an infinite loop is triggered.

             

            What's happening is that the injection of @In private ServiceProvider serviceProvider in ExternalAuthenticator fails so a method (which happens to be a setter now) fails as well (BTW, you can annotate the accessors with @BypassInterceptors to avoid injecting those components which are not actually used by the methods, it saves a little time). The loop is caused because the server tries to display the error page which is also protected (this is a financial app so no pages except the login are public) which causes the PicketLink error again and so on. It's a pretty nifty denial of service attack in fact, the server logs fill up quickly because of the stack traces.

             

            Any advice about how to control this behaviour?

             

            Thanks again for the help

             

            org.jboss.seam.RequiredException: @In attribute requires non-null value: org.picketlink.identity.seam.federation.externalAuthenticator.serviceProvider

                    at org.jboss.seam.Component.getValueToInject(Component.java:2361)

                    at org.jboss.seam.Component.injectAttributes(Component.java:1739)

                    at org.jboss.seam.Component.inject(Component.java:1557)

                    at org.jboss.seam.core.BijectionInterceptor.aroundInvoke(BijectionInterceptor.java:61)

                    at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)

                    at org.jboss.seam.core.MethodContextInterceptor.aroundInvoke(MethodContextInterceptor.java:44)

                    at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)

                    at org.jboss.seam.core.SynchronizationInterceptor.aroundInvoke(SynchronizationInterceptor.java:32)

                    at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)

                    at org.jboss.seam.intercept.RootInterceptor.invoke(RootInterceptor.java:107)

                    at org.jboss.seam.intercept.JavaBeanInterceptor.interceptInvocation(JavaBeanInterceptor.java:185)

                    at org.jboss.seam.intercept.JavaBeanInterceptor.invoke(JavaBeanInterceptor.java:103)

                    at org.picketlink.identity.seam.federation.ExternalAuthenticator_$$_javassist_seam_10.setReturnUrl(ExternalAuthenticator_$$_javassist_seam_10.java)

                    at org.picketlink.identity.seam.federation.PagesSupportingExternalAuthentication.redirectToLoginView(PagesSupportingExternalAuthentication.java:74)

                    at org.jboss.seam.navigation.Pages.postRestore(Pages.java:414)

                    at org.jboss.seam.jsf.SeamPhaseListener.postRestorePage(SeamPhaseListener.java:545)

                    at org.jboss.seam.jsf.SeamPhaseListener.afterRestoreView(SeamPhaseListener.java:394)

                    at org.jboss.seam.jsf.SeamPhaseListener.afterServletPhase(SeamPhaseListener.java:230)

                    at org.jboss.seam.jsf.SeamPhaseListener.afterPhase(SeamPhaseListener.java:196)

                    at com.sun.faces.lifecycle.Phase.handleAfterPhase(Phase.java:175)

                    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:114)

                    at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:103)

                    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)

                    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:265)

                    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)

                    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

                    at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:530)

                    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)

                    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

                    at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:83)

                    at org.picketlink.identity.seam.federation.ExternalAuthenticationFilter.doFilter(ExternalAuthenticationFilter.java:134)

                    at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)

                    at org.jboss.seam.web.IdentityFilter.doFilter(IdentityFilter.java:40)

                    at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)

                    at org.jboss.seam.web.MultipartFilter.doFilter(MultipartFilter.java:90)

                    at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)

                    at org.jboss.seam.web.ExceptionFilter.doFilter(ExceptionFilter.java:64)

                    at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)

                    at org.jboss.seam.web.RedirectFilter.doFilter(RedirectFilter.java:45)

                    at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)

                    at org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:206)

                    at org.ajax4jsf.webapp.BaseFilter.handleRequest(BaseFilter.java:290)

                    at org.ajax4jsf.webapp.BaseFilter.processUploadsAndHandleRequest(BaseFilter.java:388)

                    at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:515)

                    at org.jboss.seam.web.Ajax4jsfFilter.doFilter(Ajax4jsfFilter.java:56)

                    at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)

                    at org.jboss.seam.web.LoggingFilter.doFilter(LoggingFilter.java:60)

                    at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)

                    at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)

                    at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)

                    at org.jboss.seam.servlet.SeamFilter.doFilter(SeamFilter.java:158)

                    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)

                    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

                    at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)

                    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)

                    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

                    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:235)

                    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)

                    at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:190)

                    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:433)

                    at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:92)

                    at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.process(SecurityContextEstablishmentValve.java:126)

                    at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.invoke(SecurityContextEstablishmentValve.java:70)

                    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)

                    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)

                    at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:158)

                    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:567)

                    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)

                    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:330)

                    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:829)

                    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:598)

                    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)

                    at java.lang.Thread.run(Thread.java:619)

            • 3. Re: Accessing a server by IP/localhost with Internet Explorer bypasses PicketLink
              marcelkolsteren

              Hi Jean-Luc,

               

              Are you sure the exception occurred in ExternalAuthenticator? When I was reproducing your original problem with the seam-sp sample application, I saw an exception occurring in PagesSupportingExternalAuthentication (serviceProvider is null). That exception was swallowed by Seam. However, when I add the following fragment to the pages.xml, the exception is not swallowed any more, and I can reproduce your situation:

               

              <exception class="java.lang.Exception" log="true">

                <redirect view-id="/ErrorPage.xhtml">

                  <message severity="error">An error occurred.</message>

                </redirect>

              </exception>

               

              This problem won't happen any more as soon as JIRA PLFED-118 is resolved. But you have a more general problem regarding the error handling, and there could be other situations when for some reason the login process is failing. My advice is as follows. You've secured the error page so that the error message (which could contain some confidential information) requires being logged in. You could fix the endless loop problem by removing the "login-required" from the page descriptor, and then doing something like this in the xhtml:

               

              <c:choose>

              <c:when test="#{identity.loggedIn}">

                 ... show some detailed error information here ...

              </c:when>

              </c:otherwise>

                 ... only show a very generic error message ("a technical error occurred") here ...

              </c:choose>

               

              In that way, you prevent the authentication loop, without sacrificing the confidentiality of detailed error messages.

              • 4. Re: Accessing a server by IP/localhost with Internet Explorer bypasses PicketLink
                jeanluc

                Hi Marcel,

                 

                Thanks for the follow-up. We do have a generic error page which doesn't display technical details (the requirement for it being secure stems from a compliance policy); the tip with the conditional is useful.