Sunday, July 12, 2015

Handling SAML metadata with opensaml - Part 1

SAML metadata specification describes SAML metadata as,
SAML profiles require agreements between system entities regarding identifiers, binding support and endpoints, certificates and keys, and so forth. A metadata specification is useful for describing this information in a standardized way. This specification defines an extensible metadata format for SAML system entities, organized by roles that reflect SAML profiles.
Opensaml library provides facilities to handle SAML metadata. From here you can add opensaml dependency to your project or download the jar.
http://mvnrepository.com/artifact/org.opensaml/opensaml/2.6.4

Bellow method can be used to create opensaml metadata objects.


1
2
3
4
5
6
7
8
private <T> T createSAMLObject(final Class<T> clazz) throws NoSuchFieldException, IllegalAccessException {
        XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory();

        QName defaultElementName = (QName)clazz.getDeclaredField("DEFAULT_ELEMENT_NAME").get(null);
        T object = (T)builderFactory.getBuilder(defaultElementName).buildObject(defaultElementName);

        return object;
}

As an example if we want to create EntityDescriptor object, we can do it like this

EntityDescriptor entityDescriptor = createSAMLObject(EntityDescriptor.class);

Properties of the EntityDescriptor like EntityID can set simply like bellow.

entityDescriptor.setEntityID("EntityID");

EntityDescriptor contains one or more RoleDescriptors. We can create a role descriptor as bellow.

SPSSODescriptor spSSODescriptor = createSAMLObject(SPSSODescriptor.class);

SPSSODescriptor can be added to EntityDescriptor like bellow.

entityDescriptor.getRoleDescriptors().add(spSSODescriptor);

All the properties and elements of SAML Metadata spec are supported by opensaml library. So you can easily handle SAML metadata like this.

If we want to get the xml string of the metadata object we have created, we can use the bellow method

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public String getMetadataString(EntityDescriptor entityDescriptor) {
        String metadataXML = "";

        DocumentBuilder builder;
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

        try {
            builder = factory.newDocumentBuilder();
            Document document = builder.newDocument();
            Marshaller out = Configuration.getMarshallerFactory().getMarshaller(entityDescriptor);
            out.marshall(entityDescriptor, document);

            Transformer transformer = TransformerFactory.newInstance().newTransformer();
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");

            StringWriter stringWriter = new StringWriter();
            StreamResult streamResult = new StreamResult(stringWriter);
            DOMSource source = new DOMSource(document);
            transformer.transform(source, streamResult);
            stringWriter.close();
            metadataXML = stringWriter.toString();
        } catch (ParserConfigurationException | IOException | MarshallingException | TransformerException e) {
            e.printStackTrace();
        }

        return metadataXML;
}

If we want to create a metadata object from a metadata xml file, we can use the bellow method.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
public EntityDescriptor getMetadataObject(){
        EntityDescriptor entityDescriptor = null;

        try {

            FilesystemMetadataProvider idpMetaDataProvider = new FilesystemMetadataProvider(new File("file_path"));

            idpMetaDataProvider.setRequireValidMetadata(true);
            idpMetaDataProvider.setParserPool(new BasicParserPool());
            idpMetaDataProvider.initialize();

            XMLObject xmlObject = idpMetaDataProvider.getMetadata();
            entityDescriptor = (EntityDescriptor)xmlObject;
        } catch (MetadataProviderException e) {
            e.printStackTrace();
        }
        return entityDescriptor;
}

Before we start to do any of these things we need to bootstrap opensaml library. We can do it simply like this,

DefaultBootstrap.bootstrap();

In my next post I will focus on how to create saml metadata extensions.