Implementing Sign in with Twitter from scratch
When I made my final project for Flatiron School, Bikeways, having Sign in with Twitter available was very important to me because the #bikeNYC community has a very active, lively Twitter presence. I didn’t know it when I started, but getting it working became one of the biggest challenges I had to overcome on the project.
To implement Sign in with Twitter, Twitter requires that I use OAuth. The benefit of using OAuth is that my app doesn’t need to know your Twitter password, but you can still use your Twitter credentials to log in. However, for whatever reason, Twitter is still using OAuth 1.0a for this process, not the newer OAuth 2.0. This means we have to do a very intricate dance of AJAX requests between my app and Twitter’s API:
- Send a signed
POST
request toapi.twitter.com/oauth/request_token
. This request contains acallback_url
, which Twitter will use later in Step 4. If everything goes OK, Twitter will respond with a token and token secret. - At this point, my ‘Login with Twitter’ button becomes available. When it’s clicked, the user is directed to
api.twitter.com/oauth/authenticate
, and the token from Step 1 is included in the URL parameters. - Now, Twitter will handle the login. If the user hasn’t already authorized my app, Twitter will display its login screen and the user can enter credentials. If that’s done already, Twitter will just skip to the next step.
- Once login is complete, Twitter will actually redirect the user back to my app’s
callback_url
, which I specified in Step 1. The URL parameters Twitter sends me will contain the sameoauth_token
I got back in Step 2, and anoauth_verifier
which I can use in the next step. - When I get this response back, I must send another signed
POST
request, this time toapi.twitter.com/oauth/access_token
. The request will contain theoauth_verifier
I obtained in the previous step. - If the planets are aligned properly, I’ll finally get an
oauth_token_secret
in the response. This is my digital wristband that proves that I’ve been admitted to the party. I should be able to use theoauth_token_secret
for future Twitter API requests without having to do this dance again.
Think that’s enough complication? Not even close. There are at least 3 things that add complication to this process:
- All the parameters must be percent encoded, properly, or it won’t work.
- All the requests I send to Twitter must be signed. A signature is a long string containing all the other parameters of the request, percent encoded, sorted in a specific way, and then encrypted using HMAC-SHA1. Maybe I’ll go into more detail about that in a future blog post.
- If I get something wrong, Twitter’s API responses are quite opaque. They definitely don’t help much.
I handled most of this using my Ruby on Rails backend, though of course my React front-end had to handle the part where Twitter redirects the user back to my app. I was able to pull out the URL params using the React Router location props, which I mentioned in my previous post.
Here are the three main Twitter documents I used, that explain all of this in excruciating detail:
Implementing Sign in with Twitter
I did use the Ruby OAuth gem, but only for the OAuth::Helper
methods to percent encode my strings properly. (I also used its parse_header
method to turn the incoming params into a hash.) But that’s it. I didn’t use any of its built-in methods for creating signatures or obtaining tokens. This is partly because I found the documentation difficult to understand, and partly because I knew it would be a great learning exercise to do it all manually.