OAuth, Twitter, and LiveCode




I’m trying to build an app in LiveCode that uses Twitter’s OAuth dance to allow users of the app to post tweets to their Twitter account. I’ve set up the app in Application Management and have the Consumer Key & Secret, as well as my own Access Token & Secret. I can get my app to fetch a Request Token and Secret (Step 1, according to this doc: https://dev.twitter.com/web/sign-in/implementing). I can launch a browser window within my app and have the user sign into their Twitter account (Step 2). The browser then redirects to my app’s callback URL. The app can fetch the oauth_verifier. But when I try to get the app to convert the Request Token to an Access Token (Step 3), I get the following error: “Invalid request token.” The documentation says that I need to replace my initial Access Token with the Request Token when the app generates the oauth_signature for the Authorization Header of the POST in Step 3.

I’ve tried replacing my own Access Token as part of the signature generation process with the new Request Token. I’ve also tried substituting my own Access Token secret with the Request Token Secret returned in Step 1 with the Request Token, even though the documentation doesn’t specify doing this.

Am I missing something? Any insights would be really appreciated.

For what it’s worth here’s the LiveCode script that generates the Authorization Header for the POST command:

local sTwitter

private function arrayMerge pArray1,pArray2
local pArray
put pArray1 into pArray
repeat for each line tKey in the keys of pArray2
put pArray2[tKey] into pArray[tKey]
end repeat
return pArray
end arrayMerge

private function buildBaseString pBaseUrl, pMethod,pParams
local tResult
get the keys of pParams
sort lines of it
repeat for each line tKey in it
put tKey & “%3D” & urlencode(pParams[tKey]) & “%26” after tResult
end repeat
put char 1 to -4 of tResult into tResult
return pMethod & “&” & urlencode(pBaseUrl) & “&” & tResult
end buildBaseString

private function hmacSha1 pMsg, pKey
if length(pKey) > 64 then put sha1digest(pKey) into pKey
repeat 64 - length(pKey)
put null after pKey
end repeat
repeat for each byte c in pKey
put numtobyte(bytetonum© bitXor 54) after ipad
put numtobyte(bytetonum© bitXor 92) after opad
end repeat
return sha1digest(opad & sha1digest(ipad & pMsg))
end hmacSha1

private function buildAuthorizationHeader pOAuth
local tResult
put "Authorization: OAuth " into tResult
repeat for each line tKey in the keys of pOAuth
put tKey & “=” & quote & urlencode(pOAuth[tKey]) & quote & comma & space after tResult
end repeat
return char 1 to -3 of tResult
end buildAuthorizationHeader

on twitter.set pOAT, pOATS, pCK, pCS
put pOAT into sTwitter[“oauth_access_token”]
put pOATS into sTwitter[“oauth_access_token_secret”]
put pCK into sTwitter[“consumer_key”]
put pCS into sTwitter[“consumer_secret”]
put “https://api.twitter.com/” into sTwitter[“base_url”]
end twitter.set

private function twitter.http pMethod, pUrl
local tUrlParts
put pUrl into tUrlParts
split tUrlParts by “?”
– tUrlParts[1] : path, tUrlParts[2]: query

local tUrlArguments
put tUrlParts[2] into tUrlArguments
split tUrlArguments by “&” and “=”

local tFullUrl
put sTwitter[“base_url”] & pUrl into tFullUrl

local tBaseUrl
put sTwitter[“base_url”] & tUrlParts[1] into tBaseUrl

local tTime
put the internet date into tTime
convert tTime to seconds

local tOAuth
put “1.0” into tOAuth[“oauth_version”]
put sTwitter[“consumer_key”] into tOAuth[“oauth_consumer_key”]
put tTime into tOAuth[“oauth_nonce”]
put “HMAC-SHA1” into tOAuth[“oauth_signature_method”]
put sTwitter[“oauth_access_token”] into tOAuth[“oauth_token”]
put tTime into tOAuth[“oauth_timestamp”]

local tBaseInfo
put buildBaseString(tBaseUrl,pMethod,arrayMerge(tOAuth,tUrlArguments)) into tBaseInfo

local tCompositeKey
put urlencode(sTwitter[“consumer_secret”]) & “&” & urlencode(sTwitter[“oauth_access_token_secret”]) into tCompositeKey
put base64Encode(hmacSha1( tBaseInfo, tCompositeKey)) into tOAuth[“oauth_signature”]
set the httpHeaders to buildAuthorizationHeader(tOAuth)
if pMethod is “POST” then
post “” to url(tFullUrl)
get url(tFullUrl)
end if
return it
end twitter.http

function twitter.get pUrl
return twitter.http(“GET”, pUrl)
end twitter.get

function twitter.post pUrl
return twitter.http(“POST”, pUrl)
end twitter.post

function twitter.URLEncode pText
local tText
put URLEncode(pText) into tText
replace “+” with “%20” in tText
return tText
end twitter.URLEncode

And here’s the code for Step 3:

on getAccessToken
// answer tToken
put tToken into tOAuth[“oauth_token”]
set itemDel to "&"
put item 2 of line 2 of field “fldTweets” into tSecret
delete character 1 to 19 of tSecret
put tSecret into sTwitter[“oauth_access_token_secret”]

put twitter.post(“oauth/access_token?oauth_verifier=” & tVerifier) & return before field "fldTweets"
end getAccessToken


Problem solved. The script was using my access token in Step 3 of the OAuth dance, instead of the request token. Now I’m able to get the user-specific access token and secret in Step 3.