Wednesday, April 24, 2013

#photobucket API Authentication


I have been using REST APIs lately to communicate with various service providers via json.

One of them was particularly difficult to use: Photobucket.
Here are some of the reasons for this uncommon level of complexity:

There is no API
At this moment, previous sites such as http://photobucket.com/developer or http://developer.photobucket.com simply do not go anywhere but Photobucket generic start-up page
After querying the Photobucket team, it turns out that there is in fact an API and it is being updated so we should expect the developer area to work again in the near future.

Where is my API Key/Secret?
If you've already requested an access key in the past, good for you.
If not, you simply won't be able to use the API, unless you do one of the following:
- Contact Photobucket Facebook page (https://www.facebook.com/photobucket)
- Contact Photobucket Support site (http://support.photobucket.com/home)

Why am I having so much trouble authenticating?
So you have trying decrypting all documentation files and still no luck.
Make sure you are reading the documentation very carefully, cause you may be overseeing something.

The main requirements for first-step authentication are:
- Make an HTTP POST to http://api.photobucket.com/login/request
(Request URLs should NEVER contain an ending back slash)

- Do NOT use POSTFIELDS (POST body content). Add all parameters as a querystring on top of the URL

http://pic.photobucket.com/dev_help/WebHelpPublic/Content/Getting%20Started/Web%20Authentication.htm


Error #1 - Authentication failed nonce invalid
One of the parameters you have to send is "nonce". It is a unique value that must be send in all requests. It needs to be different for every user and every request. The idea is to create a completely random value that is guaranteed not to be repeated anytime soon. There are various ways to do this. One of them is using the time function, which retrieves the current timestamp. However, that alone might not be accepted by the service. So I usually add the md5 function on top of that (e.g. md5(time()) ).

Error #2 - Authentication failed timestamp invalid
Another parameter is the current timestamp in GMT. Fear not. Most frameworks have a function that tells this right away (for PHP it is the time() function).
There is quite a fuzz with this parameter, because sometimes the server timestamp is a bit off due to time zone differences, but since the time function retrieves the GMT value automatically, it shouldn't be a problem.
http://pic.pbsrc.com/dev_help/WebHelpPublic/Content/FAQ/FAQTech.htm?SearchType=Stem&Highlight=timestamp|Timestamp#Timestamp

Error #3 - Authentication failed signature check failed
This is by far the most irritating error. We have no idea what is happening because creating the base string and the signature is so complex and the documentation is not completely transparent.

Some pointers:

- urlencode or rawurlencode your parameters

- "Sort the parameters by name lexicographically" which means that all parameters MUST be in alphabetic order or you will get this error

- base 64 encode your signature after running the hmac sha1 algorithm

- set rawurlencode to true in the hash_hmac function

Complete anonymous access request function (from my Photobucket plugin)
function photobucket_stepone_requesttoken()
{
    //make anonymous post request
    $url = "http://api.photobucket.com/login/request";
    
    //gather up parameters in the right order
    $parameters = array(
        'format' => 'json',
        'oauth_consumer_key' => rawurlencode(get_option('photobucket-apiid')),
        'oauth_nonce' => rawurlencode(md5(time())),
        'oauth_signature_method' => rawurlencode('HMAC-SHA1'),
        'oauth_timestamp' => rawurlencode(time()),
        'oauth_version' => rawurlencode('1.0')
    );
    
    //build the query string
    $httpquery = http_build_query($parameters);

    //create the base string
    $basestring = rawurlencode("POST") . '&' . rawurlencode($url) . '&' . rawurlencode($httpquery);

    //create the signature
    $sign = base64_encode(hash_hmac("sha1", $basestring, get_option('photobucket-apisecret') . "&", true));

    //add the parameters and the signature to the url
    $url = $url . '?' . httpquery . '&oauth_signature=' . rawurlencode($sign);

    //make the post
    $result = photobucket_makehttprequest($url, "POST");
    return $result;
}


Main Consumer Authentication Documentation
http://pic.photobucket.com/dev_help/WebHelpPublic/Content/Getting%20Started/Consumer%20Authentication.htm


See my question in stack overflow

No comments:

Post a Comment