Archived Forum Post

Index of archived forum posts

Question:

Twitter oAuth 401 error

Sep 01 '14 at 08:56

Hi

I'm trying to connect to twitter from our desktop application

The Stage 1 goes OK and I get the page with the PIN code but when I try and do stage 2 I keep getting 401 errors.

Here is the last log

Thanks

ChilkatLog:
  PostUrlEncoded:
    DllDate: Aug  1 2014
    ChilkatVersion: 9.5.0.43
    UnlockPrefix: xxxxxx
    Username: xxxxxxx
    Architecture: Little Endian; 32-bit
    Language: ActiveX
    VerboseLogging: 0
    url: https://api.twitter.com/oauth/request_token
    httpRequest:
      httpVersion: 1.1
      verb: POST
      path: /oauth/request_token
      contentType: application/x-www-form-urlencoded
      charset: windows-1252
      sendCharset: 0
      mimeHeader: 
    --httpRequest
    fullRequest:
      a_synchronousRequest:
        generateRequest:
          httpRequestGenStartLine:
            genStartLine:
              startLine: POST /oauth/request_token HTTP/1.1
            --genStartLine
          --httpRequestGenStartLine
          addCookies:
            Not auto-adding cookies.
          --addCookies
          addOAuth1Header:
            oauth_timestamp: 1407945069
            oauth_nonce: u8TV1mjyTbVazntE9XYO0UZ/f3M=
            oauth_consumer_key: z3UJ8oZOtPL46NgQIR5z4huc3
            oauth_verifier: 1604339
            oauth_callback: oob
            oauth_signature_method: HMAC-SHA1
            fullUrl: https://api.twitter.com/oauth/request_token
          --addOAuth1Header
          sortedParams:
            oauth_hdr: oauth_callback
            oauth_hdr: oauth_consumer_key
            oauth_hdr: oauth_nonce
            oauth_hdr: oauth_signature_method
            oauth_hdr: oauth_timestamp
            oauth_hdr: oauth_token
            oauth_hdr: oauth_verifier
            oauth_hdr: oauth_version
          --sortedParams
          baseStringURI: https://api.twitter.com/oauth/request_token
          baseStringURI_encoded: https%3A%2F%2Fapi.twitter.com%2Foauth%2Frequest_token
          normalizedParams: oauth_callback=oob&oauth_consumer_key=z3UJ8oZOtPL46NgQIR5z4huc3&oauth_nonce=u8TV1mjyTbVazntE9XYO0UZ%2Ff3M%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1407945069&oauth_token=Szw7OBKWmGYpnfWx3vGttivWNxv4ZYSBvKUJF8woU&oauth_verifier=1604339&oauth_version=1.0
          normalizedParams_encoded: oauth_callback%3Doob%26oauth_consumer_key%3Dz3UJ8oZOtPL46NgQIR5z4huc3%26oauth_nonce%3Du8TV1mjyTbVazntE9XYO0UZ%252Ff3M%253D%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1407945069%26oauth_token%3DSzw7OBKWmGYpnfWx3vGttivWNxv4ZYSBvKUJF8woU%26oauth_verifier%3D1604339%26oauth_version%3D1.0
          signatureBaseString: POST&https%3A%2F%2Fapi.twitter.com%2Foauth%2Frequest_token&oauth_callback%3Doob%26oauth_consumer_key%3Dz3UJ8oZOtPL46NgQIR5z4huc3%26oauth_nonce%3Du8TV1mjyTbVazntE9XYO0UZ%252Ff3M%253D%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1407945069%26oauth_token%3DSzw7OBKWmGYpnfWx3vGttivWNxv4ZYSBvKUJF8woU%26oauth_verifier%3D1604339%26oauth_version%3D1.0
          oauth_signature: RazS4H0JxFDs2ij/mCNDFINlA8A=
        --generateRequest
      --a_synchronousRequest
      fullHttpRequest:
        domain: api.twitter.com
        port: 443
        ssl: 1
        openHttpConnection:
          Using existing connection.
        --openHttpConnection
        connectTime: Elapsed time: 0 millisec
        sendRequestHeader:
          sendHeaderElapsedMs: 16
        --sendRequestHeader
        sendRequestBody:
          sendBodyElapsedMs: 0
        --sendRequestBody
        statusCode: 401
        statusText: Unauthorized
        readResponseBody:
          contentLength: 44
        --readResponseBody
      --fullHttpRequest
      computeAuthorization:
        No useful WWW-Authenticate response header was found.
      --computeAuthorization
      computeAuthorization failed (2).
      success: 0
    --fullRequest
  --PostUrlEncoded
  Failed.
