Genuity Tech Blog

Tidbits of Ruby, Rails, and all things related

Signing SOAP messages in Ruby using certificates

TL; DR

Need to sign SOAP messages in Ruby with a X.509 certificate? Check out our forks of Savon and Akami. I have to give credit where credit is due. @amiel with Carnes Media did almost all of the work. I just fixed a bug and updated their work to play nice with the latest version of Savon.



I’ve been a Ruby and Rails developer now for about 5 years. In that time, I could probably count on one hand finger the number of times I’ve had to consume a SOAP service. Ruby and Rails developers seem to avoid XML, and it’s ugly step-sister SOAP, like the plague. These days, it seems most of the APIs with which I find myself interacting are usually of the JSON variety. Sometimes XML. But rarely are they full-blown SOAP APIs.

That all changed recently when my current client tasked me with connecting to a SOAP service provided by a very high-profile corporation, whose name shall remain anonymous. I thought, “SOAP. No big deal.” I quickly reached for Savon, a fantastic Ruby library for SOAP written by Daniel Harrington. My parade was soon rained on when I was told by the client, “Oh yeah. We need to be able to sign the SOAP messages with a X.509 certificate.”

Great. Savon doesn’t support signing SOAP messages with X.509 certificates. Luckily, I found this fork of Savon, which did provide the exact functionality I needed. This was all great news, except for one thing. When I tried to use it, I kept getting a SOAP fault from the service provider: Signature verification failed. This was an indication that the message signing was failing.

After many long hours of debugging and researching how message signing actually works in SOAP, I finally tracked down the problem to an out-of-place <DigestValue> element in the security header. The Savon fork I was using was putting it in the wrong place. Whatever service the original author was connecting to must not have cared about this. The service I was using wasn’t as forgiving. The error message wasn’t very helpful but I figured it out, nevertheless.

The next thing to do was to fix the bug. My instinct was to fork the carnesmedia fork and fix it there. I noticed, however, that their fork was pretty old, and a lot had changed with Savon since then. There were bugs that had been squashed, and the limited WSSE support that Savon did provide had been pulled out into a separate gem. So I set out to implement @amiel’s certificate-signing functionality into the latest version of Akami, the gem that now provided Savon with the WSSE stuff.

I’ve finished the changes necessary to incorporate this all into the latest verions of Akami and Savon and it works great! I’ve submitted pull requests to each of the respective projects. Hopefully the author will pull them in.

If you have the need to sign SOAP messages with a X.509 certificate and want to use Savon, check out our fork of Akami. There were also changes that needed to be made to Savon in order to incorporate the new certificate-signing stuff, so you will also need to use our Savon fork as well.

What did I learn from all of this? SOAP sucks. And using a certificate to sign a request is the root of all evil. OK, maybe that’s being a little too harsh, but I believe all of this is overkill for most things. For certain situations, though, where you need to be absolutely certain the message came from a trusted source, and that the contents of the message were not altered as it went through the internets, it’s actually not so horrible. There. I said it.

Comments