Ruchith Fernando's Blog

Tuesday, June 24, 2008

Web Services Security with Apache Rampart – Part 2 (Message-Level Security)

Sometime back I blogged about Nandana's article on using transport level security with Apache Rampart policy based configuration. Here's the part two of the article which talks about using WS-SecurityPolicy to apply and enforce message level on SOAP messages using Apache Axis2 and Apache Rampart.

Labels: , ,

Thursday, June 19, 2008

Back after a while ...

Hmm ... I've been away from blogging for more than a month ... so here's a recap of what I couldn't blog about :



Well ... thats it for now ... :-) ...

Labels: , , , , ,

Sunday, April 27, 2008

OpenId integration of WSO2 Identity Solution

http://wso2.org/library/3518 by Prabath

Labels: ,

Friday, April 18, 2008

WSO2 WSAS - Data Services Wins the Gold at SearchSOA Products of the Year 2007


WSO2 WSAS wins the gold award in the Data services/integration category!!!

Labels: ,

Monday, April 14, 2008

WSO2 Identity Solution 1.5 Released



WSO2 Identity Solution team is pleased to announce the release of WSO2 Identity Solution 1.5, feature-rich with OpenID.

The WSO2 Identity Solution enables LAMP and Java websites to provide strong authentication based on the new interoperable Microsoft CardSpace technology, released version 1.5 today.

This new release includes OpenID and OpenID Information Cards, further enhancing the WSO2 Identity Solution to cater to a wider audience for web based authentication. OpenID is a key feature in decentralizing single sign-on, much favored by many users.

The WSO2 Identity Solution also works with current enterprise identity directories, such as those based on the Lightweight Directory Access Protocol (LDAP) and Microsoft Active Directory, allowing them to leverage their existing infrastructure. In addition to the Identity Provider the WSO2 Identity Solution provides a Relying Party Component Set which plugs into the most common Web servers to add support for CardSpace authentication and now OpenID

WSO2 Identity Solution 1.5 can be downloaded from
http://wso2.org/downloads/solutions/identity.

Greatly appreciate your feedback and please report any issues found, using the public JIRA available at https://wso2.org/jira/browse/IDENTITY.

New features in version 1.5
---------------------------

* OpenID Provider and relying party component support
* OpenID information cards based on user name-token credential and self
issued credential
* SAML 2.0 support

Other Key Features
------------------

*Identity provider
-Simple management console
-Ability to connect to custom user stores (LDAP/Microsoft
ActiveDirectory, JDBC)
-Built in user store
-Support for the CardSpace default claim set
-Support for custom claim dialects and claims types
-Statistics/reporting/audit trail
-Ability to revoke information cards
-Issues information cards based on username-token credential and
self issued credential

*Apache HTTPD relying party module - mod_cspace
-CardSpace authentication support for static web content
-Support for any server side scripting language supported by
Apache2
-Easy integration interface for developers
-Support for content management frameworks such as Drupal,
MediaWiki
-Java Servlet Filter relying party component
-Provides an intuitive plug-in for J2EE web application
developers to enable CardSpace authentication
-Supports multi-valued claims
-Supports a set of simple operation modes

Training
--------

WSO2 Inc. offers a variety of professional Training Programs, including training on Identity Management with WSO2 Identity Solution and a number of other products.

For additional support information please refer to
http://wso2.com/training/course-catalog/


Support
-------

WSO2 Inc. offers a variety of development and production support programs, ranging from Web-based support up through normal business hours, to premium 24x7 phone support.

For additional support information please refer to
http://wso2.com/support/


- WSO2 Identity Solution Team

Thursday, March 13, 2008

Web Services Security with Apache Rampart – Part 1 ( Transport Level Security )

A tutorial on setting up UsernameToken authentication using Apache Rampart by Nandana.

Labels: , ,

Monday, February 11, 2008

Access a Restricted EJB Method as a Web Service with UsernameToken Authentication

