Search code examples
phpoauthaccess-tokenflickrhmacsha1

Getting an OAuth access token (not language specific) - same issue for Flickr and Tumblr, but not Twitter


I'm making the huge mistake of writing my own OAuth library and wrapper classes in PHP. Everything works wonderfully for Twitter's OAuth implementation, but I fail on signing the access_token step for both Tumblr and Flickr.

The ONLY difference in that step, is now I have oauth_token and oauth_verifier parameters. I'm using the Authorization header, and the only problem I can think of is that there are some character encoding issues, but I'm not sure.

Base string (broken for clarity):

POST&
http%3A%2F%2Fwww.flickr.com%2Fservices%2Foauth%2Faccess_token&
oauth_consumer_key%3Deeedfcd4c46a2c12080f58eb90a974d8
%26oauth_nonce%3D322190b47ca680d053338724ad1cc56d35d3e7b5
%26oauth_signature_method%3DHMAC-SHA1
%26oauth_timestamp%3D1322981994
%26oauth_token%3D72157628270097303-18aa378b4ab02af3
%26oauth_verifier%3Dec7811503fdd4380
%26oauth_version%3D1.0

This is exactly what Flickr expects (they tell me so in the error response), which leads me to believe the signature is the problem.

Authorization header (also broken for clarity):

Authorization: OAuth
oauth_consumer_key="eeedfcd4c46a2c12080f58eb90a974d8", 
oauth_nonce="322190b47ca680d053338724ad1cc56d35d3e7b5",
oauth_signature_method="HMAC-SHA1",
oauth_timestamp="1322981994",
oauth_token="72157628270097303-18aa378b4ab02af3",
oauth_verifier="ec7811503fdd4380",
oauth_version="1.0",
oauth_signature="LYJtgHetQWNKX3rtQlSs643FdWY%3D"

And Flickr's response:

oauth_problem=signature_invalid&
debug_sbs=POST&
    http%3A%2F%2Fwww.flickr.com%2Fservices%2Foauth%2Faccess_token&
    oauth_consumer_key%3Deeedfcd4c46a2c12080f58eb90a974d8
    %26oauth_nonce%3D322190b47ca680d053338724ad1cc56d35d3e7b5
    %26oauth_signature_method%3DHMAC-SHA1
    %26oauth_timestamp%3D1322981994
    %26oauth_token%3D72157628270097303-18aa378b4ab02af3
    %26oauth_verifier%3Dec7811503fdd4380
    %26oauth_version%3D1.0

There are no GET or POST parameters. Everything seems to be escaped correctly from what I see here. The signing works for the request_token step (and for Twitter, for ANY request). I've verified that my server clock is within a second of theirs. Am I missing something obvious? How would you go about diagnosing this?


Solution

  • I'll answer my own question.

    There were a few discrepancies between the different oauth service provider implementations:

    Twitter

    • Expects oauth_callback on request_token step
    • Doesn't return oauth_token_secret until access_token response
    • Therefore, there's an empty oauth_token_secret in signing the access_token request

    Flickr & Tumblr

    • Expect oauth_callback on authenticate (i.e. authorize) step
    • Return oauth_token_secret on request_token step (and expect you to remember it and use it to sign access_token request)

    Youtube (and other Google OAuth service providers):

    • Expects Google-proprietary "scope" on request_token step
    • Expects oauth_callback on authenticate (i.e. OAuthAuthorizeToken) step
    • Doesn't seem to like oauth_token passed in Authorization header in the access_token step (responds with "token invalid" due to required double-encoding in base string). Pass it in the post body or query string instead.