--ChilkatLog

Answer

OK to ask this a slightly different way.

Is there anyone on here using Chilkat HTTP oAuth and is managing to successfully sign into twitter using 'any account' (by that I mean any account other than the account that created the twitter 'app')

If the answer is yes please can you post a code snippet as I just can't get past sending back the PIN stage

Thanks

PS yes I am following the example here http://www.example-code.com/vb/http_twitter_pin_authorization2.asp


Answer

OK I've got a bit further but am now really tearing my hair out on this one.

My initial mistake was to assume that the token/secret that came back in part one is important and I should set those properties but it turns out I shouldn't

I am now in the situation where the stage 1 and stage 2 work in the sense I get an OK and auth/secrect tokens from stage 2

However I can't use these to post a tweet on the timeline and get a 401 ewrror

I've tried many many combinations without success

The app ha "Read, Write and Direct Access" permissions

I've pasted my class below

I'm creating/destroying the http objects in desperation to ensure there is nothing 'left over' at each stage

I've found this about encoding https://dev.twitter.com/discussions/11280

and this about Expect: 100-continue https://dev.twitter.com/discussions/15408

I'm really struggling with this now and some help would be GREATLY appreciated

Use ChilkatAx-9.5.0-win32.pkg
Use ChilkatUnlockCodes.pkg

Struct tdTwitterErrorStatus
    Boolean bSuccess
    Integer iStatusCode
    String sLastErrorText
End_Struct