What if we need to expose an EJB as a web service? No problem ... we can simply use the org.apache.axis2.rpc.receivers.ejb.EJBMessageReceiver provided by Axis2. But what if the EJB's methods are access restricted?

I figured out that it is very easy to write a custom wrapper web service to expose such a protected EJB and use standard UsernameToken authentication on it.

Following are the steps I followed to try this out:

Step 1 : Basic EJB sample with OpenEJB

First I followed this "hello world" sample using OpenEJB and setup the OpenEJB container and deployed the EJB.

Step 2 : Modified "HelloBean" to restrict access to "sayHello" method


@RolesAllowed({"committer"})
public String sayHello() {
return "Hello World!!!";
}


Now only users with committer role can access this method.
The users used by the default login module implementation are listed in "conf/users.properties" of the OpenEJB distribution.

Step 3 : Develop and deploy a service to wrap the EJB


We basically have to write a service that is a client to this EJB. I engaged Rampart on this service and configured it with WS-SecurityPolicy to expect a UsernameToken. And then obtained the user name and password from security processing results and used those credentials in invoking the EJB.

Have a look at the following service class :


package org.acme;

import java.io.IOException;
import java.util.Properties;
import java.util.Vector;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.rmi.PortableRemoteObject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;

import org.apache.axis2.context.MessageContext;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSSecurityEngineResult;
import org.apache.ws.security.WSUsernameTokenPrincipal;
import org.apache.ws.security.handler.WSHandlerConstants;
import org.apache.ws.security.handler.WSHandlerResult;


public class SimpleEJBService implements CallbackHandler {

public String sayHello() throws Exception {


Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.openejb.client.RemoteInitialContextFactory");
props.put(Context.PROVIDER_URL, "ejbd://127.0.0.1:4201");

//Obtain the principal
WSUsernameTokenPrincipal principal = getPrincipal();


//Set the username and password
props.put(Context.SECURITY_PRINCIPAL, principal.getName());
props.put(Context.SECURITY_CREDENTIALS, principal.getPassword());


Context ctx = new InitialContext(props);
Object ref = ctx.lookup("HelloBeanRemote");

//Invoke method
Hello h = (Hello)PortableRemoteObject.narrow(ref, Hello.class);
String result = h.sayHello();
return result;

}

/*
* Traverse the security processing results of rampart and pick the UsernameToken information.
*/
private WSUsernameTokenPrincipal getPrincipal() {
MessageContext msgCtx = MessageContext.getCurrentMessageContext();
Vector results = null;
if ((results = (Vector) msgCtx
.getProperty(WSHandlerConstants.RECV_RESULTS)) == null) {
throw new RuntimeException("No security results!!");
} else {
for (int i = 0; i < results.size(); i++) {
//Get hold of the WSHandlerResult instance
WSHandlerResult rResult = (WSHandlerResult) results.get(i);
Vector wsSecEngineResults = rResult.getResults();

for (int j = 0; j < wsSecEngineResults.size(); j++) {
//Get hold of the WSSecurityEngineResult instance
WSSecurityEngineResult wser = (WSSecurityEngineResult)
wsSecEngineResults.get(j);
int action = ((Integer)wser.get(WSSecurityEngineResult.TAG_ACTION)).intValue();
if(action == WSConstants.UT) {
WSUsernameTokenPrincipal principal = (WSUsernameTokenPrincipal) wser
.get(WSSecurityEngineResult.TAG_PRINCIPAL);
return principal;
}
}
}
}

return null;
}

public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException {
//Do nothing since we simply want to move forward
//user name and password to the EJB container
}


}



The services.xml is as follows :


<service>
<parameter name="ServiceClass" locked="false">org.acme.SimpleEJBService</parameter>
<operation name="sayHello">
<messageReceiver
class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />
</operation>

<module ref="rampart"/>

