For a while I’ve wanted to play with OAuth and as we’re looking to do a project that involves video uploads and streaming at work, I’ve been tinkering with the YouTube API lately. What I want to do is let users upload video to our site using their own YouTube accounts, without asking for their username and password. The tools to make this an easy job is readily available, but combining them took some investigation.
I will here go through the process of obtaining an access token from YouTube that can be used to query the API on behalf of the user. I’ll use Ruby on Rails in my example, but this is certainly not a requirement. I’m assuming you have some knowledge about how OAuth works. If not, please visit the OAuth site and read up on it. Its really the bee’s knees!
Step One, the request token
In order to initiate the authorization we need a request token. Following the documentation for the Google Data API for YouTube we see that we first need to register our site with Google in order to obtain a key and secret needed for using the OAuth protocol.
Step Zero, registering your domain
Visit Googles Manage Your Domains page, add your domain and verify it according to the instructions on that page. I set up a Heroku site for my testing and this example, http://runeb-oauth.heroku.com, since http://localhost is impossible to verify.
Once your domain is verified you have to set up a Target URL path prefix. This is just the beginning of what ever URL Google should redirect to after your user is at Googles login/authorization page, as a safety measure. I set this to simply http://runeb-oauth.heroku.com.
You should now have a OAuth Consumer Key and a OAuth Consumer Secret. Perfect!
Step One, the request token
Picking up where we left off at step one in the YouTube API docs, we quickly see that OAuth is complicated stuff. We dont want to go about implementing HMAC-SHA1 signature algorithms and all that jazz.
gem install oauth
Whee! You can now forget about the specific details of the OAuth protocol, just make sure you know whats going on and how OAuth works. I really mean it! If you just copy-paste this code, it’ll definitely bite your ass in the future. Know what you’re doing, and why you’re doing it. And keep in mind this is just an example.
OK. Time for some code!
Following the usage example from the oauth gem website, we know we need an instance of OAuth::Consumer, and it needs to know what site we’re talking with and at what paths we’ll find the token-services we need. With that instance we get a method for retrieving the request token, get_request_token, but Google also requires a Google-specific parameter with this request called scope, which limits the access token to a certain scope within Google. In this (YouTube Data API) case, it needs to be set to http://gdata.youtube.com. For a full list of possible values, visit Googles own list.
We thus end up with this code for getting a request token and a URL for authorizing it:
Step Two, authorize the request token
If you visit the URL in request_token.authorize_url you will be presented with a login for YouTube if not already logged in, and buttons for authorizing or rejecting the token. Once the user clicks the “Allow access” button, the token will be an authorized request token. This can then be swapped for an access token which is used to query the API on behalf of the user, but here the YouTube API docs fail us.
In order to get the access token we need to pass along an oauth_verifier as a parameter, not mentioned in the docs. We get this parameter as a GET parameter in the redirect Google makes back to our site. And in order to get Google to redirect back to us, we need to specify oauth_callback when we fetch the request token. Here is our revised code:
Now when the user clicks “Allow access” she will be redirected to http://runeb-oauth.heroku.com/session/create with the token as the parameter oauth_token and a new parameter called oauth_verifier. The docs says oauth_token_secret, but this is not passed, so keep track of the secret you got when fetching the request token before redirecting the user away (their session is a good bet).
In the action for the callback url you can now fetch the access token using the secret you’ve kept, plus the token and verifier passed in and start calling the YouTube API on behalf of the user. The pieces are in place, and we can make a little Rails app demonstrating the whole thing:
git init && git add . && git commit -a -m "YouTube OAuth example"
gem install heroku
heroku create runeb-oauth
└─[$]> git push heroku master
Counting objects: 16, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (8/8), done.
Writing objects: 100% (9/9), 1.46 KiB, done.
Total 9 (delta 4), reused 0 (delta 0)
-----> Heroku receiving push
-----> Rails app detected
Compiled slug size is 896K
-----> Launching...... done
http://runeb-oauth.heroku.com deployed to Heroku
To git@heroku.com:runeb-oauth.git
0ad0387..b766f7b master -> master
Phew! That should cover everything! Now you can start actually playing with the YouTube API using OAuth. As you can see, the access token instance gives you handy methods for including the needed authorization headers for the HTTP request to YouTube. Take any URL you find in the YouTube API docs, and fetch them using the methods available to you on this instance. Check the docs for the oauth gem for more information on this.
The access token never expires on its own, so you could store it (or rather, the token and the secret) in the database and have it persist across sessions. The only way it’ll become invalid (as I can see) is if the user revokes its authorization from her YouTube account (so you should probably have some validity-check somewhere).
I’ll try to follow up with examples of video upload and more if we decide to do this project.
You can see the example application in this blogpost at http://runeb-oauth.heroku.com, log in and try it (AKA do you trust me?).
Sources not mentioned elsewhere in the post
400 Bad Request on get_access_token
Using Google OAuth in Ruby on Rails Sites