Continuing on from Part 1.
Update: I got the order of the parameters wrong below so my example signature was incorrect. I have now fixed that.
Authenticating with Flickr
The process of authenticating with Flickr is a 3 stage process.
First you call the request token url and get back a request token and a request token secret.
Second you redirect the user to the authorize url and they approve your authentication request. Then they are either presented with a verification code on the screen, or the verification code is appended to your callback url.
Thirdly, once you have the verifier code you call the access token url to get your final access token.
Step 1 - Request a Request Token?
I have created an API key and shared secret especially for this tutorial which I will use below. Feel free to use this API key for testing, but do not use it for development - go get your own. The reason I provide this functionality here is so that you can test your signature generation function - if you use my api key and shared secret you should get exactly the same signature.
This is the bit that catches most people out, and so I will go through this step by step.
First, you need to get your oauth parameters set.
Nonce = "C2F26CD5C075BA9050AD8EE90644CF29"
Consumer Key = "768fe946d252b119746fda82e1599980"
Version = "1.0"
Signature Method = "HMAC-SHA1"
Callback URL = "http://www.wackylabs.net/oauth/test"
Consumer Secret = "1a3c208e172d3edc"
To generate a SHA1 signature you require two things. First a key. For OAuth the signature key is made up of two parts, your consumer secret, and your token secret (for whichever token you are using at the time). As this is the first stage you have neither, so your token secret is simply an empty string.
Key = Consumer Secret + "&" + Token Secret
The second part of the SHA1 signature generation is the base string. For OAuth the base string is made up of three parts, the HTTP method, the URL endpoint you are using, and the parameters you are sending.
OAuth Parameter Encoding - Not your normal encoding
However the key to this part is the encoding. OAuth uses an encoding which is very similar to URL encoding (i.e. replacing parts of a URL string with %NN where NN is the hex number for that character). However it is different, in that more things are encoded when using OAuth encoding (e.g. spaces can be encoded as a "+" symbol in URL encoding, but in OAuth must be encoded as "%20".
OAuth encoding only allows letters, numbers and the following 4 punctuation marks: "_", "-", "." and "~". All other characters must be encoded.
You will likely not notice the difference until you come to call methods that include things like title etc, as most parameters will not contain data that is encoded differently with the above compared to standard url encoding.
A little post I found covering some of the differences is here: http://www.marcworrell.com/article-2943-en.html
Bringing the Base String Together
For the first part of the base string then encoding doesn't matter, as it will be either "GET" or "POST". This is the same once encoded :)
For the second part your request url endpoint will get encoded to something like this:
For the final part of the base string you need to concatenate the encoded parameters and values as if you were generating a URL (except you are using oauth encoding), and then encode the whole lot again. The parameters must also be sorted in alphabetical order. Note, technically you are encoding both the parameter name and value, but as letters and the "_" character do not change after encoding the parameter names look the same after encoding.
So first you generate the following string (ignore carriage returns):
And then you encode it again (again, ignore carriage returns):
Before finally adding it all together as part1 + "&" + part2 + "&" + part3 to give a final base string like so:
Base String = "GET&http%3A%2F%2Fwww.flickr.com%2Fservices%2Foauth%2Frequest_token&
Finally you are ready to use whatever SHA1 code your programming language provides to generate the signature.
In .Net this might look like this:
byte keyBytes = System.Text.Encoding.UTF8.GetBytes(key); System.Security.Cryptography.HMACSHA1 sha1 = new System.Security.Cryptography.HMACSHA1(keyBytes); byte signatureBytes = sha1.ComputeHash(System.Text.Encoding.UTF8.GetBytes(baseString)); string signature = Convert.ToBase64String(signatureBytes);
In PHP this might look like this:
$signature = base64_encode(hash_hmac('sha1', $baseString, $key, true));
The important thing to notice with both of these examples is that you are returning binary data from the signature method, and then base 64 encoding this data. The hash_hmac() method in php can also return string data, but this will not work, so the fourth parameter is required to be set to true to return the raw binary data instead.
Using the above methods, and the above sample parameters the final signature is as follows:
Signature = "0fhNGlzpFNAsTme/hDfUb5HPB5U="
Finally Request your Token
Now you have your signature you can create the url to actually request your request token with.
Note, when generating your URL you must again encode everything (including the new oauth_signature parameter) but you do not need to use the strict OAuth encoding, but can return to normal url encoding.
URL = "http://www.flickr.com/services/oauth/request_token?oauth_callback=http%3A%2F%2Fwww.wackylabs.net%2Foauth%2Ftest&oauth_consumer_key=768fe946d252b119746fda82e1599980&oauth_nonce=C2F26CD5C075BA9050AD8EE90644CF29&oauth_timestamp=1316657628&oauth_signature_method=HMAC-SHA1&oauth_version=1.0&oauth_signature=0fhNGlzpFNAsTme%2FhDfUb5HPB5U%3D"
It is possible, rather than putting everything in the query string as above to put all of your oauth parameters in a special HTTP header instead.
OAuth parameter put into the Authorization header should be encoded using oauth encoding as for the generation of the base string. However the parameter values are enclosed in double quotes (") and each parameter is separated by a comma.
All OAuth parameters then need removing from the request URL, in this case as they are ALL oauth parameter you are just left with the request_token endpoint.
So the header would look like this (line breaks and other white space are optional between the parameters in the header):
OAuth oauth_consumer_key="768fe946d252b119746fda82e1599980", oauth_timestamp="1316657628", oauth_nonce="C2F26CD5C075BA9050AD8EE90644CF29", oauth_signature_method="HMAC-SHA1", oauth_signature="0fhNGlzpFNAsTme%2FhDfUb5HPB5U%3D", oauth_callback_url="http%3A%2F%2Fwww.wackylabs.net%2Foauth%2Ftest", oauth_version="1.0"
Note: DO NOT send oauth parameters in both the Authoriszation header and the query string (or body) as Flickr thinks you are sending each parameter twice and will generate a different signature from you (unless you include all the parameters twice when you generate the signature, but that's just silly).
In the next part I will look at error handling.