Class cTwitterHandler is a cObject

    Procedure Construct_Object
        Forward Send Construct_Object

        Property String psOAuthConsumerKey      "z3UJ8oZOtPL46NgQIR5z4huc3"    
        Property String psOAuthConsumerSecret   "PPaym9K8tk5cCeLDjY4bzHDXYGnjXQMyq7vcKka5xpE3tptVuF"    
        Property String psOAuthToken            ""    
        Property String psOAuthTokenSecret      ""   
        Property String psOAuthVerifier         ""    
    End_Procedure

    Function Stage1AuthTwitter Returns String
        Variant vRespCOMObj
        tdTwitterErrorStatus tTwitterErrorStatus
        String sAuthToken sAuthTokenSecret sAuthCbConfirmed sURL
        Boolean bOK
        Handle hoHTTP hoHTTPReq hoHTTPResp

        Get Create (RefClass(cComChilkatHttp)) to hoHTTP
        Get Create (RefClass(cComChilkatHttpRequest)) to hoHTTPReq
        Get Create (RefClass(cComChilkatHttpResponse)) to hoHTTPResp

        Get ComUnlockComponent      of hoHTTP UNLOCK_CHILKAT_HTTP to bOK
        Set ComOAuth1               of hoHTTP to 1
        Set ComOAuthConsumerKey     of hoHTTP to (psOAuthConsumerKey(Self))
        Set ComOAuthConsumerSecret  of hoHTTP to (psOAuthConsumerSecret(Self))    
        Get ComPostUrlEncoded       of hoHTTP "https://api.twitter.com/oauth/request_token" (pvComObject(hoHTTPReq)) to vRespCOMObj

        Get TestErrorStatusOfLastResponseObjectCall vRespCOMObj hoHTTP hoHTTPResp to tTwitterErrorStatus

        If (tTwitterErrorStatus.bSuccess) Begin 
            Get ComUrlEncParamValue of hoHTTPResp tTwitterErrorStatus.sLastErrorText "oauth_token" to sAuthToken
            Move ("https://api.twitter.com/oauth/authorize?oauth_token="+sAuthToken) to sURL
        End

        Send Destroy of hoHTTP
        Send Destroy of hoHTTPReq
        Send Destroy of hoHTTPResp

        Function_Return sURL    // the caller does a Send ComNavigate sURL 0 0 0 0   to show the PIN page
    End_Function

    Function Stage2AuthTwitter String sPin Returns Boolean
        Variant vRespCOMObj
        tdTwitterErrorStatus tTwitterErrorStatus
        String sAuthToken sAuthTokenSecret 
        Boolean bOK
        Handle hoHTTP hoHTTPReq hoHTTPResp

        Get Create (RefClass(cComChilkatHttp)) to hoHTTP
        Get Create (RefClass(cComChilkatHttpRequest)) to hoHTTPReq
        Get Create (RefClass(cComChilkatHttpResponse)) to hoHTTPResp

        Set psOAuthVerifier to sPin
        Get ComUnlockComponent      of hoHTTP UNLOCK_CHILKAT_HTTP to bOK
        Set ComOAuth1               of hoHTTP to 1
        Set ComOAuthConsumerKey     of hoHTTP to (psOAuthConsumerKey(Self))
        Set ComOAuthConsumerSecret  of hoHTTP to (psOAuthConsumerSecret(Self))    
        Set ComOAuthVerifier        of hoHTTP to (psOAuthVerifier(Self))

        Get ComPostUrlEncoded       of hoHTTP "https://api.twitter.com/oauth/request_token" (pvComObject(hoHTTPReq)) to vRespCOMObj

        Get TestErrorStatusOfLastResponseObjectCall vRespCOMObj hoHTTP hoHTTPResp to tTwitterErrorStatus

        If (tTwitterErrorStatus.bSuccess) Begin 
            Get ComUrlEncParamValue of hoHTTPResp tTwitterErrorStatus.sLastErrorText "oauth_token" to sAuthToken
            Get ComUrlEncParamValue of hoHTTPResp tTwitterErrorStatus.sLastErrorText "oauth_token_secret" to sAuthTokenSecret
            Set psOAuthToken to sAuthToken    
            Set psOAuthTokenSecret to sAuthTokenSecret   
        End

        Send Destroy of hoHTTP
        Send Destroy of hoHTTPReq
        Send Destroy of hoHTTPResp

        Function_Return tTwitterErrorStatus.bSuccess
    End_Function

    Function TestErrorStatusOfLastResponseObjectCall Variant vRespCOMObj Handle hoHTTP Handle hoHTTPResponse Returns tdTwitterErrorStatus
        tdTwitterErrorStatus tTwitterErrorStatus

        If (IsNullComObject(vRespCOMObj)) Begin 
            Get ComLastErrorText of hoHTTP to tTwitterErrorStatus.sLastErrorText
        End
        Else Begin 
            Set pvComObject of hoHTTPResponse to vRespCOMObj
            Get ComStatusCode of hoHTTPResponse to tTwitterErrorStatus.iStatusCode
            If (tTwitterErrorStatus.iStatusCode=200) Begin 
                Move True to tTwitterErrorStatus.bSuccess
                Get ComBodyStr of hoHTTPResponse to tTwitterErrorStatus.sLastErrorText        
            End
            Else Begin 
                Get ComLastErrorText of hoHTTP to tTwitterErrorStatus.sLastErrorText
            End
        End

        Function_Return tTwitterErrorStatus
    End_Function

    Function PostTweetToOwnTimeLine String sTweet Returns tdTwitterErrorStatus
        Variant vRespCOMObj
        tdTwitterErrorStatus tTwitterErrorStatus
        Boolean bOK
        Handle hoHTTP hoHTTPReq hoHTTPResp

        Get Create (RefClass(cComChilkatHttp)) to hoHTTP
        Get Create (RefClass(cComChilkatHttpRequest)) to hoHTTPReq
        Get Create (RefClass(cComChilkatHttpResponse)) to hoHTTPResp

        Get ComUnlockComponent      of hoHTTP UNLOCK_CHILKAT_HTTP to bOK
        Set ComOAuth1               of hoHTTP to 1
        Set ComOAuthConsumerKey     of hoHTTP to (psOAuthConsumerKey(Self))       // these 4 properties all have values at this point
        Set ComOAuthConsumerSecret  of hoHTTP to (psOAuthConsumerSecret(Self))    
        Set ComOAuthToken           of hoHTTP to (psOAuthToken(Self))
        Set ComOAuthTokenSecret     of hoHTTP to (psOAuthTokenSecret(Self))
        Set ComOAuthVerifier        of hoHTTP to ""

        Send ComAddParam            of hoHTTPReq "status" (left(sTweet,140))
        Send ComAddHeader           of hoHTTPReq "Content-Type" "application/x-www-form-urlencoded"

        Get ComPostUrlEncoded       of hoHTTP "https://api.twitter.com/1.1/statuses/update.json" (pvComObject(hoHTTPReq)) to vRespCOMObj

        Get TestErrorStatusOfLastResponseObjectCall vRespCOMObj hoHTTP hoHTTPResp to tTwitterErrorStatus

        Send Destroy of hoHTTP
        Send Destroy of hoHTTPReq
        Send Destroy of hoHTTPResp

        Function_Return tTwitterErrorStatus
    End_Function
