simonspa / twitcurl

Automatically exported from code.google.com/p/twitcurl
0 stars 0 forks source link

oAuthHandlePIN No longer working #57

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. Run Twitter Client and attempt to use twitter client without visiting Twitter
2. Even when supplying a proper Username and Password the application will fail

What is the expected output? What do you see instead?
The TwitCurl uses the function oAuthHandlePIN to connect to twitter and submit 
a signin/authorize form to Twitter with the username and password supplied. 
Instead of returning a page with the pin encapsulated in: 
code-desc"><code>######</code>, the form submit returns a page with: 

<html><body>You are being <a 
href="https://api.twitter.com/login/error?username_or_email=testscreenname&amp;r
edirect_after_login=%2F">redirected</a>.</body></html>

What version of the product are you using? On what operating system?
Using Windows 7, and the latest source downloaded from GitHUB. 

Please provide any additional information below.
It seems twitter may have updated this webpage because inorder to get TwitCURL 
to find the Authenticity_Token and oAuthToken, I had to update 
twitcurls.h
const std::string OAUTHLIB_TOKEN_END_TAG_TWITTER_RESP = "\" />";

to this:
const std::string OAUTHLIB_TOKEN_END_TAG_TWITTER_RESP = "\"/>";

Original issue reported on code.google.com by cesar...@gmail.com on 8 Apr 2015 at 2:35

GoogleCodeExporter commented 9 years ago
oAuthHandlePIN does not work and cannot get access token using twitcurl no 
longer.

Original comment by gsmmi...@gmail.com on 11 May 2015 at 2:50

GoogleCodeExporter commented 9 years ago
I was able to fix this issue in my version of TwitCurl, if you are interested 
in the solution, and have the ability to make the necessary changes to TwitCURL 
in your project. 

The changes involve editing the TwitCURLs.h header to update the constant that 
determines the END tag for the TOKENS as mentioned above. 

The second edit needs to be done toe the TwitCURL.cpp source code, specifically 
the function bool 

twitCurl::oAuthHandlePIN( const std::string& authorizeUrl )

We need to add cookie handling into this function in order to pass through a 
twitter session cookie value that Twitter apparently requires now. 

struct curl_slist* pCookieList = NULL;
..
..
curl_easy_setopt( m_curlHandle, CURLOPT_COOKIELIST, &pCookieList);

before the initial URL submission then after we get the page that has the 
authenticity token and the oAuthTokenVal we retrieve the cookie list.

curl_easy_getinfo( m_curlHandle, CURLINFO_COOKIELIST, &pCookieList );

then after the authenticityToken and oauthTokenVal have been extracted from the 
resulting page. We need to add the cookie list into the POST that includes the 
username and passowrd.

curl_easy_setopt( m_curlHandle, CURLOPT_COOKIELIST, &pCookieList);

Doing this I am able to login as the user and retrieve the PIN in order to 
authorize my application for this user. 

Original comment by cesar...@gmail.com on 11 May 2015 at 2:09

GoogleCodeExporter commented 9 years ago
We have also problem with the oAuthHandlePIN. Suddenly it does not work anymore.

cesar...@gmail.com, can you post more details about your solution? I am not 
sure where to put your lines of code to make it work. If you write done the 
line numbers (based on line numbers here): 

https://code.google.com/p/twitcurl/source/browse/trunk/libtwitcurl/twitcurl.cpp

or post the whole updated method that would be helpful.

/Michael

Original comment by samlogic...@gmail.com on 19 May 2015 at 5:25

GoogleCodeExporter commented 9 years ago
Sure like I said there are two files in the twitCURL project that need to be 
updated. The changes that need to be made to twitcurlurls.h is pretty simple so 
I want bother with that.

This is the new version of oAuthPINHandle that works for me, compare it to the 
original to see which changes I made:

