Twitter访问令牌请求返回“无效或过期令牌”

时间:2014-09-10 16:10:30

标签: php twitter twitter-oauth

我使用自定义代码连接到Twitter并请求访问令牌。出于某种原因,当试图发布到" access_token"在API上它返回"无效或过期的令牌"。代码如下(除了一些外部函数调用和属性,这应该足以复制错误):

    public function authenticate($get,$return = false) {                                                
    session_start();        

            if (!isset($get['oauth_verifier'])){
                    // Step 1 - get a request token
                    $step1 = $this->processRequest('oauth/request_token',0,$this->pObj->getRedirectUrl().'?process=true');                                        
                    parse_str($step1,$parts);

                    if ($parts['oauth_callback_confirmed'] !== 'true'){ die('Error with process'); }

                    $_SESSION['tw_secret'] = $parts['oauth_token_secret'];

                    // Step 2
                    $url = str_replace('1.1/','',$this->api_url);
                    header("Location: {$url}oauth/authenticate?oauth_token={$parts['oauth_token']}");
            } else {
                    // Step 3
                    $this->o_token = $get['oauth_token'];
                    $this->o_secret = $_SESSION['tw_secret'];                     
                    $content['oauth_verifier'] = $get['oauth_verifier'];
                    $step3 = $this->processRequest('oauth/access_token',1,null,$content,'array');                     
            }           
    }

    // https://dev.twitter.com/docs/auth/creating-signature
    private function generateSignature($oauth,$fullurl,$http_method,$content){        

            // Take params from url
            $main_url = explode('?',$fullurl);

            // Split the content
            $contents = explode('&',$content);

            $urls = array_merge(explode('&',$main_url[1]),$contents);

            foreach ($urls as $param){
                    $bits = explode('=',$param);
                    if (strlen($bits[0])){
                            $oauth[$bits[0]] = rawurlencode($bits[1]);
                    }    
            }

            ksort($oauth);

            $string = http_build_query($oauth);

            $new_string = strtoupper($http_method).'&'.urlencode($main_url[0]).'&'.urlencode(urldecode($string));

            // The request_token request doesn't need a o_secret because it doesn't have one!
            $sign_key = strstr($fullurl,'request_token') ? $this->c_secret.'&' : $this->c_secret.'&'.$this->o_secret;                 

    return urlencode(base64_encode(hash_hmac('sha1',$new_string,$sign_key,true)));        
    }

    public function processRequest($in_url,$test = false,$callback = null,$content = null, $content_type = 'json',$form_content_type = 'application/x-www-form-urlencoded'){                
    $method = 'GET';

            // Twitter still uses Oauth1 (which is a pain)
            $oauth = array(
                    'oauth_consumer_key'=>$this->c_key,
                    'oauth_nonce'=>$this->random(32),
                    'oauth_signature_method'=>'HMAC-SHA1',
                    'oauth_timestamp'=>time(),
                    'oauth_token'=>$this->o_token,
                    'oauth_version'=>'1.0'  
            );

            $url = $this->api_url.$in_url;

            if (strlen($callback)){
                    $oauth['oauth_callback'] = urlencode(urldecode($callback));
                    unset($oauth['oauth_token']);
                    $method = 'POST';
                    $url = str_replace('1.1/','',$url);
            }                

            if (is_array($content) || strlen($content)){ $method = 'POST'; }

            $oauth['oauth_signature'] = $this->generateSignature($oauth,$url,$method,'');                                

            ksort($oauth);

            foreach ($oauth as $k=>$v){
                    $auths[] = $k.'="'.$v.'"';
            }

            $stream = array('http' =>
                                    array(
                                            'method' => $method,
                                            'ignore_errors'=>true, // http://php.net/manual/en/context.http.php - otherwise browser returns error not error content
                                            'follow_location'=>false,
                                            'max_redirects'=>0,
                                            'header'=> array(
                                                                    'Content-type: '.$form_content_type,
                                                                    'Authorization: OAuth '.implode(', ',$auths),
                                                                    'Connection: close'
                                                            )                                             
                                    )
                            );                                 

            if (is_array($content)){  
                    $content = $content_type == 'json' ? json_encode($content) : http_build_query($content);
                   /* foreach ($content as $k=>$v){
                            $strs[] = "$k=".urlencode(urldecode($v));        
                    }

                    // Just for now to keep things simple
                    $content = 'status=Hello%20Ladies%20%2b%20Gentlemen%2c%20a%20signed%20OAuth%20request%21';*/
            } 

            if (!is_null($content)){
                    $stream['http']['content'] = $content;
            }                                                               

            // Tell streams to make a request  
            // Invalid key or 401 error tends to suggest an incorrect signing key / signature                                     
            $response = file_get_contents($url, false, stream_context_create($stream));             

            if ($test){
                    print'<pre>';print_r($oauth);print'</pre>';
                    print'<pre>';print_r($stream);print'</pre>';
                    //echo $callback.'<br>';
                    echo $url.'<br>';
                    //print'<pre>';print_r($http_response_header);print'</pre>';
                    print'<pre>[';print_r($response);print']</pre>';
            }                                

            if (!is_object(json_decode($response))){
                    // Content supplied is not json - just return it
                    return $response;                        
            } else {
                    $response = json_decode($response);
            }                                

    return $this->pObj->convertObjectToArray($response);                                                
    }                

1 个答案:

答案 0 :(得分:0)

问题的原因是:

1)不应包含Twitter API的版本 2)帖子缺少签名中的Oauth_verifier

感谢twitteroauth提供了一些指导。