Sunday, May 5, 2013

HTTP Basic Authentication via Web Browser

Web servers might use HTTP Basic Authentication to allow access to protected resources. This is a challenge and response mechanism.

How does the web server challenge?

When the browser sends a request to a protected resource, server sends back an HTTP 401 (Unauthorized) status code with a header:

WWW-Authenticate: Basic realm="site name"

realm is an identifier given to the protected area.

Refer following HTTP headers captured while trying to access my WiFi router's admin console :)


How does web browser respond??

Usually, when the browser receives this, it prompts the user to enter credentials. It also displays the realm name.


Upon user submit, browser sends the original request back to the server, but this time including an additional header:  

Authorization: Basic username:password

username:password is sent Base64 encoded.


Usually the browse caches this so the user doesn't have to enter the credentials all the time.

Ref:
IBM
wikipedia

Wednesday, May 1, 2013

Pretty-print XML using Java

This can be done by using the javax.xml.transform package as follows:
import java.io.StringReader;
import java.io.StringWriter;

import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.*;

...

public static String prettyFormat(String input, int indent) {
 try {
     Source xmlInput = new StreamSource(new StringReader(input));
     StringWriter stringWriter = new StringWriter();
     StreamResult xmlOutput = new StreamResult(stringWriter);
     TransformerFactory transformerFactory = TransformerFactory.newInstance();
     Transformer transformer = transformerFactory.newTransformer(); 
     transformer.setOutputProperty(OutputKeys.INDENT, "yes");
     transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", String.valueOf(indent));
     transformer.transform(xmlInput, xmlOutput);
     return xmlOutput.getWriter().toString();
 } catch (Exception e) {
     e.printStackTrace();
     return null;
 }
}
Ref:
http://stackoverflow.com/questions/139076/how-to-pretty-print-xml-from-java

Extracting values from an XML payload using AXIOM

From the following XML payload (only the required parts are displayed) I received while testing Passive-STS with WSO2 Identity Server, I wanted to get the values of "NameIdentifier" and the Claims which are included in 'Attribute' tags.
<?xml version="1.0" encoding="UTF-8"?><wst:RequestSecurityTokenResponseCollection xmlns:wst="http://docs.oasis-open.org/ws-sx/ws-trust/200512">
  <wst:RequestSecurityTokenResponse>
    <wst:TokenType>http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1</wst:TokenType>
    <wst:RequestedAttachedReference>
      <wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
        <wsse:KeyIdentifier ValueType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.0#SAMLAssertionID">_619a4efa0be21de4227fa5c45e9d1c31</wsse:KeyIdentifier>
      </wsse:SecurityTokenReference>
    </wst:RequestedAttachedReference>
    <wst:RequestedUnattachedReference>
      <wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
        <wsse:KeyIdentifier ValueType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.0#SAMLAssertionID">_619a4efa0be21de4227fa5c45e9d1c31</wsse:KeyIdentifier>
      </wsse:SecurityTokenReference>
    </wst:RequestedUnattachedReference>
    <wst:Lifetime>
      <wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2013-05-01T03:17:10.592Z</wsu:Created>
      <wsu:Expires xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2013-05-01T03:22:10.592Z</wsu:Expires>
    </wst:Lifetime>
    <wst:RequestedSecurityToken>
      <Assertion xmlns="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:samlp="urn:oasis:names:tc:SAML:1.0:protocol" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" AssertionID="_619a4efa0be21de4227fa5c45e9d1c31" IssueInstant="2013-05-01T03:17:10.595Z" Issuer="localhost" MajorVersion="1" MinorVersion="1">
        <Conditions NotBefore="2013-05-01T03:17:10.592Z" NotOnOrAfter="2013-05-01T03:22:10.592Z"/>
        <AttributeStatement>
          <Subject>
            <NameIdentifier Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">admin</NameIdentifier>
            <SubjectConfirmation>
              <ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:bearer</ConfirmationMethod>
            </SubjectConfirmation>
          </Subject>
          <Attribute AttributeName="Email" AttributeNamespace="http://wso2.org/claims/emailaddress">
            <AttributeValue>admin@wso2.com</AttributeValue>
          </Attribute>
          <Attribute AttributeName="First Name" AttributeNamespace="http://wso2.org/claims/givenname">
            <AttributeValue>admin</AttributeValue>
          </Attribute>
        </AttributeStatement>
        ...
After trying few methods, one of my colleagues suggested using AXIOM. Thanks to AXIOMUtil.stringToOM() It turned out to be a pretty simple thing :)

Following is the code I used to reach those values...
public void handleResponse(String response){
 OMElement element = null;
        
 try {
     element = AXIOMUtil.stringToOM(response);
 } catch (XMLStreamException e) {
     e.printStackTrace();
 }

 element = element.getFirstChildWithName(new QName("http://docs.oasis-open.org/ws-sx/ws-trust/200512", "RequestSecurityTokenResponse"));
 element = element.getFirstChildWithName(new QName("http://docs.oasis-open.org/ws-sx/ws-trust/200512", "RequestedSecurityToken"));
 element = element.getFirstChildWithName(new QName("urn:oasis:names:tc:SAML:1.0:assertion", "Assertion"));
 element = element.getFirstChildWithName(new QName("urn:oasis:names:tc:SAML:1.0:assertion", "AttributeStatement"));

 OMElement subjectElement = element.getFirstChildWithName(new QName("urn:oasis:names:tc:SAML:1.0:assertion", "Subject"));

 String username = subjectElement.getFirstElement().getText();

 Iterator itr = element.getChildrenWithName(new QName("urn:oasis:names:tc:SAML:1.0:assertion", "Attribute"));

 Map<String, String> claimMap = new HashMap<String, String>();
  
 while(itr.hasNext()){
     OMElement elem = (OMElement)itr.next();
     String claimURI = ((OMAttribute)elem.getAttribute(new QName("AttributeNamespace"))).getAttributeValue();
     claimMap.put(claimURI, elem.getFirstElement().getText()); 
 }
}
There, username will contain the value of the 'NameIdentifier' i.e. admin
And claimMap will contain the claims, where Map entry's key will be 'AttributeNamespace' and value will be 'AttributeValue'.