<wsp:Policy wsu:Id="UTOverTransport" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
<wsp:ExactlyOne>
<wsp:All>
<sp:TransportBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:TransportToken>
<wsp:Policy>
<sp:HttpsToken RequireClientCertificate="false"/>
</wsp:Policy>
</sp:TransportToken>
<sp:AlgorithmSuite>
<wsp:Policy>
<sp:Basic256/>
</wsp:Policy>
</sp:AlgorithmSuite>
<sp:Layout>
<wsp:Policy>
<sp:Lax/>
</wsp:Policy>
</sp:Layout>
<sp:IncludeTimestamp/>
</wsp:Policy>
</sp:TransportBinding>
<sp:SignedSupportingTokens xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:UsernameToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient" />
</wsp:Policy>
</sp:SignedSupportingTokens>

<ramp:RampartConfig xmlns:ramp="http://ws.apache.org/rampart/policy">
<ramp:passwordCallbackClass>org.acme.SimpleEJBService</ramp:passwordCallbackClass>
</ramp:RampartConfig>

</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>


</service>


Note that I didn't bother with authentication of the incoming UsernameToken because this will be handled by the login module of the EJB container.

I first copied all (probably we don't need all of them ...) openejb-* jars from the OpenEJB distro and the jar'ed org.acme.Hello interface to the "lib" directory of WSO2WSAS-2.2 standalone and deployed the service.

Step 4 : Web service client


Finally I generated a client stub using the WSDL2Java tool and developed my client code


package org.acme;

import org.acme.HelloEJBStub.SayHelloResponse;
import org.apache.axiom.om.impl.builder.StAXOMBuilder;
import org.apache.axis2.client.Options;
import org.apache.axis2.client.ServiceClient;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.ConfigurationContextFactory;
import org.apache.neethi.Policy;
import org.apache.neethi.PolicyEngine;
import org.apache.rampart.RampartMessageData;

public class Client {

public static void main(String[] args) throws Exception {

//This is because we use a self signed SSL cert in WSO2WSAS
System.setProperty("javax.net.ssl.trustStore", "/path/to/wso2wsas.jks");
System.setProperty("javax.net.ssl.trustStorePassword", "wso2wsas");

ConfigurationContext ctx = ConfigurationContextFactory.createConfigurationContextFromFileSystem("/path/to/my/client/repo");

HelloEJBStub stub = new HelloEJBStub(ctx);
ServiceClient client = stub._getServiceClient();

//Engage Rampart
client.engageModule("rampart");

Options options = client.getOptions();


//Set user name and password
options.setUserName("jonathan");
options.setPassword("secret");

//Load and set UsernameToke/HTTPS policy
options.setProperty(
RampartMessageData.KEY_RAMPART_POLICY,
loadPolicy("/path/to/simpl/usernametoken/over/https/policy.xml"));

//Invoke service operation
SayHelloResponse resp = stub.sayHello();

System.out.println(resp.get_return());
}

private static Policy loadPolicy(String xmlPath) throws Exception {
StAXOMBuilder builder = new StAXOMBuilder(xmlPath);
return PolicyEngine.getPolicy(builder.getDocumentElement());
}

}


Note that I have used "jonathan" as the user name and "secret" as the password. This user is there by default in the OpenEJB distro.

That's it !!! ... When I ran the client I got the following response:


Hello World!!!


And when I tried chaing the username I get :


Exception in thread "main" org.apache.axis2.AxisFault: This principle is not authorized.
at org.apache.axis2.util.Utils.getInboundFaultFromMessageContext(Utils.java:479)
at org.apache.axis2.description.OutInAxisOperationClient.handleResponse(OutInAxisOperation.java:351)
at org.apache.axis2.description.OutInAxisOperationClient.send(OutInAxisOperation.java:397)
at org.apache.axis2.description.OutInAxisOperationClient.executeImpl(OutInAxisOperation.java:214)
at org.apache.axis2.client.OperationClient.execute(OperationClient.java:163)
at org.acme.HelloEJBStub.sayHello(HelloEJBStub.java:433)
at org.acme.Client.main(Client.java:32)


Now it is clear that the login module was not able to authenticate the user.

Labels: , , , ,