Tuesday, January 4, 2011

Spring-WS 2: WS-Security Using WSS4J

In this tutorial we will explore how to add WS-Security using WSS4J in an existing Spring-WS application. We will secure our web service using Spring's Wss4jSecurityInterceptor. In the client-side, we will use soapUI to verify the results.

What is WS-Security?
WS-Security (Web Services Security, short WSS) is a flexible and feature-rich extension to SOAP to apply security to web services. It is a member of the WS-* family of web service specifications and was published by OASIS.

The protocol specifies how integrity and confidentiality can be enforced on messages and allows the communication of various security token formats, such as SAML, Kerberos, and X.509. Its main focus is the use of XML Signature and XML Encryption to provide end-to-end security.

WS-Security describes three main mechanisms:
  • How to sign SOAP messages to assure integrity. Signed messages provide also non-repudiation.
  • How to encrypt SOAP messages to assure confidentiality.
  • How to attach security tokens.
Source: Wikipedia (http://en.wikipedia.org/wiki/WS-Security
)

To view the official specification please visit OASIS Web Services Security (WSS) TC

What is WSS4J?
Apache WSS4J is an implementation of the OASIS Web Services Security (WS-Security) from OASIS Web Services Security TC. WSS4J is primarily a Java library that can be used to sign and verify SOAP Messages with WS-Security information. WSS4J will use Apache Axis and Apache XML-Security projects and will be interoperable with JAX-RPC based server/clients and .NET server/clients.

WSS4J implements:
- Web Services Security: SOAP Message Security 1.1
- Username Token Profile 1.1
- X.509 Certificate Token Profile 1.1

