August 27, 2015

Understanding Web-Services Security & XML Encryption

Web-services are client and server programs that communicate over the Hypertext Transfer Protocol (HTTP). They use SOAP messaging, which is much more efficient and less bandwidth-costly. Web-services have become a vital technology for organizations because of the variety of features offered.

The security of web-services is important to understand, because it affects the data flow over different networks.

Schemes to Provide Message-Level Security

XML Digital Signature

The XML digital signature is designed to be used in XML transaction and provides authentication, data integrity, and non-repudiation. XML digital signature offers flexibility by allowing for one or more items to be signed, as well as both XML and non-XML data.  Additionally, it is used to sign only specific portions of the XML tree, rather than the complete document.

The XML signature itself will generally indicate the location of the original signed object. This reference can:

  • Be referenced by a URI within the XML signature
  • Reside within the same resource as the XML signature (the signature is a sibling)
  • Be embedded within the XML signature (the signature is the parent)
  • Have its XML signature embedded within itself (the signature is the child)

XML Encryption

XML Encryption gives developers a secure, uniform way to protect their XML documents. Using this scheme, only the data that should be encrypted will be, rather than the whole document.

An example of XML Encryption is given below:

<Order>
<name>Prabhat Singh</name>
<address>ABC</address>
<prodNumber>9012345678</prodNumber>
<quantity>4</quantity>
<EncryptedData xmlns='http://www.w3.org/2000/11/temp-xmlenc'>
<EncryptionMethod Algorithm="urn:nist-gov:tripledes-ede-cbc">
<s0:IV xmlns:s0='http://somens'>ABCD</s0:IV>
</EncryptionMethod>
<KeyInfo xmlns='http://www.w3.org/2000/09/xmldsig#'>
</KeyInfo>
<CipherData>A23B45C56</CipherData>
</EncryptedData>
</Order>

XML Key Management Specification (XKMS)

XKMS consists of two parts: XKISS (XML Key Information Service Specification) and XKRSS (XML Key Registration Service Specification). XKISS defines a protocol for resolving or validating public keys contained in a signed and encrypted XML documents, while XKRSS defines a protocol for public key registration, revocation, and recovery.

The key aspect of XKMS is that it serves as a protocol specification between an XKMS client and in XKMS server. In doing this, the XKMS server provides trust services to its clients (in the form of web services) by performing various public key infrastructure (PKI) operations, such as public key validation, registration, recovery, and revocation on behalf of the clients.

Extensible Access Control Markup Language (XACML)

The primary goal of XACML is to standardize the access control language in XML syntax. There is no need to develop an application-specific access control language or to write the access control policy in multiple languages; instead, system administrators should need to understand only one standardized language.

Secure Assertion Markup Langauge (SAML)

SAML is an XML-based framework used to exchange security-related information between the client and the servers. The security information is expressed in terms of assertions, which defines how SAML assertion can transport using SOAP over HTTP.

WS-Security

Web-service security specification defines end-to-end SOAP messaging security through SOAP header extensions. It supports a one-time authentication feature, XML encryption, multiple security tokens, and exchanges signs from the communication partner.

Example

  1. WEB-INF/sun-jaxws.xml: Endpoints for requests
    <?xml version="1.0" encoding="UTF-8"?>
    <endpoints
      xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime"
      version="2.0">
      <endpoint
        name="CalWS"
        implementation="com.tpg.prabhat.CalWSImpl"
        url-pattern="/CallWS"/>
    </endpoints>
  2. Service interface: To request handler interface where path has been given (handler.xml) for header validation class
    @WebService
    @HandlerChain(file="handler.xml")
    public interface CalWS {
    	@WebResult(name = "HeaderResponse")
    	public String headerValidation();
    
    }
  3. Handler.xml: Contains header validation class path
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <javaee:handler-chains xmlns:javaee="http://java.sun.com/xml/ns/javaee"
    	xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    	<javaee:handler-chain>
    		<javaee:handler>
    			<javaee:handler-class>com.tpg.prabhat.header.SoapHeaderValidator</javaee:handler-class>
    		</javaee:handler>
    	</javaee:handler-chain>
    </javaee:handler-chains>
  4. Service Implementation class: SOAP service implementation class
    @WebService(endpointInterface = "com.tpg.prabhat.CalWS",
    portName="calWSPort", serviceName = "calWSService")
    @HandlerChain(file="handler.xml")
    
    public class CalWSImpl implements CalWS {
    @WebMethod(operationName = "HeaderRequest", action = "headerValidation")
    	@WebResult(name = "HeaderResponse")
    	public String headerValidation(){
    		// other code process
    		return "chain";
    	}
    }
  5. SoapHeaderValidator.java: Validation class to validate username and password
    public class SoapHeaderValidator implements SOAPHandler<SOAPMessageContext>{
    
    	@Override
    	public boolean handleMessage(SOAPMessageContext context) {
    
    		System.out.println("Server : handleMessage()......");
    
    		Boolean isRequest = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
    
    		if(!isRequest){
    
    			try{
    				SOAPMessage soapMsg = context.getMessage();
    				SOAPEnvelope soapEnv = soapMsg.getSOAPPart().getEnvelope();
    				SOAPHeader soapHeader = soapEnv.getHeader();
    
    				//if no header, add one
    				if (soapHeader == null){
    					soapHeader = soapEnv.addHeader();
    					//throw exception
    					generateSOAPErrMessage(soapMsg, "No SOAP header.");
    				}
    
    				Iterator it = soapHeader.extractAllHeaderElements();
    
    				if (it == null || !it.hasNext()){
    					generateSOAPErrMessage(soapMsg, "No header block for next actor.");
    				}
    
    				Node node = (Node) it.next();
    				String name = node.getNodeName();
    				String value = (node == null) ? null : node.getValue();
    
    				if (value == null){
    					generateSOAPErrMessage(soapMsg, "No value in header block.");
    				}
    
    				if(!name.equals("UsernameToken") && !value.equals("Prabhat")){
    					generateSOAPErrMessage(soapMsg, "Invalid key and value, access is denied.");
    				}
    
    				//tracking
    				soapMsg.writeTo(System.out);
    
    			}catch(SOAPException e){
    				System.err.println(e);
    			}catch(IOException e){
    				System.err.println(e);
    			}
    
    		}
    
    		//continue other handler chain
    		return true;
    	}
    
    	@Override
    	public boolean handleFault(SOAPMessageContext context) {
    
    		System.out.println("Server : handleFault()......");
    
    		return true;
    	}
    
    	@Override
    	public void close(MessageContext context) {
    		System.out.println("Server : close()......");
    	}
    
    	@Override
    	public Set<QName> getHeaders() {
    		System.out.println("Server : getHeaders()......");
    		return null;
    	}
    
    	private void generateSOAPErrMessage(SOAPMessage msg, String reason) {
    		try {
    			SOAPBody soapBody = msg.getSOAPPart().getEnvelope().getBody();
    			SOAPFault soapFault = soapBody.addFault();
    			soapFault.setFaultString(reason);
    			throw new SOAPFaultException(soapFault); 
    		}
    		catch(SOAPException e) { }
    	}
    
    }
  6. SOAP Request: Simple SOAP request
    <?xml version="1.0" encoding="utf-8"?>
    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    	<soap:Header>
    		<Username>pks</Username>
    		<Password Type="PasswordText">>password</Password>
    	</soap:Header>
    	<soap:Body>
    		<ns2:getHelloWorldAsString xmlns:ns2="http://prabhat.tpg.com/">
    			// other string as per requirement
    		</ns2:getHelloWorldAsString>
    	</soap:Body>
    </soap:Envelope>

Find the source code here.