Wednesday, June 26, 2013

WSO2 ESB talk to WSO2 Identity Server and get the authentication decision to invoke the proxy service

This is very good and simple example. let me explain the exact requirement.

If we need to secure the proxy service with UT (Username Token) in WSO2 ESB but all users and roles are maintained in the WSO2 Identity Server so when the users are going to invoke this service it should talk to WSO2 IS and get authenticated. In order to do this we have to implement Password Callback handler as follows.You can checkout total source here

[code language="java"]
package org.wso2.is.callback;


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.axis2.transport.http.HTTPConstants;
import org.apache.axis2.transport.http.HttpTransportProperties;
import org.apache.ws.security.WSPasswordCallback;
import org.wso2.carbon.authenticator.stub.AuthenticationAdminStub;
import org.wso2.carbon.um.ws.api.WSUserStoreManager;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import java.io.IOException;


public class ISCallBackHandler implements CallbackHandler {
private static final Log log = LogFactory.getLog(ISCallBackHandler.class);
private String serverUrl = "https://localhost:9443/services/";

private AuthenticationAdminStub authstub = null;
private ConfigurationContext ctx;
private String authCookie = null;
private WSUserStoreManager remoteUserStoreManager = null;
@Override
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
try {
for (int i = 0; i < callbacks.length; i++) {
if (callbacks[i] instanceof WSPasswordCallback) {
WSPasswordCallback passwordCallback = (WSPasswordCallback) callbacks[i];
String username = passwordCallback.getIdentifer();
String receivedPasswd = passwordCallback.getPassword();

ctx = ConfigurationContextFactory.createConfigurationContextFromFileSystem(null, null);
String authEPR = serverUrl + "AuthenticationAdmin";
authstub = new AuthenticationAdminStub(ctx, authEPR);
ServiceClient client = authstub._getServiceClient();
Options options = client.getOptions();
HttpTransportProperties.Authenticator authenticator = new HttpTransportProperties.Authenticator();
authenticator.setUsername("admin");
authenticator.setPassword("admin");
authenticator.setPreemptiveAuthentication(true);
options.setProperty(HTTPConstants.AUTHENTICATE, authenticator);
client.setOptions(options);

boolean status = authstub.login(username,receivedPasswd,"localhost");
if(status){
//Login Successful
} else{
throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
}

}
}

}catch (UnsupportedCallbackException e){
if(log.isDebugEnabled()){
log.debug(e.getMessage(), e); //logging invlaid passwords and attempts
throw e;
}
throw e;
} catch (Exception e){
log.error(e.getMessage(), e);
//can't build an unsupported exception.
throw new UnsupportedCallbackException(null, e.getMessage());
}

}
}

[/code]

1. First of all you have to build the above project and place the created jar file in to $ESB_HOME/repository/components/lib
2. Create the proxy service as follows and secured by UT
esb

esb1

esb2

esb3

2. Now you have to engage the created Password Call back handler. This is simply do with the policy configuration.
Go to policy configuration and insert the following line into the rampart configuration as follows.
"org.wso2.is.callback.ISCallBackHandler"

esb

esb1

esb2

esb3

3. Now you can invoke the service with username and password which is located in WSO2 Identity server.
(If you are going to run ESB and IS on same machine please consider the port offset as well as change the call back handler server url)

1 comment: