5 Replies Latest reply on Sep 16, 2014 9:13 AM by vinay.kumar

    PicketLink 2.1.8 in Websphere 7.0

    ramkump

      Hello Anil - We are new to picketlink and are trying to setup Picketlink (2.1.8) with Websphere 7.0. Our vision is to move towards JBoss in the near future. So we are using JBoss frameworks like Picket link and RestEasy for our SSO and Rest services needs. We configured our IDP as mentioned in this link (Standalone) -

      https://docs.jboss.org/author/display/PLINK/Standalone+Web+Applications(All+Servlet+Containers)

       

      This is what happens:

      When using the sales-standalone-1.0.3.final war file as the SP (for testing) - we tried accessing the piechart.gif image (inside sales-standalone-1.0.3.final war) in the browser, it redirects to our IDP application as expected. Once we login using the userid/password, it authenticates agianst our AD through our AASLoginHandler and returns to the IDPLoginServlet. IDPLoginServlet then redirects to IDPServlet. IDPServlet throws a NullPointerException as follows. The line number shows an AttributeManager being null as the reason for the error. That is when we created our own AttributeManager too (though the documentation says it is optional and will take the Default AttributeManager). But still we have the same NullPointerException after creating the AASAttributeManager. The error and the details of our changes are given below. Can you pls see if this has anything to do with Websphere 7. We are running everything in the Standalone mode.

       

      App server where IDP is running - Websphere 7

      Picketlink Jar file used - picketlink-core-2.1.8.Final (No other jar files are used for Picket Link)

       

      Exception

       

      [3/19/14 12:59:30:172 CDT] 00000014 servlet       E com.ibm.ws.webcontainer.servlet.ServletWrapper init SRVE0100E: Uncaught init() exception created by servlet IDPServlet in application AAS_Single_Sign_On: java.lang.RuntimeException: java.lang.NullPointerException

        at org.picketlink.identity.federation.web.servlets.IDPServlet.init(IDPServlet.java:241)

        at com.ibm.ws.webcontainer.servlet.ServletWrapper.init(ServletWrapper.java:358)

        at com.ibm.ws.webcontainer.servlet.ServletWrapperImpl.init(ServletWrapperImpl.java:169)

        at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:739)

        at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:502)

        at com.ibm.ws.webcontainer.servlet.ServletWrapperImpl.handleRequest(ServletWrapperImpl.java:179)

        at com.ibm.ws.webcontainer.webapp.WebAppRequestDispatcher.forward(WebAppRequestDispatcher.java:354)

        at org.picketlink.identity.federation.web.servlets.IDPLoginServlet.redirectToIDP(IDPLoginServlet.java:146)

        at org.picketlink.identity.federation.web.servlets.IDPLoginServlet.doPost(IDPLoginServlet.java:99)

        at javax.servlet.http.HttpServlet.service(HttpServlet.java:738)

        at javax.servlet.http.HttpServlet.service(HttpServlet.java:831)

        at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1657)

        at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:939)

        at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:502)

        at com.ibm.ws.webcontainer.servlet.ServletWrapperImpl.handleRequest(ServletWrapperImpl.java:179)

        at com.ibm.ws.webcontainer.servlet.CacheServletWrapper.handleRequest(CacheServletWrapper.java:91)

        at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:864)

        at com.ibm.ws.webcontainer.WSWebContainer.handleRequest(WSWebContainer.java:1583)

        at com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:186)

        at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:452)

        at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewRequest(HttpInboundLink.java:511)

        at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.processRequest(HttpInboundLink.java:305)

        at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.ready(HttpInboundLink.java:276)

        at com.ibm.ws.tcp.channel.impl.NewConnectionInitialReadCallback.sendToDiscriminators(NewConnectionInitialReadCallback.java:214)

        at com.ibm.ws.tcp.channel.impl.NewConnectionInitialReadCallback.complete(NewConnectionInitialReadCallback.java:113)

        at com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:165)

        at com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:217)

        at com.ibm.io.async.AsyncChannelFuture.fireCompletionActions(AsyncChannelFuture.java:161)

        at com.ibm.io.async.AsyncFuture.completed(AsyncFuture.java:138)

        at com.ibm.io.async.ResultHandler.complete(ResultHandler.java:204)

        at com.ibm.io.async.ResultHandler.runEventProcessingLoop(ResultHandler.java:775)

        at com.ibm.io.async.ResultHandler$2.run(ResultHandler.java:905)

        at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1604)

      Caused by: java.lang.NullPointerException

        at org.picketlink.identity.federation.web.servlets.IDPServlet.init(IDPServlet.java:216)

        ... 32 more

       

       

      Following are the changes done.

      1. Web.xml

      <listener>

        <listener-class>

        org.picketlink.identity.federation.web.core.IdentityServer</listener-class>

        </listener>

         <servlet>

        <servlet-name>IDPLoginServlet</servlet-name>

        <servlet-class>

        org.picketlink.identity.federation.web.servlets.IDPLoginServlet</servlet-class>

        <init-param>

        <param-name>loginClass</param-name>

        <param-value>com.xxx.xxx.idp.handler.AASIdPLoginHandler</param-value>

        </init-param>

        </servlet>

        <servlet>

        <servlet-name>IDPServlet</servlet-name>

        <servlet-class>

        org.picketlink.identity.federation.web.servlets.IDPServlet</servlet-class>

        </servlet>

        <servlet-mapping>

        <servlet-name>IDPLoginServlet</servlet-name>

        <url-pattern>/</url-pattern>

        </servlet-mapping>

        <servlet-mapping>

        <servlet-name>IDPServlet</servlet-name>

        <url-pattern>/IDPServlet</url-pattern>

        </servlet-mapping>

      2. Picketlink.xml

      <PicketLink xmlns="urn:picketlink:identity-federation:config:2.1" AttributeManager="com.xxx.xxx.idp.attribute.AASAttributeManager">

          <PicketLinkIDP xmlns="urn:picketlink:identity-federation:config:2.1">

              <IdentityURL>http://localhost:9080/aas/</IdentityURL>

              <Trust>

                  <Domains>localhost</Domains>

              </Trust>

          </PicketLinkIDP>

          <Handlers xmlns="urn:picketlink:identity-federation:handler:config:2.1">

              <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2IssuerTrustHandler" />

              <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2LogOutHandler" />

              <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2AuthenticationHandler" />

              <Handler class="com.xxx.xxx.idp.handler.AASIdPLoginHandler" />

          </Handlers>

      </PicketLink>

       

      3. AASIdPLoginHandler - authenticate() method

      public boolean authenticate(String username, Object credential)

        throws LoginException {

        String password = null;

        XmlCreator xmlCreator = new XmlCreator();

        String authXmlString = null;

        String authResponse = null;

        if (credential instanceof byte[]) {

        password = new String((byte[]) (byte[]) credential);

        } else if (credential instanceof String) {

        password = (String) credential;

        } else {

        throw picketLinkLogger.unknowCredentialType(credential.getClass()

        .getName());

        }

        try {

        authXmlString = xmlCreator.getXmlContent(prepareAuthVO(username,

        password));

        authResponse = callAASAuth(authXmlString);

        } catch (AASException e) {

        logger

        .error("AAS Exception while authenticating in IDP. Returning Failed Authentication Code..."

        + e.getMessage());

        return false;

        }

        return authResponse == null ? false

        : convertResponseMsgToBoolean(authResponse);

        }

       

      4. AASAttributeManager - getAttributes() method

      public Map<String, Object> getAttributes(Principal userPrincipal, List<String> attributeKeys) {

               Map<String,Object> attributes = new HashMap<String, Object>();

               HttpServletRequest request;

               try {

                   request = (HttpServletRequest) javax.security.jacc.PolicyContext.getContext("javax.servlet.http.HttpServletRequest");

                   HttpSession session = request.getSession();

                   Object customAttributes = session.getAttribute("ATTRIBUTES");

                   if ( customAttributes != null ) {

                       Map<String, Object> attributesMap = (Map<String, Object>) customAttributes;

                     

                       for ( String key : attributeKeys ) {

                           Object attribute = attributesMap.get(key);

                           if ( attribute != null) {

                               attributes.put(key, attribute);

                           }

                       }

                     

                   }

               } catch (PolicyContextException e) {

                   // TODO Auto-generated catch block

                   e.printStackTrace();

               }

               return attributes;

           }

        • 1. Re: PicketLink 2.1.8 in Websphere 7.0
          anil.saldhana

          Try with PicketLink v2.6.0.CR1

          There is a new servlet filter called as IDPFilter that should work on all web containers.

           

          Getting started: http://picketlink.org/gettingstarted/

           

          Here is a quickstart for that:

          jboss-picketlink-quickstarts/picketlink-federation-saml-idp-servlet-filter at master · jboss-developer/jboss-picketlink-…

          • 2. Re: PicketLink 2.1.8 in Websphere 7.0
            ramkump

            Hello Anil,


            With this WEB.XML AND picketlink.xml, we were able to go past all the issues in Websphere 7.0 till the end where SAML response is being written out.

            At the end, when our Websphere web application is writing back SAML Response content to the  browser as mentioned in step 3 (Picketlink Code), we are getting a WriteBeyondContentLengthException from the Websphere web container as mentioned in step 4 (given below). The error happens at outputStream.println(str) in the  picketlink framework code (step 3) given below.  We raised the issue with IBM Websphere Prod Dev Team and after a month's research they have come up with their response (mentioned in step 5 below). It looks like in the picketlink code, after the  content-length was set to 1288 and the write of 1288 data, there seems to be another write of a whitespace character (either a \n or space). This is the cause of the 'WriteBeyondContentLengthException'.


            Do you think we can make this (last step) work in Websphere with some minor changes to the Picketlink framework. If not, we will have to move to some other framework. Pls let me know.

             

             

            Websphere App Server - 7.0.0.19 

            Red Hat Picketlink - 2.1.8.Final

             

            1. WEB.XML

            <listener>

              <listener-class>

              org.picketlink.identity.federation.web.core.IdentityServer</listener-class>

              </listener>

               <servlet>

              <servlet-name>IDPLoginServlet</servlet-name>

              <servlet-class>

              org.picketlink.identity.federation.web.servlets.IDPLoginServlet</servlet-class>

              <init-param>

              <param-name>loginClass</param-name>

              <param-value>com.xxx.xxx.idp.handler.AASIdPLoginHandler</param-value>

              </init-param>

              </servlet>

              <servlet>

              <servlet-name>IDPServlet</servlet-name>

              <servlet-class>

              org.picketlink.identity.federation.web.servlets.IDPServlet</servlet-class>

              </servlet>

              <servlet-mapping>

              <servlet-name>IDPLoginServlet</servlet-name>

              <url-pattern>/</url-pattern>

              </servlet-mapping>

              <servlet-mapping>

              <servlet-name>IDPServlet</servlet-name>

              <url-pattern>/IDPServlet</url-pattern>

              </servlet-mapping>

             

            2. PICKETLINK>XML

            <PicketLink xmlns="urn:picketlink:identity-federation:config:2.1" >

                <PicketLinkIDP xmlns="urn:picketlink:identity-federation:config:2.1" AttributeManager="com.xxx.xxx.idp.attribute.AASAttributeManager">

                    <IdentityURL>http://localhost:9080/xxx/</IdentityURL>

                    <Trust>

                        <Domains>localhost</Domains>

                    </Trust>

                </PicketLinkIDP>

                    <PicketLinkSTS xmlns="urn:picketlink:identity-federation:config:1.0" TokenTimeout="1000" ClockSkew="1000">

                    <TokenProviders>

                        <TokenProvider ProviderClass="org.picketlink.identity.federation.core.saml.v2.providers.SAML20AssertionTokenProvider"

                            TokenType="urn:oasis:names:tc:SAML:2.0:assertion" TokenElement="Assertion"

                            TokenElementNS="urn:oasis:names:tc:SAML:2.0:assertion" />

                    </TokenProviders>

                </PicketLinkSTS>

              <Handlers xmlns="urn:picketlink:identity-federation:handler:config:2.1">

              <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2IssuerTrustHandler"/>

              <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2LogOutHandler"/>

              <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2AuthenticationHandler"/>

              </Handlers>

            </PicketLink>

             

             

              

            3. PICKETLINK CODE  (where exception is thrown)

            public static void sendPost(DestinationInfoHolder holder, 

            HttpServletResponse response, boolean request) throws IOException { 

              String key = request ? GeneralConstants.SAML_REQUEST_KEY : 

            GeneralConstants.SAML_RESPONSE_KEY;    

              String relayState = holder.getRelayState(); 

              String destination = holder.getDestination(); 

              String samlMessage = holder.getSamlMessage();    

              if (destination == null) { 

              throw logger.nullValueError("Destination is null"); 

              }    

              response.setContentType("text/html"); 

              common(holder.getDestination(), response); 

              StringBuilder builder = new StringBuilder();    

              builder.append("<HTML>"); 

              builder.append("<HEAD>");    

              if (request) 

              builder.append("<TITLE>HTTP Post Binding (Request) 

            </TITLE>"); 

              else 

              builder.append("<TITLE>HTTP Post Binding Response (Response)

            </TITLE>");    

              builder.append("</HEAD>"); 

              builder.append("<BODY Onload=\"document.forms[0].submit()\">");   

              builder.append("<FORM METHOD=\"POST\" ACTION=\"" + destination 

            + "\">"); 

              builder.append("<INPUT TYPE=\"HIDDEN\" NAME=\"" + key + "\"" + 

            " VALUE=\"" + samlMessage + "\"/>"); 

              

              if (isNotNull(relayState)) { 

              builder.append("<INPUT TYPE=\"HIDDEN\" NAME=\"RelayState\" 

            " + "VALUE=\"" + relayState + "\"/>"); 

              }    

              builder.append("<NOSCRIPT>"); 

              builder.append("<P>JavaScript is disabled. We strongly 

            recommend to enable it. Click the button below to continue.</P>"); 

              builder.append("<INPUT TYPE=\"SUBMIT\" VALUE=\"CONTINUE\" />");

              builder.append("</NOSCRIPT>");    

              builder.append("</FORM></BODY></HTML>");    

              String str = builder.toString();    

              logger.trace(str);    

              ServletOutputStream outputStream = response.getOutputStream();    

              // we need to re-configure the content length, because Tomcat 

            may have written some content. 

              response.resetBuffer(); 

              response.setContentLength(str.length());    

              outputStream.println(str); 

              outputStream.close(); 

              } 

             

            4. EXCEPTION IN WEBSPHERE

            00000017 servlet       E com.ibm.ws.webcontainer.servlet.ServletWrapper service SRVE0068E: Uncaught exception created in one of the service methods of the servlet IDPServlet in application XX_AAS_Single_Sign_On. Exception created : com.ibm.ws.webcontainer.srt.WriteBeyondContentLengthException

              at com.ibm.wsspi.webcontainer.util.BufferedServletOutputStream.print(BufferedServletOutputStream.java:487)

              at javax.servlet.ServletOutputStream.println(ServletOutputStream.java:235)

              at javax.servlet.ServletOutputStream.println(ServletOutputStream.java:253)

              at org.picketlink.identity.federation.web.util.PostBindingUtil.sendPost(PostBindingUtil.java:143)

              at org.picketlink.identity.federation.web.util.IDPWebRequestUtil.send(IDPWebRequestUtil.java:234)

              at org.picketlink.identity.federation.web.servlets.IDPServlet.doPost(IDPServlet.java:543)

             

            5. IBM SERVER TEAM's RESPONSE

            The IBM Websphere Product Dev team researched for a month on this and mentioned that there is a '\n' (new feed or return character) which is being written after the actual HTML content and that is making the container to throw this exception and is not a bug in the server code. For my question on how it is working in JBoss and Tomcat, there response is that those servers may choose to ignore the  additional data which is exceeding the specified content-length. Given below is the IBM Websphere Product Dev team response.

             

            "After the  content-length was set to 1288 and the write of 1288 data, there seems 

            to be another write of a whitespace character (either a \n or space). 

            See the gap between the second print print --> and the flush (below):    

              

            [5/1/14 15:09:39:029 CDT] 0000001d HttpBaseMessa 3 

            setContentLength(b,b): false 1288 

            [5/1/14 15:09:39:029 CDT] 0000001d BNFHeadersImp 1 Adding header 

            [Content-Length] with value [1288] 

            [5/1/14 15:09:39:029 CDT] 0000001d srt < 

            com.ibm.ws.webcontainer.srt.SRTServletResponse setIntHeader RETURN 

            [5/1/14 15:09:39:029 CDT] 0000001d srt < 

            com.ibm.ws.webcontainer.srt.SRTServletResponse setContentLength RETURN 

            [5/1/14 15:09:39:045 CDT] 0000001d util 1 

            com.ibm.wsspi.webcontainer.util.BufferedServletOutputStream print print

            --> <HTML><HEAD><TITLE>HTTP Post Binding (Request)</TITLE></HEAD><BODY 

            Onload="document.forms[0].submit()"><FORM METHOD="POST" 

            ACTION="http://localhost:8080/idp-standalone/"><INPUT TYPE="HIDDEN" 

            NAME="SAMLRequest" 

            VALUE="PHNhbWxwOkF1dGhuUmVxdWVzdCB4bWxuczpzYW1scD0idXJuOm9hc2lzOm5hbWVzO

            nRjOlNBTUw6Mi4wOnByb3RvY29sIiB4bWxucz0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6M

            i4wOmFzc2VydGlvbiIgSUQ9IklEX2VjYWNiNDYwLTk0YmQtNDIyYS04Y2E0LWUyMTI4NWNjM

            TRlZSIgVmVyc2lvbj0iMi4wIiBJc3N1ZUluc3RhbnQ9IjIwMTQtMDUtMDFUMjA6MDk6MzguO

            TUxWiIgRGVzdGluYXRpb249Imh0dHA6Ly9sb2NhbGhvc3Q6ODA4MC9pZHAtc3RhbmRhbG9uZ

            S8iIEFzc2VydGlvbkNvbnN1bWVyU2VydmljZVVSTD0iaHR0cDovL2xvY2FsaG9zdDo4MDgwL

            3NhbGVzLXN0YW5kYWxvbmUvIiBQcm90b2NvbEJpbmRpbmc9InVybjpvYXNpczpuYW1lczp0Y

            zpTQU1MOjIuMDpiaW5kaW5nczpIVFRQLVBPU1QiPjxzYW1sOklzc3VlciB4bWxuczpzYW1sP

            SJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIj5odHRwOi8vbG9jYWxob

            3N0OjgwODAvc2FsZXMtc3RhbmRhbG9uZS88L3NhbWw6SXNzdWVyPjxzYW1scDpOYW1lSURQb

            2xpY3kgRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6bmFtZWlkLWZvcm1hd

            Dp0cmFuc2llbnQiIEFsbG93Q3JlYXRlPSJ0cnVlIj48L3NhbWxwOk5hbWVJRFBvbGljeT48L

            3NhbWxwOkF1dGhuUmVxdWVzdD4="/><NOSCRIPT><P>JavaScript is disabled. We 

            strongly recommend to enable it. Click the button below to 

            continue.</P><INPUT TYPE="SUBMIT" VALUE="CONTINUE" 

            /></NOSCRIPT></FORM></BODY></HTML> 

            [5/1/14 15:09:39:045 CDT] 0000001d srt 1 

            com.ibm.ws.webcontainer.srt.SRTServletResponse alertFirstWrite 

            _outWriter: --> null 

            [5/1/14 15:09:39:045 CDT] 0000001d util 1 

            com.ibm.wsspi.webcontainer.util.BufferedServletOutputStream print print

            --> 

              

            [5/1/14 15:09:39:045 CDT] 0000001d util 1 

            com.ibm.wsspi.webcontainer.util.BufferedServletOutputStream flush flush

            [5/1/14 15:09:39:045 CDT] 0000001d util 1 

            com.ibm.wsspi.webcontainer.util.BufferedServletOutputStream flushBytes 

            flushBytes  

              

            If it is indeed a write of a whitespace, this may be the cause of the 

            exception since the data is now bigger than the set 1288."

            • 3. Re: PicketLink 2.1.8 in Websphere 7.0
              anil.saldhana

              Use the IDPFilter I mentioned in my last post.  Configure it in your web.xml and you should be good to go.  You can use the WebSphere web container authentication at the IDP.

               

              Download the latest PicketLink (v2.6.0.CR2) from http://www.picketlink.org

              • 4. Re: PicketLink 2.1.8 in Websphere 7.0
                ramkump

                Thanks Anil! Will try this out and will post the result here.

                • 5. Re: PicketLink 2.1.8 in Websphere 7.0
                  vinay.kumar

                  Hello Ramesh,

                   

                  I know replying to an old thread may not be the best idea, but I would like to know if you had any luck in running Picketlink successfully on WebSphere? If yes, please let me know how you did configure / integrate with your application. I'm stomped..

                   

                  Thanks,

                  Vinay