I have a external SOAP Web service that is implemented with WS-Security and SAML ... The SOAP Request of the web service is as following :-
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v1="http://services.test.getDesignation.com/schema/MainData/V1">
<soapenv:Header>
<wsse:Security 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">
<saml1:Assertion AssertionID="_1EB4A2A52467EB9373141364603919871" IssueInstant="2014-10-18T15:27:19.198Z" Issuer="self" MajorVersion="1" MinorVersion="1" xsi:type="saml1:AssertionType" xmlns:saml1="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<saml1:Conditions NotBefore="2014-10-18T15:27:19.198Z" NotOnOrAfter="2014-10-18T15:32:19.198Z"/>
<saml1:AuthenticationStatement AuthenticationInstant="2014-10-18T15:27:19.198Z" AuthenticationMethod="urn:oasis:names:tc:SAML:1.0:am:password" xsi:type="saml1:AuthenticationStatementType">
<saml1:Subject>
<saml1:NameIdentifier Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">getDesignationservice</saml1:NameIdentifier>
<saml1:SubjectConfirmation>
<saml1:ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:sender-vouches</saml1:ConfirmationMethod>
</saml1:SubjectConfirmation>
</saml1:Subject>
</saml1:AuthenticationStatement>
</saml1:Assertion>
<wsse:UsernameToken wsu:Id="UsernameToken-1EB4A2A52467EB9373141364603919870">
<wsse:Username>username</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">password</wsse:Password>
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">FCyqP2DThmR6ygNWnzNrKQ==</wsse:Nonce>
<wsu:Created>2014-10-18T15:27:19.198Z</wsu:Created>
</wsse:UsernameToken>
<wsu:Timestamp wsu:Id="TS-1EB4A2A52467EB9373141364603919869">
<wsu:Created>2014-10-18T15:27:19.197Z</wsu:Created>
<wsu:Expires>2014-10-18T15:28:19.197Z</wsu:Expires>
</wsu:Timestamp>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<v1:getDesignationRequest>
<v1:DesignationCode>bd</v1:DesignationCode>
</v1:getDesignationRequest>
</soapenv:Body>
</soapenv:Envelope>
Now , what I am trying to do is to call the external service in Java code using SAAJ ..
So far I tried the following :-
import java.io.ByteArrayOutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.Random;
import java.util.TimeZone;
import javax.xml.namespace.QName;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPBodyElement;
import javax.xml.soap.SOAPConnection;
import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPHeaderElement;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import org.apache.xerces.impl.dv.util.Base64;
import org.w3c.dom.Node;
public class SOAPSecurity3 {
private static String calculatePasswordDigest(String nonce, String created, String password) {
String encoded = null;
try {
String pass = hexEncode(nonce) + created + password;
MessageDigest md = MessageDigest.getInstance( "SHA1" );
md.update( pass.getBytes() );
byte[] encodedPassword = md.digest();
encoded = Base64.encode(encodedPassword);
} catch (NoSuchAlgorithmException ex) {
/* Logger.getLogger(HeaderHandler.class.getName()).log(Level.SEVERE, null, ex);*/
}
return encoded;
}
private static String hexEncode(String in) {
StringBuilder sb = new StringBuilder("");
for (int i = 0; i < (in.length() - 2) + 1; i = i + 2) {
int c = Integer.parseInt(in.substring(i, i + 2), 16);
char chr = (char) c;
sb.append(chr);
}
return sb.toString();
}
private static SOAPMessage createSoapRequest(String value) throws Exception{
//This is used to get time in SOAP request in yyyy-MM-dd'T'HH:mm:ss.SSS'Z' format
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:dd.SSS'Z'");
formatter.setTimeZone(TimeZone.getTimeZone("GMT"));
//This is for UsernameToken element
Random generator = new Random();
String nonceString = String.valueOf(generator.nextInt(999999999)); // This generate random nonce
Date timestamp = new java.util.Date();
String pass = "password";
String user = "username";
//This is for UsernameToken element ends
//This is for TimeStamp element value
java.util.Date create = new java.util.Date();
java.util.Date expires = new java.util.Date(create.getTime() + (5l * 60l * 1000l));
//This is for TimeStamp value ends
MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage soapMessage = messageFactory.createMessage();
SOAPPart soapPart = soapMessage.getSOAPPart();
//SOAP Envelope
SOAPEnvelope soapEnvelope = soapPart.getEnvelope();
soapEnvelope.addNamespaceDeclaration("v1", "http://services.test.getDesignation.com/schema/MainData/V1");
//SOAP Header
SOAPHeader header = soapMessage.getSOAPHeader();
if (header == null) {
header = soapEnvelope.addHeader();
}
SOAPElement security =header.addChildElement("Security", "wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd").addAttribute(new QName("xmlns:wsu"), "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
SOAPElement usernameToken = security.addChildElement("UsernameToken", "wsse").addAttribute(QName.valueOf("wsu:Id"),"UsernameToken-89293AC6E584F11ADF141358720544137");
// add the username to usernameToken
SOAPElement userNameSOAPElement = usernameToken.addChildElement("Username","wsse");
userNameSOAPElement.addTextNode("username");
// add the password to usernameToken
SOAPElement passwordSOAPElement = usernameToken.addChildElement("Password","wsse").addAttribute(new QName("Type"), "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText");
passwordSOAPElement.addTextNode("password");
//Adding random Nonce
SOAPElement nonce =usernameToken.addChildElement("Nonce", "wsse").addAttribute(new QName("EncodingType"), "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary");
nonce.addTextNode(Base64.encode(hexEncode(nonceString).getBytes()));
//Adding created element of UsernameToken
SOAPElement created = usernameToken.addChildElement("Created", "wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
created.addTextNode(formatter.format(timestamp)); //formatter formats the date to String
//Adding Timestamp
SOAPElement timestampElem = security.addChildElement("Timestamp", "wsu").addAttribute(QName.valueOf("wsu:Id"),"TS-1EB4A2A52467EB9373141362942343119");
SOAPElement elem = timestampElem.addChildElement("Created", "wsu");
elem.addTextNode(formatter.format(create)); //formatter formats the date to String
timestampElem.addChildElement(elem);
elem = timestampElem.addChildElement("Expires", "wsu");
elem.addTextNode(formatter.format(expires)); //formatter formats the date to String
timestampElem.addChildElement(elem);
//////SOAP Body
SOAPBody soapBody = soapEnvelope.getBody();
SOAPElement soapElement = soapBody.addChildElement("getDesignationRequest", "v1");
SOAPElement element1 = soapElement.addChildElement("DesignationCode", "v1");
element1.addTextNode(value);
soapMessage.saveChanges();
System.out.println("----------SOAP Request------------");
soapMessage.writeTo(System.out);
return soapMessage;
}
private static void createSoapResponse(SOAPMessage soapResponse) throws Exception {
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
Source sourceContent = soapResponse.getSOAPPart().getContent();
System.out.println("\n----------SOAP Response-----------");
/////////////////////////////////////////////////////
StreamResult result = new StreamResult(System.out);
transformer.transform(sourceContent, result);
System.out.println();
}
public static void main(String args[]) throws Exception{
SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
SOAPConnection soapConnection = soapConnectionFactory.createConnection();
String url = "http://localhost:8090/designation";
SOAPMessage soapRequest = createSoapRequest("SSE");
SOAPMessage soapResponse = soapConnection.call(soapRequest, url);
createSoapResponse(soapResponse);
String Code =soapResponse.getSOAPBody().getElementsByTagName("Code").item(0).getFirstChild().getNodeValue();
if(Code.equals("Success"))
{
String Result=soapResponse.getSOAPBody().getElementsByTagName("DesignationCodeResult").item(0).getFirstChild().getNodeValue();
System.out.println(Result );
}
else
{
System.out.println("SOAP Fault");
}
soapConnection.close();
}
}
Which is able to produce following Request and call the external service :-
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v1="http://services.test.getDesignation.com/schema/MainData/V1">
<SOAP-ENV:Header>
<wsse:Security 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="UsernameToken-89293AC6E584F11ADF141358720544137">
<wsse:Username>username</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">password</wsse:Password>
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">FyRZEA==</wsse:Nonce>
<wsu:Created>2014-10-19T15:38:19.744Z</wsu:Created>
</wsse:UsernameToken>
<wsu:Timestamp wsu:Id="TS-1EB4A2A52467EB9373141362942343119">
<wsu:Created>2014-10-19T15:38:19.744Z</wsu:Created>
<wsu:Expires>2014-10-19T15:43:19.744Z</wsu:Expires>
</wsu:Timestamp>
</wsse:Security>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<v1:getDesignationRequest>
<v1:DesignationCode>SSE</v1:DesignationCode>
</v1:getDesignationRequest>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
But I am not able to generate SAML tags required in this java code to generate the Actual SOAP Request that is required (mentioned at the top in the question) .. Please help .. how can I use this Java code to generate **SAML**
Request required for the secured external service ...
Thanks
You can use a Axis 2 client and add Rampart to it for adding SAML support.. Is it possible for you to do that?