Hi,

Here we are going to see how too secure WebService using WSEE standards of UsernameToken. The element is introduced in the WSS-SOAP Message Security documents as a way of providing a username and a element may be specified. Passwords of type wsse:PasswordText are not limited to actual passwords. wsse:PasswordText merely implies that the information held in the password is “in the clear text”, as opposed to holding a “digest” of the information

In this sample we will not use the Basic Authentication mechanism rather we will use the WSEE standards inside our webService to secure it using UsernameToken. In our previous example “Implementing UsernameToken in WebService with Basic Authentication” we used the UsernameToken in association with the BASIC Authentication so an extra header was being added in the Http response as “header=authorization=Basic a2VybWl0OnRoZWZyb2c=”.

But in this current demo we will not use the BASIC authentication rather we will use the WSEE standard UsernameToket authorization mechanism. The <security-domain> we are going to use as “java:/jaas/JBossWS” which is already defined inside the “$PROFILE/conf/login-config.xml” file as following :

  <!--
    A template configuration for the JBossWS security domain.
    This defaults to the UsersRolesLoginModule the same as other and should be
    changed to a stronger authentication mechanism as required.
  -->
  <application-policy name="JBossWS">
    <authentication>
      <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule"
        flag="required">
        <module-option name="usersProperties">props/jbossws-users.properties</module-option>
        <module-option name="rolesProperties">props/jbossws-roles.properties</module-option>
        <module-option name="unauthenticatedIdentity">anonymous</module-option>
      </login-module>
    </authentication>
  </application-policy>

Step1). Create a directory somewhere in your filesystem as “/home/userone/UserNameToken_With_WSSE” here we will write the WebService WAR and the Standalone client application.

Step2). Create a webservice application directory with name “UserNameTokenService.war” inside “/home/userone/UserNameToken_With_WSSE” .

Step3). Write the “UsernameEndpoint.java” endpoint interface inside the directory “/home/userone/UserNameToken_With_WSSE/UserNameTokenService.war/WEB-INF/classes” as following:

package test.wssecurity;
import javax.jws.WebMethod;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;

@WebService(name = "UsernameEndpoint", targetNamespace = "http://test/wssecurity")
@SOAPBinding(style = SOAPBinding.Style.RPC)
public interface UsernameEndpoint {
    @WebMethod
    @WebResult(partName = "return")
    public String getUsernameToken();

}

Step4).Write the service implementation class “UsernameBean.java” inside the directory “/home/userone/UserNameToken_With_WSSE/UserNameTokenService.war/WEB-INF/classes” as following:

package test.wssecurity;
import java.security.Principal;
import javax.annotation.Resource;
import javax.jws.WebMethod;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.xml.ws.WebServiceContext;
import org.jboss.ws.annotation.EndpointConfig;

@WebService(name = "UsernameEndpoint", serviceName = "UsernameService", targetNamespace = "http://test/wssecurity")
@EndpointConfig(configName = "Standard WSSecurity Endpoint")
@SOAPBinding(style = SOAPBinding.Style.RPC)

public class UsernameBean
{
   @WebMethod
   @WebResult(partName = "return")
   public String getUsernameToken()
   {
      System.out.println("nt[WebService- UsernameBean] getUsernameToken: " + "HelloWorld");
      return "Hello ...";
   }
}

