Simple Oauth is not simple

Nagesh Bansal
3 min readNov 16, 2022

This post is about how Oauth makes life painful. I spent hours debugging something that should have barely taken a few minutes.

Back story

We recently started working on Breeze, a Notion based Social Media Calendar. One of the features that users want most is analytics. They want to see what is performing well and what is not. Fair enough.

I set out on building the same. Right now, the focus was to make it work for Twitter and later on add the others. Going into a little technical details, Twitter has two API versions, v1.1 and v2. While v1.1 uses Oauth authentication, v2 uses Oauth2. When we started building we had started with v2 APIs only to realise that the v2 APIs does not have media upload capability, meaning, you can only send text tweets.

After 1 week of struggle, we moved to v1.1 APIs. This is where the initial struggle started. Testing APIs with Oauth in Postman was already proving to be a struggle but then when finally the APIs started working, the code in Ruby gave up. I just generated the exact same code and tested it with Ruby

This is when I gave up using this and started using the Twitter gem. All this is going well and we were finally able to successfully launch Twitter to Notion.

Moving to analytics

So when the request for analytics came in, I thought, maybe we can use the same gem and get things done. Or so you thought. Beat this: v1.1 APIs only give you number of likes and retweets. If you want more details, you need to use v2 APIs. And since the authentication was done with Oauth, this particular v2 API works with Oauth.

So this time, there was no workaround(because the Twitter gem is based on v1.1 APIs). I had to power through Oauth. I did some digging in the Twitter API and saw that they used the simple_oauth Twitter gem.

I did a quick installation and followed their footsteps in generating the simple oauth header. Do you want to see the results:

First: The header that works for the Twitter gem

OAuth oauth_consumer_key="consumer_key", oauth_nonce="92fa00fe2a368143df1eff3c5a17feac", oauth_signature="CTrauS2Brh9uYVlYa8tpkT%2B9U8g%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1668604313", oauth_token="access_token", oauth_version="1.0"

Second: The header that does not work for me

OAuth oauth_consumer_key="consumer_key", oauth_token="access_token", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1668529108", oauth_nonce="ABCDEFGHIJKLMNOPQRSTUVWXYZ123456", oauth_version="1.0", oauth_signature="s%2BmVIEG71GUUto6dZr77HHtRt4U%3D"

After playing spot the difference for over 2 hours, I was about to give up. I had been following the exact same method, but to no luck

The solution

If you try to google, you will only find a few examples. This gist was the best that I could find. Finally, like a true hacker, this is what I did. I extended the Twitter gem which was already working and used it to send v2 requests with Oauth.

Not proud of the hack, but I don’t think it was worth spending any more hours on something that should have worked easily in the first place. 😅

--

--