Source: Apache WSS4J (http://ws.apache.org/wss4j/)

What is Wss4jSecurityInterceptor?
The Wss4jSecurityInterceptor is an EndpointInterceptor that is based on Apache's WSS4J.

Source: Spring WS 2.0 Reference
We will not recreate the whole web service. We'll just focus on what needs to be added to enable an WSS4J-based security.

Open the spring-ws.xml file and replace it with the following configuration:

spring-ws.xml

Actually we don't need to replace everything. What we did is add a Wss4jSecurityInterceptor inside the sws-interceptors element:

The validationActions is a list of actions composed of space-separated strings. When a client sends a message, the validationActions will be executed. In our example, it will check if there's a Timestamp element in the incoming message. It also checks if the Timestamp hasn't expired. It also checks if there's a UsernameToken present in the message.

The securementActions is a list of actions composed of space-separated strings. These actions will be performed when the web service is replying back to the client. In this example, the web service is returning a Timestamp element and UsernameToken. Both can be customized. timestampPrecisionInMilliseconds declares the precision of the time. The securementUsername and securementPassword declares the actual username and password values, as well as the type of password PasswordText. The outgoing message also include a Nonce and the date Created.

To authenticate the credentials from the incoming message, we declared a bean callbackHandler that references a SimplePasswordValidationCallbackHandler bean:

Watch the package name! There's also an equivalent SimplePasswordValidationCallbackHandler for XWSS! Unlike the XWSS implementation, we don't need to declare an extra securityPolicy.xml here. Everything is contained within this configuration.

What is soapUI?
soapUI is the world's leading Web Service Testware. With over 2 million downloads, it's the de facto tool for SOA testing.

Source: http://www.eviware.com/soapUI/soapui-products-overview.html

It's also mentioned as one of the tools for testing Spring-WS applications:
These tools can help you test your Web service applications.

- soapui is a desktop application for inspecting, invoking and testing (functional and load) of web services over HTTP.
- the WS-I testing tools, which make sure your Web service is interoperable.
- Axis Tcpmon is a monitoring tool which allows you to see the XML as it is sent and received across the wire.

Source: http://static.springsource.org/spring-ws/sites/2.0/resources.html

Follow the steps below to perform a test:
1. Open soapUI.

2. Create a new soapUI project:

3. Open the project and create a new request:

4. On the right side window, you should see a request template. To add a WSS UsernameToken or Timestamp, right-click on the request and select Add WSS UsernameToken or Add WSS Timestamp.

5. To send the message, hit the Submit button (the green arrow).

Using soapUI we send the following SOAP message:

Our web service responds back with the following SOAP message:

If we remove the Timestamp element from the client, the web responds back with an exception:

If the Timestamp is expired, we get the following:

If we remove the UsernameToken instead, the web service replies:

If the username or password is incorrect, we get the following exception instead:


Our web service has been secured but this doesn't mean it's fool-proof. Security is a serious and complicated matter. There are many numerous variables that needs to be considered. By adding security in our web service we have lessened the risk of being exposed. But remember no matter how small is the risk, it's still a risk.

To access the web service, use the following endpoint in soapUI:
http://localhost:8080/{project name}/krams/ws
where {project name} is either spring-ws (if you're using the sample application from the other tutorial) or spring-ws-wss4j (fi you're using the sample application at the end of this tutorial).

The best way to learn further is to try the actual application.

Download the project
You can access the project site at Google's Project Hosting at http://code.google.com/p/spring-ws-2-0-0-rc2-tutorial/

You can download the project as a Maven build. Look for the spring-ws-wss4j.zip in the Download sections.

You can run the project directly using an embedded server via Maven.
For Tomcat: mvn tomcat:run
For Jetty: mvn jetty:run

If you want to learn more about Spring MVC and integration with other technologies, feel free to read my other tutorials in the Tutorials section.

Related OASIS Specification and References:
- WS-Security Core Specification 1.1
- Username Token Profile 1.1
- To see the complete list, visit http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=wss
StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Spring-WS 2: WS-Security Using WSS4J ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

15 comments:

  1. Excelent introduction to wss4j&spring integration, thank you.

    ReplyDelete
  2. Good tutorial, but i get an exception:
    java.lang.ClassNotFoundException: org.apache.ws.security.WSSecurityException

    for some reason it looks for apaches' WSSecurityException but not spring-ws's one (i.e. org.springframework.ws.soap.security.WsSecurityException)

    ReplyDelete
  3. Great tutorial,

    but I can't get the response from SoapUI.
    What's the problem?


    Thanks.

    ReplyDelete
  4. Good example thanks!... I'm creating a java client to consume the webservice, without set a list because I have so many users allowed and could be morem but I got this error:

    The security token could not be authenticated or authorized; nested exception is:
    javax.security.auth.callback.UnsupportedCallbackException; nested exception is org.apache.ws.security.WSSecurityException: The security token could not be authenticated or authorized; nested exception is:
    javax.security.auth.callback.UnsupportedCallbackException

    And I dont wanna use this:




    secret
    pass


    ReplyDelete
    Replies
    1. I think you're missing some log there. Can you post the whole message using Pastebin http://pastebin.com/ ?

      Delete
  5. I am doing a sort of web services testing using soapUI, and I am running into the following issue.

    I am getting "Password has expired" message for the submitted request in soapUI. I am not getting the correct response which I am supposed to. My other members of the team are getting the correct message though.

    FYI. I did not put any password in the xml script.

    Please kindly suggest.

    ReplyDelete



  6. S:Server
    ID: 3E61EF9A-0D7B-4086-8ADC-2A5E5F449512: Password has expired


    ID: 3E61EF9A-0D7B-4086-8ADC-2A5E5F449512: Password has expired








    ReplyDelete
  7. Thanks for your great tutorial Mark. I have a spring ws application and there are many clients authanticate server and use services. I want to design a new token based security system. Is it possible database authentication for clients and using tokens for authorization. i don't want to write any username and password to xml file.

    Thanks.

    ReplyDelete
  8. I am getting following exception

    security processing failed; nested exception is:
    org.apache.ws.security.WSSecurityException: The security token could not be authenticated or authorized

    ReplyDelete
  9. Hi krams,

    I successfully deployed your application and working but when i am sending request from soap UI firsttime it is authenticating succss but second time if time is not expired it is giving failure status and user is alredy subscribed

    ReplyDelete
  10. Happy to found this blog. Good Post!. It was so good to read and useful to improve my knowledge as updated one, keep blogging. Hibernate Training in Electronic City
    Java Training in Electronic City

    ReplyDelete