bool twitCurl::oAuthHandlePIN( const std::string& authorizeUrl /* in */ )
{
    /* Return if cURL is not initialized */
    if( !isCurlInit() )
        return false;

    std::string dataStr;
    std::string oAuthHttpHeader;
    std::string authenticityTokenVal;
    std::string oauthTokenVal;
    std::string pinCodeVal;
    unsigned long httpStatusCode = 0;
    size_t nPosStart, nPosEnd;
    struct curl_slist* pOAuthHeaderList = NULL;

    //-- ADDED by cesareof for cookie handling
    struct curl_slist* pCookieList = NULL;

    /* Prepare standard params */
    prepareStandardParams();

    /* Set OAuth header */
    m_oAuth.getOAuthHeader( eOAuthHttpGet, authorizeUrl, dataStr, oAuthHttpHeader );
    if( oAuthHttpHeader.length() )
    {
        pOAuthHeaderList = curl_slist_append( pOAuthHeaderList, oAuthHttpHeader.c_str() );
        if( pOAuthHeaderList )
            curl_easy_setopt( m_curlHandle, CURLOPT_HTTPHEADER, pOAuthHeaderList );
    }

    /* Set http request and url */
    curl_easy_setopt( m_curlHandle, CURLOPT_HTTPGET, 1 );
    curl_easy_setopt( m_curlHandle, CURLOPT_URL, authorizeUrl.c_str() );
    //-- ADDED by cesareof for cookie handling
    curl_easy_setopt( m_curlHandle, CURLOPT_COOKIELIST, &pCookieList);

    /* Send http request */
    if( CURLE_OK == curl_easy_perform( m_curlHandle ) )
    {
        if( pOAuthHeaderList )
        {
            curl_easy_getinfo( m_curlHandle, CURLINFO_HTTP_CODE, &httpStatusCode );
            curl_slist_free_all( pOAuthHeaderList );

            // Now, let's find the authenticity token and oauth token
            nPosStart = m_callbackData.find( oAuthLibDefaults::OAUTHLIB_AUTHENTICITY_TOKEN_TWITTER_RESP_KEY );
            if( std::string::npos == nPosStart )
            {
                return false;
            }
            nPosStart += oAuthLibDefaults::OAUTHLIB_AUTHENTICITY_TOKEN_TWITTER_RESP_KEY.length();
            nPosEnd = m_callbackData.substr( nPosStart ).find( oAuthLibDefaults::OAUTHLIB_TOKEN_END_TAG_TWITTER_RESP )   
            if( std::string::npos == nPosEnd )
                return false;

            authenticityTokenVal = m_callbackData.substr( nPosStart, nPosEnd );

            nPosStart = m_callbackData.find( oAuthLibDefaults::OAUTHLIB_TOKEN_TWITTER_RESP_KEY );
            if( std::string::npos == nPosStart )
                return false;

            nPosStart += oAuthLibDefaults::OAUTHLIB_TOKEN_TWITTER_RESP_KEY.length();
            nPosEnd = m_callbackData.substr( nPosStart ).find( oAuthLibDefaults::OAUTHLIB_TOKEN_END_TAG_TWITTER_RESP );
            if( std::string::npos == nPosEnd )
                return false;

            oauthTokenVal = m_callbackData.substr( nPosStart, nPosEnd );
            //-- ADDED by cesareof for cookie handling
        curl_easy_getinfo( m_curlHandle, CURLINFO_COOKIELIST, &pCookieList );
        }
    }
    else if( pOAuthHeaderList )
    {
        curl_slist_free_all( pOAuthHeaderList );
        return false;
    }

    // Second phase for the authorization
    pOAuthHeaderList = NULL;
    oAuthHttpHeader.clear();

    /* Prepare standard params */
    prepareStandardParams();

    /*
    Now, we need to make a data string for POST operation
    which includes oauth token, authenticity token, username, password.
    */
    dataStr =   oAuthLibDefaults::OAUTHLIB_AUTHENTICITY_TOKEN_KEY + "=" + authenticityTokenVal + "&" +  
                oAuthLibDefaults::OAUTHLIB_REDIRECT_AFTER_LOGIN + "="+ authorizeUrl.c_str() + "&" +       
                oAuthLibDefaults::OAUTHLIB_TOKEN_KEY + "=" + oauthTokenVal + "&" +                      
                oAuthLibDefaults::OAUTHLIB_SESSIONUSERNAME_KEY + "=" + getTwitterUsername() + "&" +     
                oAuthLibDefaults::OAUTHLIB_SESSIONPASSWORD_KEY + "=" + getTwitterPassword();

    /* Set OAuth header */
    m_oAuth.getOAuthHeader( eOAuthHttpPost, authorizeUrl, dataStr, oAuthHttpHeader );
    if( oAuthHttpHeader.length() )
    {
        pOAuthHeaderList = curl_slist_append( pOAuthHeaderList, oAuthHttpHeader.c_str() );
        if( pOAuthHeaderList )
            curl_easy_setopt( m_curlHandle, CURLOPT_HTTPHEADER, pOAuthHeaderList );
    }

    /* Set http request and url */
    curl_easy_setopt( m_curlHandle, CURLOPT_POST, 1 );
    curl_easy_setopt( m_curlHandle, CURLOPT_URL, authorizeUrl.c_str() );
    curl_easy_setopt( m_curlHandle, CURLOPT_COPYPOSTFIELDS, dataStr.c_str() );
    //-- ADDED by cesareof for cookie handling
    curl_easy_setopt( m_curlHandle, CURLOPT_COOKIELIST, &pCookieList);

    /* Send http request */
    if( CURLE_OK == curl_easy_perform( m_curlHandle ) )
    {
        if( pOAuthHeaderList )
        {
            curl_easy_getinfo( m_curlHandle, CURLINFO_HTTP_CODE, &httpStatusCode );
            curl_slist_free_all( pOAuthHeaderList );

            // Now, let's find the PIN CODE
            nPosStart = m_callbackData.find( oAuthLibDefaults::OAUTHLIB_PIN_TWITTER_RESP_KEY );
            if( std::string::npos == nPosStart )
                return false;

            nPosStart += oAuthLibDefaults::OAUTHLIB_PIN_TWITTER_RESP_KEY.length();
            nPosEnd = m_callbackData.substr( nPosStart ).find( oAuthLibDefaults::OAUTHLIB_PIN_END_TAG_TWITTER_RESP );
            if( std::string::npos == nPosEnd )
                return false;

            pinCodeVal = m_callbackData.substr( nPosStart, nPosEnd );
            getOAuth().setOAuthPin( pinCodeVal );
            return true;
        }
    }
    else if( pOAuthHeaderList )
        curl_slist_free_all( pOAuthHeaderList );

    //-- ADDED by cesareof for cookie handling
    if( pCookieList )
        curl_slist_free_all( pCookieList );

    return false;
}

