18th
Secure and Signed AuthSub Requests in Ruby
I pulled the trigger in my last blog post about solving Google AuthSub’s warning. It solved only half the problem - the not-showing-the-warning half. I was too quick to assume it would work since Google returned a token. Actually performing GET on the contacts feed would yield me a 401 Unauthorized.
So, what did I get wrong? A few things.
Firstly, I didn’t have to set the sig in the request authorization URL. A simple secure=1 would have been sufficient. I confused this concept with other request schemes like Facebook’s which signs the request and appends the sig to the URL parameters.
Secondly, for secure AuthSub requests, you need to set special signed headers. Regular non-secure AuthSub requests only need a short header.
Authorization: AuthSub token="COy2q9qdGRDWm7iMAm"
However, if you want secure requests, you need to sign the request. It’ll look something like this.
Authorization: AuthSub token="COy2q9qdGRDWm7iMAm" sigalg="rsa-sha1" data="GET http://www.google.com/m8/feeds/contacts/default/thin?max-results=200 1237370831 18094396511823580603" sig="XOQNfKpQ8VPCN2Yp+Zt="
I thought I nailed it but it still returned me 401 Unauthorized. I downloaded the Python GData client to compare the sig values and indeed the sig I generated was off.
So the final piece of the puzzle is how do I correctly generate the signature. google-authsub (and my contacts commit) got it wrong. This is what it was doing:
digest = OpenSSL::Digest::SHA1.new(data).hexdigest
sig = [@@pkey.private_encrypt(digest)].pack("m") #Base64 encode
After much googling, I found the answer. Immad Akhund posted the solution on the Google Data Protocol mailing list in June 2008. The correct way to sign data is to use the OpenSSL::PKey::RSA#sign method and remove the newlines after Base64 encoding.
sig = @@pkey.sign(OpenSSL::Digest::SHA1.new, data)
sig = [sig].pack("m").gsub(/\n/, "") #Base64 encode
So, there you have it. I’ve pushed a new commit to the contacts library with all the fixes. I’ll be forking google-authsub and pushing fixes there too in hopes that another person wouldn’t need to spend a day figuring it out like I did.