7 Replies Latest reply on Jul 15, 2010 12:05 PM by stuartdjames

    Implementing WS-Security Usename Token Profile Authenticatio

    dhanushgopinath

      Hi All,

      The below mentioned steps will help you implementing WS-Security Usename Token Profile on for POJO based Webservices. This example is done with JBOSS 4.2.3 AS with JBOSS Native WS 3.1.0.

      Assumptions

      1. This is a step by step example of implementing the Username Token Authentication Profile of WS Security (based on http://xml.coverpages.org/WSS-UsernameTokenProfile-20040315.pdf ) using the JBOSS WS version 3.1.0.
      2. JBOSS AS version 4.2.3 is installed.
      3. JBOSS WS 3.1.0 is deployed onto the JBOSS AS by following the instructions in the location http://www.jboss.org/file-access/default/members/jbossws/downloads/Install-jbossws-native-3.1.0.GA.txt
      4. The web service implementation is already created using the Top Down approach.
      5. JBOSS_HOME is the home directory of JBOSSAS where jboss-4.2.3.GA is unzipped.
      6. While writing the WS Service Client we assume that the client side stubs are already provided.
      7. Username and Password used in this implementation is the JBOSS default username and password (kermit=thefrog)


      Steps - Server Side


      1. Add the annotation @SecurityDomain("JBossWS") to the implementation class of web service.

      a. This requires the importing of the package org.jboss.annotation.security.SecurityDomain to the web service and hence will need the jar jboss-annotations-ejb3.jar in the classpath of your application. This jar is available in the JBOSS_HOME/client directory.

      b. This security domain (JBossWS )should be available under the application policy category in the login configuration xml file in JBOSS_HOME/server/default/conf/login-config.xml. (I guess it should be possible to add a custom security domain by adding a separate application policy configuration on to this file. But I have not tested it though. )
      2. Create a file jboss-web.xml under the WEB-INF directory of your application and add the following content to the XML file.

      <?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE jboss-web PUBLIC "-//JBoss//DTD Web Application 2.4//EN" "http://www.jboss.org/j2ee/dtd/jboss-web_4_0.dtd">
      <jboss-web>
      
       <security-domain>java:/jaas/JBossWS</security-domain>
       <context-root>/CONTEXT_ROOT_OF_YOUR_APP</context-root>
      </jboss-web>
      


      3. Copy the file standard-jaxws-endpoint-config.xml from the location JBOSS_HOME\server\default\deploy\jbossws.sar\META-INF to the META-INF directory of your application and edit it as follows.

      a. Remove all the endpoint config elements (<endpoint-config>) except the one with the config name (Standard WSSecurity Endpoint). Your standard-jaxws-endpoint-config.xml should look like this.
      <?xml version="1.0" encoding="UTF-8"?>
      <jaxws-config xmlns="urn:jboss:jaxws-config:2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:javaee="http://java.sun.com/xml/ns/javaee"
       xsi:schemaLocation="urn:jboss:jaxws-config:2.0 jaxws-config_2_0.xsd">
       <endpoint-config>
       <config-name>Standard WSSecurity Endpoint</config-name>
       <post-handler-chains>
       <javaee:handler-chain>
       <javaee:protocol-bindings>##SOAP11_HTTP ##SOAP11_HTTP_MTOM</javaee:protocol-bindings>
       <javaee:handler>
       <javaee:handler-name>WSSecurity Handler</javaee:handler-name>
       <javaee:handler-class>org.jboss.ws.extensions.security.jaxws.WSSecurityHandlerServer</javaee:handler-class>
       </javaee:handler>
       <javaee:handler>
       <javaee:handler-name>Recording Handler</javaee:handler-name>
       <javaee:handler-class>org.jboss.wsf.framework.invocation.RecordingServerHandler</javaee:handler-class>
       </javaee:handler>
       </javaee:handler-chain>
       </post-handler-chains>
       </endpoint-config>
      


      4. Create the Server side WSSE declaration (jboss-wsse-server.xml) file as per the Jboss WS 3.1.0 User guide (http://jbossws.jboss.org/mediawiki/index.php?title=WS-Security_options#POJO_Endpoint_-_Authentication_and_Authorization) in the WEB-INF directory of your application. The contents can be as given below or can be according to the above link if your want to provide role level security.
      <?xml version="1.0" encoding="UTF-8"?>
      <jboss-ws-security xmlns="http://www.jboss.com/ws-security/config"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.jboss.com/ws-security/config
      http://www.jboss.com/ws-security/schema/jboss-ws-security_1_0.xsd">
       <config>
       <authorize>
       <unchecked />
       </authorize>
       </config>
      </jboss-ws-security>
      


      5. Export the application WAR file and deploy it in JBOSS. Your application should deploy successfully. Check the log file to know more details.

      Steps - Client Side

      To test the application's Web Service Security we can write a sample WS Client. Before that we need to edit jbossws-users.properties file in the location JBOSS_HOME\ server\default\conf\props because the default JBossWS security domain look for the users configured in this file. Add users to this file in the username=password form. The steps to write the client are as given below.

      1. Create the Client side WSSE declaration (jboss-wsse-client.xml) file in a location accessible to the web service client. The contents should be as per the JBOSS WS User guide (http://jbossws.jboss.org/mediawiki/index.php?title=JAX-WS_User_Guide#Client_side_WSSE_declaration_.28jboss-wsse-client.xml.29 ). Since we are using Username Token Authentication, the contents of this file should be as follows.
      <?xml version="1.0" encoding="UTF-8"?>
      <jboss-ws-security xmlns="http://www.jboss.com/ws-security/config"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.jboss.com/ws-security/config
      http://www.jboss.com/ws-security/schema/jboss-ws-security_1_0.xsd">
       <config>
       <username/>
       </config>
      </jboss-ws-security>
      


      2. Create the WS Service Client. The important code fragment is as given below. This will require the importing of the package org.jboss.ws.core.StubExt which is available in the jar, jboss-native-core.jar. So this jar should be added to the client class path. The skeleton code is as given.
      
      String url = "YOUR_DEPLOYED_WSDL_URL";
      URL wsdlURL = new URL(url);
      URL clientSideSecurityfile = new File("jboss-wsse-client.xml").toURL();
      QName serviceName = new QName(SERVICE_TARGET_NS, SERVICE_NAME);
       Service service = Service.create(wsdlURL, serviceName);
      
      //Get the Web Service Interface PORT
       AWFUtilityServicePortType port = (AWFUtilityServicePortType) service.getPort(AWFUtilityServicePortType.class);
      
      //Set the Security Configurations
       ((StubExt) port).setSecurityConfig(clientSideSecurityfile.toExternalForm());
       ((StubExt) port).setConfigName("Standard WSSecurity Client");
      
      //Set the user name password
       Map<String, Object> reqContext = ((BindingProvider) port).getRequestContext();
       reqContext.put(BindingProvider.USERNAME_PROPERTY, "kermit");
       reqContext.put(BindingProvider.PASSWORD_PROPERTY, "thefrog");
       reqContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, url);
      
      //Make the Call
       java.lang.String partGetIDRequest = "Hello World";
       java.lang.String result = port.getID(partGetIDRequest);
       System.out.println("Result = " + result);
      


      3. So there is it we are all set. Make the call you can see the SOAP Messages when the user name and password matches

      a. In Bound

      <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:awf="http://www.test.com/WF/Framework/AWFUtilityService">
       <soapenv:Header>
       <wsse:Security soapenv:mustUnderstand="1"
       xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
       xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
       <wsse:UsernameToken wsu:Id="token-1-1236072936329-25515818">
       <wsse:Username>kermit</wsse:Username>
       <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">thefrog</wsse:Password>
       </wsse:UsernameToken>
       </wsse:Security>
       </soapenv:Header>
       <soapenv:Body>
       <awf:ID>Hi</awf:ID>
       </soapenv:Body>
      </soapenv:Envelope>
      



      b. Out Bound
      <env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
       <env:Header/>
       <env:Body>
       <ns1:IDValue xmlns:ns1="http://www.test.com/WF/Framework/AWFUtilityService">Hello World, Your ID is 1</ns1:IDValue>
       </env:Body>
      </env:Envelope>
      



      c. When the User name and Password doesn't match the following SOAP fault is thrown.
      <env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
       <env:Header/>
       <env:Body>
       <env:Fault>
       <faultcode xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">wsse:FailedAuthentication</faultcode>
       <faultstring>The security token could not be authenticated or authorized.</faultstring>
       </env:Fault>
       </env:Body>
      </env:Envelope>
      


      Hope these steps helps. If you find any issues after implementing by these steps, please post it here.

      Thanks & Regards
      Dhanush

        • 1. Re: Implementing WS-Security Usename Token Profile Authentic

          I've tried exactly these steps and the authentication is not working. I can send any combination of username/password and the server does not complains about wrong password.

          Does anyone was able to reproduce these steps? I am going crazy with this problem for 2 entire days.

          • 2. Re: Implementing WS-Security Usename Token Profile Authentic
            jayblanc

            Hi,

            I've tested the authentication using Digest Password

            1. JBoss AS 5.0.1.GA
            2. JBOSS WS native 3.0.5.GA
            3. WebService is implemented using an EJB3 Endpoint.
            4. Client is generated using standard JAXWS (with maven) but executed using jbossws-native-client
            5. JDK 6 (using -Djava.endorsed.dirs=${jboss.home}/lib/endorsed during client execution)
            6. Username Token is configured to produce a PasswordDigest and not a clear password.

            Everything works fine using the jboss-native-client

            2 problems appears also :

            1. If I'm using SOAPUI to generate a SOAP call, in the server side, password does not match. (If I'm using a configuration with no digest, the SOAPUI call works fine). I assume there is a difference between the SOAPUI generated Digest and the JBoss generated Digest but what is this difference ?

            2. The way to put UserName and Password on the client side is :

            AuthenticationService_Service service = new AuthenticationService_Service();
            AuthenticationService port = service.getAuthenticationService();
            
            ((StubExt) port).setConfigName("Standard WSSecurity Client");
            
            Map<String, Object> reqContext = ((BindingProvider)port).getRequestContext();
            reqContext.put(BindingProvider.USERNAME_PROPERTY, "kermit");
            reqContext.put(BindingProvider.PASSWORD_PROPERTY, "thefrog");
            
            String connectedUser = port.getConnectedUserIdentifier();
            logger.info("Connected user : " + connectedUser);
            assertTrue(connectedUser.equals("kermit"));
            


            Then the WSSecurityHandlerClient take this HTTP header information to generate the correct wsse SAOP header assertion, calculating a password digest of the clear password provided. The problem is that the HTTP header information is not removed and is visible clearely in the HTTP header... So the password is well encoded using a digest in the SOAP header but not in the HTTP header. Is it an issue or is there any other way to give Username/Password information to the WSSecurityHandlerClient ?

            3. Is there is some code sample that show how to use SAML instead of Usernam/Token ?

            If you capture trames using Wireshar

            • 3. Re: Implementing WS-Security Usename Token Profile Authentic
              asoldano

              The Username Token Profile is about setting username/pwd through SOAP Headers. Specify the property auth type to prevent the username from being used in the HTTP header:

              ((BindingProvider)port).getRequestContext().put(StubExt.PROPERTY_AUTH_TYPE, StubExt.PROPERTY_AUTH_TYPE_WSSE);


              SAML tokens not supported yet.

              • 4. Re: Implementing WS-Security Usename Token Profile Authentic
                pedrosena

                Hi,

                I'm trying to implement this solution, but for some reason, the authentication mecanism is not reading correctly my Soap Header.

                I saw in log:

                2009-06-01 11:09:24,265 DEBUG [org.jboss.security.auth.spi.UsersRolesLoginModule] Bad password for username=null
                2009-06-01 11:09:24,265 DEBUG [org.jboss.ejb3.security.Ejb3AuthenticationInterceptor] Authentication failure
                javax.security.auth.login.FailedLoginException: Password Incorrect/Password Required
                 at org.jboss.security.auth.spi.UsernamePasswordLoginModule.login(UsernamePasswordLoginModule.java:213)
                


                And I'm sending:

                <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.netsar.com.br/tnw/bus">
                 <soapenv:Header>
                 <wsse:Security soapenv:mustUnderstand="1"
                 xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
                 xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
                 <wsse:UsernameToken wsu:Id="token-1-1236072936329-25515818">
                 <wsse:Username>submarino</wsse:Username>
                 <wsse:Password
                Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">subm4r1n0</wsse:Password>
                 </wsse:UsernameToken>
                 </wsse:Security>
                 </soapenv:Header>
                 <soapenv:Body>
                 </soapenv:Body>
                </soapenv:Envelope>


                I'm testing it from SoapUI, the message was made manually.

                I created a new login entry on login-config.xml, its loading properly the users, but its not authenticating.

                Would appreciate some help here,

                Regards,

                PS

                • 5. Re: Implementing WS-Security Usename Token Profile Authentic
                  pedrosena

                  Hi Guys,

                  I made it work with simple Pojos, but with SLSB no way.

                  What is the trick?

                  Thanks

                  • 6. Re: Implementing WS-Security Usename Token Profile Authentic
                    jayblanc

                    Thanks alessio, setting StubExt.PROPERTY_AUTH_TYPE works fine.

                    I have also a problem with SoapUI Digest which always give me an Invalid User.

                    for exemple : using kermit/thefrog, the generated request for SoapUI is :

                    <soapenv:Envelope xmlns:hel="http://org.qualipso.factory.ws/helloworld" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
                     <soapenv:Header>
                     <wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
                     <wsse:UsernameToken wsu:Id="UsernameToken-10666036" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
                     <wsse:Username>kermit</wsse:Username>
                     <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">a4QMImbwZWY5ofgqZQK7SqkWF9M=</wsse:Password>
                     <wsse:Nonce>bEC2QeCam1oBnj+wpGBPQw==</wsse:Nonce>
                     <wsu:Created>2009-08-21T10:47:42.580Z</wsu:Created>
                     </wsse:UsernameToken>
                     </wsse:Security>
                     </soapenv:Header>
                     <soapenv:Body>
                     <hel:sayHelloWorld/>
                     </soapenv:Body>
                    </soapenv:Envelope>
                    


                    Whereas the generated request for the same credentials using the jboss endorsed JAX-WS 2.1 client is :

                    <env:Envelope xmlns:env='http://schemas.xmlsoap.org/soap/envelope/'>
                     <env:Header>
                     <wsse:Security env:mustUnderstand='1' xmlns:wsse='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd' xmlns:wsu='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd'>
                     <wsu:Timestamp wsu:Id='timestamp'>
                     <wsu:Created>2009-08-21T10:49:48.298Z</wsu:Created>
                     <wsu:Expires>2009-08-21T10:54:48.298Z</wsu:Expires>
                     </wsu:Timestamp>
                     <wsse:UsernameToken wsu:Id='token-1-1250851788299-24072801'>
                     <wsse:Username>kermit</wsse:Username>
                     <wsse:Password Type='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest'>oOxvxKABFwsUfCvOpjE+GfyrQJs=</wsse:Password>
                     <wsse:Nonce EncodingType='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary'>NXS4XKiKBe9eaJdiAjtCG23A1e3w3wZ9j38POOu4Dvg=</wsse:Nonce>
                     <wsse:Created>2009-08-21T10:49:48.289Z</wsse:Created>
                     </wsse:UsernameToken>
                     </wsse:Security>
                     </env:Header>
                     <env:Body>
                     <ns1:sayHelloWorld xmlns:ns1='http://org.qualipso.factory.ws/helloworld'></ns1:sayHelloWorld>
                     </env:Body>
                    </env:Envelope>
                    


                    I don't understand why the SoapUI client is not able to authenticate using the same configuration...

                    • 7. Re: Implementing WS-Security Usename Token Profile Authentic
                      stuartdjames

                      Hi Wilson,

                       

                      I encountered this issue with an example I'm working on.  Did you manage to resolve it?

                       

                      Regards,

                       

                      Stuart