Original comment by cesar...@gmail.com on 19 May 2015 at 5:34

GoogleCodeExporter commented 9 years ago
cesar...@gmail.com,

Thank you for source code. It worked fine. Now Twitter work for us again. :)

However, there was a minor change I needed to do to make in the header file to 
make it work. I needed to use this line in the header file:

const std::string OAUTHLIB_TOKEN_END_TAG_TWITTER_RESP = "\">";

instead of

const std::string OAUTHLIB_TOKEN_END_TAG_TWITTER_RESP = "\"/>";

I needed to remove the slash in the string, otherwise the end tag was not 
found. I don't know why, but this is something to be aware of.

Original comment by samlogic...@gmail.com on 19 May 2015 at 6:55

GoogleCodeExporter commented 9 years ago
You're welcome. That is the minor change I was referring to in Twitcurlurls.h I 
realize now I left the / in the comment, but you are correct the value should 
be: 

before->
const std::string OAUTHLIB_TOKEN_END_TAG_TWITTER_RESP = "\" />";

after->
const std::string OAUTHLIB_TOKEN_END_TAG_TWITTER_RESP = "\">";

Probably why it is better to just copy and paste from my code then try and 
remember and retype what I did. 

Thanks

Original comment by cesar...@gmail.com on 19 May 2015 at 7:03

GoogleCodeExporter commented 9 years ago
Attempting to rebuild the above function (oAuthHandlePIN) using the provided 
code resulted in a build error referencing an unknown constant: 
oAuthLibDefaults::OAUTHLIB_REDIRECT_AFTER_LOGIN, which is undefined in my 
twitcurls.h header.  What should that value be?  Thanks!

Original comment by Antm...@gmail.com on 6 Jun 2015 at 8:41

GoogleCodeExporter commented 9 years ago
In my version of twitcurlurls.h there is this value in: 

namespace oAuthLibDefaults
{
..
..
  const std::string OAUTHLIB_REDIRECT_AFTER_LOGIN = "redirect_after_login";

}

It is just the key for the redirect tag, not sure if it is necessary in the 
form submission but if you need to you can add it. 

Original comment by cesar...@gmail.com on 8 Jun 2015 at 2:10