/**
* Thrown by SsoValidationException if the passed token is invalid.
*
* @author mosstm
*
*/
public class SSOValidationException extends Exception {
private static final long serialVersionUID = 1L;
public SSOValidationException() {
super();
}
public SSOValidationException(String message, Throwable cause) {
super(message, cause);
}
public SSOValidationException(String message) {
super(message);
}
public SSOValidationException(Throwable cause) {
super(cause);
}
}
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.xml.rpc.JAXRPCException;
import javax.xml.rpc.handler.MessageContext;
import javax.xml.rpc.handler.soap.SOAPMessageContext;
import javax.xml.soap.Name;
import javax.xml.soap.Node;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPBodyElement;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFactory;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import org.systinet.wasp.handler.WaspGenericHandler;
import com.svpmfm.ice.common.context.ClientContexts;
import com.svpmfm.ice.common.remoting.IceRemoteInvocation;
public class WaspSSOAuthenticationInterceptor extends WaspGenericHandler {
public static final String SSO_TOKEN_ELEMENT = "ssoToken";
/**
* Map of method and parameter names. Each entry represents a SOAP message body element which is expected
* to contain a ssoToken for use in {@link #handleInput(MessageContext)}. This property is optional and
* is only expected to be supplied by components which are forced (typically for back compatability
* reasons) to support the explicit provision of the ssoToken as a method parameter. If this property is
* not initialised or not populated then ssoToken discovery will fall back to the default 'find in header'
* strategy.
*/
private Map<String, String> bodyParts = new HashMap<String, String>();
public WaspSSOAuthenticationInterceptor(SSOValidator ssoValidator, ClientContexts clientContextManager) {
}
public WaspSSOAuthenticationInterceptor() {
}
/**
* Typically we expect the ssoToken to be present in the header of the SOAP message like this:
*
* <pre>
* <header...>
* <...>
* <ssoToken>myssotoken123</ssoToken>
* <...>
* </header...>
* </pre>
*
* But some methods are required, for back comptability reasons, to support the explicit provision of the
* ssoToken as a method parameter. In this case the token will, of course, appear in the body of the SOAP
* message. But where? there is no reliable way of determining this without resorting to meta data so here
* comes: {@link #bodyParts} to define the method names supporting ssoToken paramaters and the name of the
* parameter storing the ssoToken. If the SOAP message's body matches on {@link #bodyParts} then we try to
* extract the ssoToken from the relevant part otherwise we fall back on the default strategy of finding
* the token in the SOAP header.
*/
public boolean handleInput(MessageContext context) {
SOAPMessage message = ((SOAPMessageContext) context).getMessage();
// it may be one of the back compatible methods which still accepts the token in the body
String ssoToken = getTokenFromBody(message);
if (ssoToken == null) {
ssoToken = getTokenFromHeader(message);
}
IceRemoteInvocation.setSsoToken(ssoToken == null ? "dummyToken" : ssoToken);
return true;
}
private String getTokenFromHeader(SOAPMessage message) {
String ssoToken = null;
try {
SOAPHeader header = message.getSOAPPart().getEnvelope().getHeader();
if (header != null) {
Iterator kids = header.getChildElements(SOAPFactory.newInstance().createName(SSO_TOKEN_ELEMENT));
SOAPElement elem = (SOAPElement) kids.next();
if (elem != null) {
Iterator childElements = elem.getChildElements();
Node tokenElem = (Node) childElements.next();
ssoToken = tokenElem.getValue();
}
}
} catch (SOAPException e) {
throw new JAXRPCException("No SSO token provided.");
} catch (RuntimeException e) {
throw new JAXRPCException("Invalid User", e);
} catch (Exception e) {
throw new JAXRPCException("SSO failure ", e);
}
return ssoToken;
}
private String getTokenFromBody(SOAPMessage message) {
String ssoToken = null;
if (getBodyParts() != null && !getBodyParts().isEmpty()) {
try {
SOAPBody body = message.getSOAPPart().getEnvelope().getBody();
if (body != null) {
Iterator kids = body.getChildElements();
while (kids.hasNext()) {
SOAPBodyElement element = (SOAPBodyElement) kids.next();
Name name = element.getElementName();
String headerEntryName = name.getLocalName();
if (matched(headerEntryName)) {
Iterator grandkids = element.getChildElements(SOAPFactory.newInstance().createName(
getBodyParts().get(headerEntryName)));
SOAPElement elem = (SOAPElement) grandkids.next();
if (elem != null) {
Iterator childElements = elem.getChildElements();
Node tokenElem = (Node) childElements.next();
ssoToken = tokenElem.getValue();
}
}
}
}
} catch (SOAPException e) {
throw new JAXRPCException("No SSO token provided.");
} catch (RuntimeException e) {
throw new JAXRPCException("Invalid User", e);
} catch (Exception e) {
throw new JAXRPCException("SSO failure ", e);
}
}
return ssoToken;
}
private boolean matched(String headerEntryName) {
for (String bodyPart : getBodyParts().keySet()) {
if (bodyPart.equals(headerEntryName)) {
return true;
}
}
return false;
}
public Map<String, String> getBodyParts() {
return bodyParts;
}
public void setBodyParts(Map<String, String> bodyParts) {
this.bodyParts = bodyParts;
}
}
import javax.xml.rpc.JAXRPCException;
import javax.xml.rpc.handler.MessageContext;
import javax.xml.rpc.handler.soap.SOAPMessageContext;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFactory;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import org.systinet.wasp.handler.WaspGenericHandler;
import com.svpmfm.ice.common.context.ClientContexts;
public class WaspSSOClientAuthenticationHandler extends WaspGenericHandler {
public static final String SSO_TOKEN_ELEMENT = "SSOToken";
public static final String SSO_USER_ELEMENT = "SSOUser";
private ClientContexts clientContextManager;
public WaspSSOClientAuthenticationHandler(ClientContexts clientContextManager) {
this.clientContextManager = clientContextManager;
}
public WaspSSOClientAuthenticationHandler() {
}
public boolean handleOutput(MessageContext context) {
SOAPMessage message = ((SOAPMessageContext) context).getMessage();
insertSSODetailsInHeader(message);
return true;
}
private void insertSSODetailsInHeader(SOAPMessage message) {
try {
SOAPHeader header = message.getSOAPPart().getEnvelope().getHeader();
if (header != null) {
SOAPElement ssoTokenElement = SOAPFactory.newInstance().createElement(SSO_TOKEN_ELEMENT);
ssoTokenElement.addTextNode(getSSOToken());
header.addChildElement(ssoTokenElement);
SOAPElement ssoUserElement = SOAPFactory.newInstance().createElement(SSO_USER_ELEMENT);
ssoUserElement.addTextNode(getSSOUserName());
header.addChildElement(ssoUserElement);
}
} catch (SOAPException e) {
throw new JAXRPCException("No SSO header provided.");
} catch (RuntimeException e) {
throw new JAXRPCException("Invalid User", e);
} catch (Exception e) {
throw new JAXRPCException("SSO failure ", e);
}
}
private String getSSOToken() {
return clientContextManager.getCurrentContext().getSsoToken();
}
private String getSSOUserName() {
return clientContextManager.getCurrentContext().getUser().getName();
}
}