The lows and highs of SAML

I’ve been working on a number of OAUTH based authentication systems recently as part of the work I’m doing for Warwickshire County Council on the Alpha Identify project. This has led me to also look at SAML. I’ve been building a simple SAML demo app to help me understand how it works, and in expectation that I will need to start building SAML systems in the next month or two. I’ve been using Onelogin’s ruby-saml as a guide to what is needs, and Lawrence Pit’s ruby-saml-idp project was a great help in getting started.

In working through ruby-saml, it seems clear to me that it is a porting from another language. This works, and means it is based on proven techniques. However, I think starting over and building some of the tools needed to produce SAML solutions, in a more ruby way, would make the code cleaner and more easy to extend. So I have started building saml_tools as a ruby toolbox for working with SAML objects.

Another major driver behind saml_tools stems from my belief that the starting point for building many SAML solutions will be the SAML documents themselves. That is, the developer will know the SAML document that will be sent to request authentication, and the document that will be sent in response to that request. They will then need to build the tools that will create, send, receive and process these documents. So I wanted a system that will make it easy to use an existing SAML document as a template for generating more documents. For me, the obvious solution was to use erb templates. It works well for Rails; why not SAML too. The resulting template is a lot easier to ‘read’ and understand, than a document that is solely built in multiple Nokogiri or REXML insertions.

However, the process has not been plain sailing and has involved a lot of head scratching, particularly regarding the signing of SAML responses. To quote this blog: “using a certificate to sign a request is the root of all evil.“, and putting the assertion signature inside the assertion itself seems perversely complex to me. I think the best demonstration of the lows and highs I went through in trying to work it out are three email I sent to a college during my ordeal:

Hi,

Thought I’d let off steam a little:

Unravelling SAML is A PAIN IN THE ARSE!

To test something, you have to pull something from over there, and manipulate it based on something somewhere else, and then compare it with the element here!

It’s like wadding through mud.

For example, the signature is in the stuff being signed. So you have to extract the signature, before you can check if it matches the stuff it was in.

Who designed this system!

Rob – working through it slowly but surely.

Which was followed fairly quickly with:

I think I’ve come up with a really simple example of why inserting the signature into the data being signed is fundamentally flawed.

Imagine my data is all held in a foo tag, I create a signature that I store in a bar tag:

 <foo>
  <bar>
  <\bar>
 <\foo>

Before I can check the signature I need to remove bar. However, what do I leave behind? For example, should foo now look like this:

 <foo>
 <\foo>

or this:

 <foo><\foo>

Now that may seem a trivial difference, but the problem is that the signed data is wrapped up with base64 encoding. And those two examples output different results when encoded!!!!

At that point I was ready to give up. I’d written a sequence of steps that appeared to be working, but when I put them together to check part of a signature from a real SAML request document, it failed. I could not see what was wrong and I was starting to go round in circles. Fortunately, being the pig headed buffoon I am, I persevered and finally:

The solution to my problems was to read up on XML security. Reading this was my eureka moment:

http://users.dcc.uchile.cl/~pcamacho/tutorial/web/xmlsec/xmlsec.html

The way SAML signs responses isn’t so much a SAML thing, as an XML thing. It’s one of the “standard” ways of signing XML documents. I still think it is mad to put the signature inside the section of XML being signed – especially as the standard gives you other options.

I think it must come from when you sign a whole document. In that case, where else can you put the signature but inside the document? Otherwise you risk breaking the integrity of the document, or separating the signature from the document being signed.

Also, two things I struggled to get my head round: canonicalization, and the format of white space around the removed signature; turned out to be intimately related. Canonicalization is the fix for the white space problem; it formats any XML document or fragment, into a standard format that is shared across all implementations of XML. So it ensures that the space betweens two elements, that is left when a signature is removed, is always of the same format.

So in two days I’ve gone from being ready to give up on SAML, to now having a much better understanding of how it all fits together.

With my new found knowledge, I was able to build a SAML response from scratch, and when I tested that against my code, it validated correctly. It turned out that the problem was not the code but the document I was testing it against. That’s why I could not see a fault in the code!

However, the key point is this is yet another example of where failure leads to much better understanding. If my code had just worked, I would not have had to dig so much deeper into the underlying systems, and I would not have learnt as much as I did about how SAML works.

So, yet another example of the fact that you learn more from your failures than your successes.

This entry was posted in Ruby and tagged , , , . Bookmark the permalink.