Step4). Write the “web.xml” file as following inside directory “/home/userone/UserNameToken_With_WSSE/UserNameTokenService.war/WEB-INF”:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">
  <servlet>
    <servlet-name>UsernameService</servlet-name>
    <servlet-class>org.jboss.wsf.stack.jbws.EndpointServlet</servlet-class>
    <init-param>
      <param-name>jboss.ws.endpoint</param-name>
      <param-value>test.wssecurity.UsernameBean</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
    <servlet-name>UsernameService</servlet-name>
    <url-pattern>/*</url-pattern>
  </servlet-mapping>

  <security-constraint>
    <web-resource-collection>
      <web-resource-name>UsernameService</web-resource-name>
      <url-pattern>/*</url-pattern>
      <http-method>GET</http-method>
      <http-method>POST</http-method>
    </web-resource-collection>
 </security-constraint>

  <security-role>
    <role-name>friend</role-name>
  </security-role>
</web-app>

Step5). Write the “jboss-web.xml” file as following inside directory “/home/userone/UserNameToken_With_WSSE/UserNameTokenService.war/WEB-INF”:

<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
  <security-domain>java:/jaas/JBossWS</security-domain>
</jboss-web>

Step6). Write the “jboss-wsee-server.xml” file as following inside directory “/home/userone/UserNameToken_With_WSSE/UserNameTokenService.war/WEB-INF”:
NOTE: jboss-wsee-server.xml is the security configuration file used on the server-side. This applies to all incoming requests to a web service endpoint, as well as the outgoing responses sent by the web service endpoint.

<?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>
  <!-- Enable Authentication via Username Token. We do not care about the roles, but users should be authenticated! -->
  <authorize>
      <unchecked/>
  </authorize>
  <!-- Force presence of wsse:usernameToken header in requests -->
  <requires>
      <username/>
  </requires>
</config>
</jboss-ws-security>"

Step7). Now compile the classes present inside the “/home/userone/UserNameToken_With_WSSE/UserNameTokenService.war/WEB-INF/classes” directory as following:

$ javac -d . UsernameEndpoint.java
$ javac -d . UsernameBean.java

Step8). deploy the “UserNameTokenService.war” WebApplication directory inside “$PROFILE/deploy” directory of JBoss. As soon as you will deploy above webservice inside the JBoss profile you will be able to see following kind of messages inside your JBoss Console:

17:51:27,443 INFO  [DefaultEndpointRegistry] register: jboss.ws:context=UserNameTokenService,endpoint=UsernameService
17:51:27,561 INFO  [TomcatDeployment] deploy, ctxPath=/UserNameTokenService
17:51:28,128 INFO  [WSDLFilePublisher] WSDL published to: file:/home/userone/jboss-6/jboss-as/server/default/data/wsdl/UserNameTokenService.war/UsernameService1873434917945303908.wsdl

Now you will be able to access the WSDL from the following URL: http://localhost:8080/UserNameTokenService?wsdl
as following:

<definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://test/wssecurity" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="UsernameService" targetNamespace="http://test/wssecurity">
	<types/>
	<message name="UsernameEndpoint_getUsernameToken"/>
	<message name="UsernameEndpoint_getUsernameTokenResponse">
		<part name="return" type="xsd:string"/>
	</message>
	<portType name="UsernameEndpoint">
		<operation name="getUsernameToken">
			<input message="tns:UsernameEndpoint_getUsernameToken"/>
			<output message="tns:UsernameEndpoint_getUsernameTokenResponse"/>
		</operation>
	</portType>
	<binding name="UsernameEndpointBinding" type="tns:UsernameEndpoint">
		<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
			<operation name="getUsernameToken">
		<soap:operation soapAction=""/>
			<input>
				<soap:body namespace="http://test/wssecurity" use="literal"/>
			</input>
			<output>
				<soap:body namespace="http://test/wssecurity" use="literal"/>
			</output>
		</operation>
	</binding>
	<service name="UsernameService">
		<port binding="tns:UsernameEndpointBinding" name="UsernameEndpointPort">
			<soap:address location="http://127.0.0.1:8080/UserNameTokenService"/>
		</port>
	</service>
</definitions>

Writing Client to Access UsernameToken Secure Service

Step9). Create a directory with name “Client” inside the directory “/home/userone/UserNameToken_With_WSSE” and then use the “$JBOSS_HOME/bin/wsconsume.sh” script to generate the client artifacts:
NOTE:
before running the wsconsume.sh script make sure that you set the JAVA_HOME inside this script which should point to any JDK higher to 1.5
JAVA_HOME=/home/userone/jdk1.6.0_21

./wsconsume.sh -k -o /home/userone/UserNameToken_With_WSSE/Client -p client.wssecurity -s /home/userone/UserNameToken_With_WSSE/Client http://localhost:8080/UserNameTokenService?wsdl

./wsconsume.sh -k -o /home/userone/UserNameToken_With_WSSE/Client -p client.wssecurity -s /home/userone/UserNameToken_With_WSSE/Client http://localhost:8080/UserNameTokenService?wsdl
parsing WSDL...

[INFO] Trying to read authorization file : "/home/jsenshar/.metro/auth"...

generating code...

client/wssecurity/UsernameEndpoint.java
client/wssecurity/UsernameService.java

compiling code...

javac -d /home/userone/UserNameToken_With_WSSE/Client -classpath :/home/userone/jdk1.6.0_21/lib/tools.jar:/home/userone/jboss-6/jboss-as/client/activation.jar:/home/userone/jboss-6/jboss-as/client/getopt.jar:/home/userone/jboss-6/jboss-as/client/wstx.jar:/home/userone/jboss-6/jboss-as/client/jbossall-client.jar:/home/userone/jboss-6/jboss-as/client/log4j.jar:/home/userone/jboss-6/jboss-as/client/mail.jar:/home/userone/jboss-6/jboss-as/client/jbossws-spi.jar:/home/userone/jboss-6/jboss-as/client/jbossws-common.jar:/home/userone/jboss-6/jboss-as/client/jbossws-framework.jar:/home/userone/jboss-6/jboss-as/client/jaxws-tools.jar:/home/userone/jboss-6/jboss-as/client/jaxws-rt.jar:/home/userone/jboss-6/jboss-as/client/stax-api.jar:/home/userone/jboss-6/jboss-as/client/jaxb-api.jar:/home/userone/jboss-6/jboss-as/client/jaxb-impl.jar:/home/userone/jboss-6/jboss-as/client/jaxb-xjc.jar:/home/userone/jboss-6/jboss-as/client/streambuffer.jar:/home/userone/jboss-6/jboss-as/client/stax-ex.jar:/home/userone/jboss-6/jboss-as/client/javassist.jar:/home/userone/jboss-6/jboss-as/client/jboss-xml-binding.jar:/home/userone/jboss-6/jboss-as/client/jbossws-native-client.jar:/home/userone/jboss-6/jboss-as/client/jbossws-native-core.jar:/home/userone/jboss-6/jboss-as/client/jbossws-native-jaxws.jar:/home/userone/jboss-6/jboss-as/client/jbossws-native-jaxws-ext.jar:/home/userone/jboss-6/jboss-as/client/jbossws-native-jaxrpc.jar:/home/userone/jboss-6/jboss-as/client/jbossws-native-saaj.jar -Xbootclasspath/p:/home/userone/jboss-6/jboss-as/lib/endorsed/jbossws-native-jaxws.jar:/home/userone/jboss-6/jboss-as/lib/endorsed/jaxb-api.jar /home/userone/UserNameToken_With_WSSE/Client/client/wssecurity/UsernameEndpoint.java /home/userone/UserNameToken_With_WSSE/Client/client/wssecurity/UsernameService.java

Above command line utility will generate all the required client side artifacts inside the “/home/userone/UserNameToken_With_WSSE/Client/” directory.

Step10). Now we will need to write the WebService client program “SimpleUsernameTestCase.java” inside “/home/userone/UserNameToken_With_WSSE/Client” directory as following:

package client.wssecurity;
import java.io.File;
import java.net.URL;
import java.util.Map;
import javax.xml.namespace.QName;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.Service;
import org.jboss.ws.core.StubExt;
import org.jboss.wsf.test.JBossWSTestSetup;

public class SimpleUsernameTestCase
{
   private static UsernameEndpoint port;
    public static void main(String ar[]) throws Exception
    {
         URL wsdlURL = new File("META-INF/wsdl/UsernameService.wsdl").toURL();
         URL securityURL = new File("META-INF/jboss-wsse-client.xml").toURL();
         QName serviceName = new QName("http://test/wssecurity", "UsernameService");

         Service service = Service.create(wsdlURL, serviceName);
         port = (UsernameEndpoint)service.getPort(UsernameEndpoint.class);
         System.out.println("nt Got the Service Port: "+port);

         ((StubExt)port).setSecurityConfig(securityURL.toExternalForm());
         ((StubExt)port).setConfigName("Standard WSSecurity Client");

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

         Map<String, Object> reqContext = bp.getRequestContext();

         // As the <security-domain>java:/jaas/JBossWS</security-domain>
         // Username & passwords are defined inside "$PROFILE/conf/props/jbossws-users.properties" file.

         //  NOTE:  Make sure to uncomment the username & password in this file 
         reqContext.put(BindingProvider.USERNAME_PROPERTY, "kermit");
         reqContext.put(BindingProvider.PASSWORD_PROPERTY, "thefrog");

         String retObj = port.getUsernameToken();
         System.out.println("nt port.getUsernameToken(): "+retObj);
    }
}

Step11). Access the WSDL file from URL “http://localhost:8080/UserNameTokenService?wsdl” then save it inside the “/home/userone/UserNameToken_With_WSSE/Client/META-INF/wsdl” directory with some name as “UsernameService.wsdl”.

Step12). Create a file “jboss-wsse-client.xml” inside “/home/userone/UserNameToken_With_WSSE/Client/META-INF” as following:
NOTE: “jboss-wsse-client.xml” is the security configuration used on the client-side. This applies to all outgoing requests sent by a client, as well the response messages that are received by the client.

<?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>

Step13). Compile/Run the client program as following:

 javac -d . SimpleUsernameTestCase.java
 java -Djava.endorsed.dirs=/home/userone/jboss-6/jboss-as/lib/endorsed client.wssecurity.SimpleUsernameTestCase
log4j:WARN No appenders could be found for logger (org.jboss.ws.metadata.builder.jaxws.JAXWSWebServiceMetaDataBuilder).
log4j:WARN Please initialize the log4j system properly.

	 Got the Service Port: org.jboss.ws.core.jaxws.client.ClientImpl@67dacccc

	 port.getUsernameToken(): Hello ...

NOTE: Make sure that you use the “-Djava.endorsed.dirs=/home/userone/jboss-6/jboss-as/lib/endorsed” JAVA_OPTS while running your JBoss WebService client in order to make sure that your Client is using the JBoss WS stack.

Step15). If you want to see the SOAP Envelope along with the SOAP Headers then you can enable the following category inside the “$PROFILE/conf.jboss-log4j.xml” file by uncommenting the following section in it:

   <!-- Enable JBossWS message tracing  -->
   <category name="org.jboss.ws.core.MessageTrace">
     <priority value="TRACE"/>
   </category>

The SOAP messages will start appearing inside the “$PROFILE/log/server.log” file.

2011-10-16 18:38:58,310 TRACE [org.jboss.ws.core.MessageTrace] (http-127.0.0.1-8080-1) Incoming Request Message
<env:Envelope xmlns:env='http://schemas.xmlsoap.org/soap/envelope/'>
 <env:Header>
  <wsse:Security env:mustUnderstand='1' xmlns:ds='http://www.w3.org/2000/09/xmldsig#' 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-1318770538053-1595417149'>
    <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>
 </env:Header>
 <env:Body>
  <ns1:getUsernameToken xmlns:ns1='http://test/wssecurity'/>
 </env:Body>
</env:Envelope>
2011-10-16 18:38:58,342 INFO  [STDOUT] (http-127.0.0.1-8080-1) 
	[WebService- UsernameBean] getUsernameToken: HelloWorld 
2011-10-16 18:38:58,348 TRACE [org.jboss.ws.core.MessageTrace] (http-127.0.0.1-8080-1) Outgoing Response Message
<env:Envelope xmlns:env='http://schemas.xmlsoap.org/soap/envelope/'>
 <env:Header/>
 <env:Body>
  <ns1:getUsernameTokenResponse xmlns:ns1='http://test/wssecurity'>
   <return>Hello ...</return>
  </ns1:getUsernameTokenResponse>
 </env:Body>
</env:Envelope>

.
.
Thanks
Middleware Magic Team

If you enjoyed this post, please consider leaving a comment or subscribing to the RSS feed to have future articles delivered to your feed reader.