End_Class

Last response

ChilkatLog:
  PostUrlEncoded:
    DllDate: Aug  1 2014
    ChilkatVersion: 9.5.0.43
    UnlockPrefix: CAREDAHttp
    Username: CM-101220-PC:Andrew
    Architecture: Little Endian; 32-bit
    Language: ActiveX
    VerboseLogging: 0
    url: https://api.twitter.com/1.1/statuses/update.json
    httpRequest:
      httpVersion: 1.1
      verb: GET
      path: /
      contentType: application/x-www-form-urlencoded
      charset: windows-1252
      sendCharset: 0
      mimeHeader: 
      requestParams:
        requestItem:
          name: status
          value: VDF Test Tweet Tuesday 19th
        --requestItem
      --requestParams
    --httpRequest
    fullRequest:
      a_synchronousRequest:
        generateRequest:
          httpRequestGenStartLine:
            genStartLine:
              startLine: POST /1.1/statuses/update.json HTTP/1.1
            --genStartLine
          --httpRequestGenStartLine
          addCookies:
            Not auto-adding cookies.
          --addCookies
          addOAuth1Header:
            oauth_timestamp: 1408454442
            oauth_nonce: COry5NFSZaORD7tIpnComnyqNXk=
            oauth_consumer_key: z3UJ8oZOtPL46NgQIR5z4huc3
            oauth_callback: oob
            oauth_signature_method: HMAC-SHA1
            fullUrl: https://api.twitter.com/1.1/statuses/update.json
            entityBodyParams:
              paramName: status
            --entityBodyParams
          --addOAuth1Header
          sortedParams:
            oauth_hdr: oauth_callback
            oauth_hdr: oauth_consumer_key
            oauth_hdr: oauth_nonce
            oauth_hdr: oauth_signature_method
            oauth_hdr: oauth_timestamp
            oauth_hdr: oauth_token
            oauth_hdr: oauth_version
            oauth_hdr: status
          --sortedParams
          baseStringURI: https://api.twitter.com/1.1/statuses/update.json
          baseStringURI_encoded: https%3A%2F%2Fapi.twitter.com%2F1.1%2Fstatuses%2Fupdate.json
          normalizedParams: oauth_callback=oob&oauth_consumer_key=z3UJ8oZOtPL46NgQIR5z4huc3&oauth_nonce=COry5NFSZaORD7tIpnComnyqNXk%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1408454442&oauth_token=mRHB7PZlwI427f5Q8ZmxVyMpqHcqVJ6s&oauth_version=1.0&status=VDF%20Test%20Tweet%20Tuesday%2019th
          normalizedParams_encoded: oauth_callback%3Doob%26oauth_consumer_key%3Dz3UJ8oZOtPL46NgQIR5z4huc3%26oauth_nonce%3DCOry5NFSZaORD7tIpnComnyqNXk%253D%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1408454442%26oauth_token%3DmRHB7PZlwI427f5Q8ZmxVyMpqHcqVJ6s%26oauth_version%3D1.0%26status%3DVDF%2520Test%2520Tweet%2520Tuesday%252019th
          signatureBaseString: POST&https%3A%2F%2Fapi.twitter.com%2F1.1%2Fstatuses%2Fupdate.json&oauth_callback%3Doob%26oauth_consumer_key%3Dz3UJ8oZOtPL46NgQIR5z4huc3%26oauth_nonce%3DCOry5NFSZaORD7tIpnComnyqNXk%253D%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1408454442%26oauth_token%3DmRHB7PZlwI427f5Q8ZmxVyMpqHcqVJ6s%26oauth_version%3D1.0%26status%3DVDF%2520Test%2520Tweet%2520Tuesday%252019th
          oauth_signature: wYKjFHg820TxiTekw4krjSixHdE=
        --generateRequest
      --a_synchronousRequest
      fullHttpRequest:
        domain: api.twitter.com
        port: 443
        ssl: 1
        openHttpConnection:
          Opening connection directly to HTTP server.
          httpHostname: api.twitter.com
          httpPort: 443
          ssl: 1
          socket2Connect:
            connect2:
              connectImplicitSsl:
                clientHandshake:
                  clientHandshake2:
                    processHandshakeRecord:
                      processHandshakeMessage:
                        processServerHello:
                          HelloExtension: renegotiation_info
                          HelloExtensionLen: 1
                        --processServerHello
                      --processHandshakeMessage
                    --processHandshakeRecord
                  --clientHandshake2
                --clientHandshake
                checkServerCert:
                  Not verifying server certificate...
                  Set the RequireSslCertVerify property to enable verification.
                --checkServerCert
                Secure Channel Established.
              --connectImplicitSsl
            --connect2
          --socket2Connect
          connectElapsedMs: 655
          HTTP connection succeeded.
        --openHttpConnection
        connectTime: Elapsed time: 655 millisec
        sendRequestHeader:
          sendHeaderElapsedMs: 0
        --sendRequestHeader
        sendRequestBody:
          sendBodyElapsedMs: 0
        --sendRequestBody
        statusCode: 401
        statusText: Unauthorized
        readResponseBody:
          contentLength: 61
        --readResponseBody
      --fullHttpRequest
      computeAuthorization:
        No useful WWW-Authenticate response header was found.
      --computeAuthorization
      computeAuthorization failed (2).
      success: 0
    --fullRequest
  --PostUrlEncoded
  Failed.
