One thing that i did learn this past weekend is how much folks don’t really understand oAuth. This is understandable, since the oAuth site isn’t exactly the friendliest read ever. It was written by crypto programmers who, by nature, tend to be highly exacting and since they live in a world of obscurity, they kinda assume you live in that world too.
In all honesty, oAuth is surprisingly simple, once you understand a few things.
First off, let’s get rid of the various “consumer key”, “oauth tokens”, and “three legged” crap that you don’t understand. (Hell, i barely remember the difference between consumer keys and oauth tokens.) Instead, let’s say that there’s a seedy 1920’s gin joint at the edge of town that you want to go into.
Said gin joint might have a few ways to let you in. The first would be a door. You walk up, open it and go inside. This is general access since there’s no way to prove you’re you and not some random revenuer intent on shutting down the place to save us all from the savage demon liquor. So let’s up the ante on how you get in.
So, the “secret” knock isn’t really getting you anywhere. Instead you need some sort of secret. That’s where oAuth steps in. oAuth is all about a common, agreed upon way for two parties to say “Yeah, it’s me.” What’s more, there are even two levels of “me”. The first level is the equivalent of “Tony sent me.”
Let me sidetrack a bit more and talk about two part cryptography (i promise, it’ll be short.) Let’s say that in order to get into my gin joint, you’ve got to know a guy named “Tony”. Now, while you could walk up to the door and say “Tony sent me”, Tony may not appreciate having his name blurted out to the guy hiding in the trashcan. So you’re both clever and say “Nunzio’s cousin”. Both you and the doorman know Tony has a cousin named Nunzio, so he let’s you in. Next person walks up and say “Angelina’s brother”. Same deal, and since the guy in the trashcan has no idea who you’re all talking about, he’s stuck outside.
That, in effect, is what the “consumer key” and “shared secret” are about. Ok, first pet oAuth peeve of mine. Nobody knows what the hell “consumer key” means. Let’s call that “application key”, because it’s the key that your application will use to get in. This is the low level stuff and the way it works is you combine it, along with all the other bits of the URL and the “shared secret” into a “signature” value.
Right, you’re confused again, aren’t you. Ok, here’s an example:
Let’s say you want to use the Example.com API. It uses oAuth. So you go sign up to use it and you get the following back
Consumer Key: abcdefg
Shared Secret: 123456
and let’s say you want to get the info about Star Wars:
Well, oAuth requires a few extra parameters:
|Parameter||what the hell it is|
|oauth_consumer_key||The thing we sent ya.|
|oauth_timestamp||the UTC of when the request was made|
|oauth_nonce||Completely random value|
|oauth_signature_method||How you’re going to generate the signature|
A few notes: nonce is short for “nonsense” and it’s pretty much that. It’s just a random thing you’ve tossed in to make this request unique. You could use the same value all the time, but that’s a bit less secure. Likewise signature method could be anything from PLAINTEXT (very bad) to HMAC-RSA1. A pretty common signature method is HMAC-SHA1 which does a darn fine job of working on darn near everything.
Notice that i didn’t mention “shared secret” or “signature” in there. That’s because the shared secret is the fact that you and the doorman both know you’re talking about Tony. The signature bit is made up from all of the above (including the base URL, the arguments, and the above oauth_* junk) plus the hidden “shared secret”. All the oAuth libraries have some mechanism that allows you to do this signing, but naturally, they’re each different in how you send it in. Once the URL is signed, you wind up with something like:
(Ok, the timestamp and signature are a LOT longer than that, but hey, it’s an example, It’s not supposed to work.)
It doesn’t matter what order the arguments are in, so long as they stay in the same order when you send everything to the remote server.
The nice thing is that using just that, you don’t have to do anything hard. In fact, this is called “2 legged” authorization because there’s one “leg” where you got the secret knock info, and a second “leg” where you sent it back.
Now, let’s say you want to get into the joint and meet the head cheese. You need buy the extra heavy duty security for that and you need to ask permission to do that. Well, oAuth has the same sort of mechanism and it’s cleverly called the oAuth Request Token. (Arrgh! i HATE that! Look, i’m going to call it the “Protected Token” since that’s what you use it for.) To get it, you need to go through a few extra hoops.
For example, with the Example.com API, if you wanted to modify a user’s queue, you’ll need to get permission from that user, his or her ID, and the actual request token. While this request token doesn’t expire for Example.com (although the user can revoke it), some sites do timebomb the beasties, but getting a new one is always the same.
To get the request token, you use your Application Token (your consumer_key) and make a special request to the Access Token service, just like you would any other “general service” thing.
And you get back a one time use access “oauth_token” and secret.
You then use that one time access token for both sending the user to the “Ok, yeah, he’s with me” Example.com login/authorization page, as well as the immediately following request to get the official “good ’til whenever” token request:
(Yeah, my elementary counting skills tell me that’s more than “one time only” but, i’m trying to remove pedantry, not add to it.) That convoluted back and forth is called “three legged” auth for reasons that possibly involve the same sort of extra leg that was featured on Kiss of the Spider Woman, but i digress.
Once you have this oauth_token and secret from the “access_token” method, you can then use that, in addition to your consumer_key and secret, to do the double secret handshake knock to get to the nifty user info crap. Why the doubly elaborate dance? Because it’s even more secure and it means that the user (or system) could reject the access without having to make you start from square one. That’s why i refer to this as the “Protected Info” token, since it’s what you generally use it for.
signature = crypt(your_IP+"some string");
//Yes, my real code has a LOT more to it than that.
which makes a string based off of the address you’re connecting to ans scrambles it in some weird way. i then add it to the comment form and check that it matches the value i recalculate. Crappy? You bet, but surprisingly straight forward and effective. Kind of a “roll-your-own” AppID. Of course, there are lots of problems with something like that, and while it’s effective for small scale things, it doesn’t really scale horribly well since all your calls are going through you as a proxy. (Again, not a terribly difficult problem to solve, but one more layer you have to contend with.)
There. A bit more clear, now? In summary:
- Consumer_key = general use. oAuth_token = protected use.
- remember to pass the signature method the matching secrets for whatever tokens you use (and, obviously, don’t include the secret for whatever token you don’t use)
- Be sure to url encode any funky values in the signature (that took me a few tries to figure out).
- Be sure to url encode any funky values in the other arguments BEFORE you sign the URL