--ChilkatLog

Answer

Note if I use the tokens in "Your access token" in my account twitter using the same statuses/up0date call I can post to my own timeline as me .... but obliviously that does not enable the application to post on other users timeline as themselves as it circumvents the PIN login process and they are my keys anyway

So the long and the short of it is I've been unsuccessful in using the keys obtained via the oAuth process to actually do anything with

Has anyone achieved this regardless of language ?

Thanks


Answer

Having successfully got the token from the two stage auth process it even fails it's own verify_credentials check ! ?

PLEASE can someone on here give me their own example (in any language) of a two stage auth and a successful action after that using the token to prove i'm doing something wrong in my own code

Here is my verify_credentials in a language called Dataflex and i'm getting a 401 error back just like all my other attempts to use the received tokens

Thanks

Function VerifyCredentials Returns tdTwitterErrorStatus
    Variant vRespCOMObj
    tdTwitterErrorStatus tTwitterErrorStatus
    Boolean bOK
    Handle hoHTTP hoHTTPReq hoHTTPResp

    Get Create (RefClass(cComChilkatHttp)) to hoHTTP
    Get Create (RefClass(cComChilkatHttpRequest)) to hoHTTPReq
    Get Create (RefClass(cComChilkatHttpResponse)) to hoHTTPResp

    Get ComUnlockComponent      of hoHTTP UNLOCK_CHILKAT_HTTP to bOK
    Set ComOAuth1               of hoHTTP to 1
    Set ComOAuthConsumerKey     of hoHTTP to (psOAuthConsumerKey(Self))       // these 4 properties all have values at this point
    Set ComOAuthConsumerSecret  of hoHTTP to (psOAuthConsumerSecret(Self))    
    Set ComOAuthToken           of hoHTTP to (psOAuthToken(Self))
    Set ComOAuthTokenSecret     of hoHTTP to (psOAuthTokenSecret(Self))
    Set ComOAuthVerifier        of hoHTTP to ""

    Get ComQuickGetObj          of hoHTTP "https://api.twitter.com/1.1/account/verify_credentials.json" to vRespCOMObj

    Get TestErrorStatusOfLastResponseObjectCall vRespCOMObj hoHTTP hoHTTPResp to tTwitterErrorStatus

    Send Destroy of hoHTTP
    Send Destroy of hoHTTPReq
    Send Destroy of hoHTTPResp

    Function_Return tTwitterErrorStatus
End_Function

Answer

A polite but frustrated post.

With over 100 views is there really no one on here using Chilkat to obtain an oAuth login from Twitter and then actively doing something with it

I just can't get the received key to work

Thanks


Answer

With a significant amount of help from Chilkat themselves I've now got to the bottom of it

For anyone else reading this my problem was ....

In a nutshell at Stage 2 of the oAuth process requires the token and secret from stage 1 and the second request should be a GET not a POST as per the Chilkat examples