开发者

Google OAuth Signature Invalid response (PHP)

Eyes are getting sore trying to hunt down the issue causing this. I'm narrowing it down but I'm tired of changing different parameters to get the signature to pass. I've been comparing my base string and Authorization headers with those output by the google-code-playground.

I've been referencing this article and think I am getting close:

PHP Oauth signature_invalid

My base string:

GET&https%3A%2F%2Fwww.google.com%2Faccounts%2FOAuthGetRequestToken&oauth_callback%3Dhttp%253A%252F%252Fgooglecodesamples.com%252Foauth_playground%252Findex.php%26oauth_consumer_key%3Danonymous%26oauth_nonce%3D1f8a27974826a0001f679186898bb79a%26oauth_signature_method%3DHMAC- SHA1%26oauth_timestamp%3D1313023952%26oauth_version%3D1.0%26scope%3Dhttps%253A%252F%252Fwww.google.com%252Fcalendar%252Ffeeds%252F

Authorization headers:

OAuth oauth_consumer_key="anonymous", oauth_nonce="1f8a27974826a0001f679186898bb79a", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1313023952", oauth_callback="http%3A%2F%2Fgooglecodesamples.com%2Foauth_playground%2Findex.php", oauth_version="1.0", oauth_signature="nHL5107wlVXrB5GJjyDClpc5pJs%3D"0signature_invalid

Main Function:

private function oAuthGetRequestToken()
{
    echo "<pre>";
    $secret = 'anonymous';
    $url = 'https://www.google.com/accounts/OAuthGetRequestToken';
    $scope = 'https://www.google.com/calendar/feeds/';

    $authParams = array(
                    'oauth_consumer_key' => 'anonymous',
                    'oauth_nonce' => self::generateNonce(),
                    'oauth_signature_method' => 'HMAC-SHA1',
                    'oauth_timestamp' => time(),
                    'oauth_callback' => 'http://googlecodesamples.com/oauth_playground/index.php',
                    'oauth_version' => '1.0');

    $unsignedBaseString = self::getBaseString('GET', $url, $authParams, $scope);            

    $unsignedKey = array($authParams['oauth_consumer_key'], $secret);
    $unsignedKeyParts = array_map('urlencode', $unsignedKey);
    $key = implode('&', $unsignedKeyParts);

    $oauth_signature = self::hmacsha1($key, $unsignedBaseString);
    $authParams['oauth_signature'] = $oauth_signature;

    $rest = new Rest();
    $oAuthGetRequestTokenResponse = $rest->OAuthHttpGetRequest($url, $authParams, $scope);
    print_r($oAuthGetRequestTokenResponse);
}

Helper functions:

    protected function generateNonce()
{
    $nonce = hash('md5', self::makeRandomString());
    return $nonce;
}

protected function makeRandomString($bits = 256)
{
    $bytes = ceil($bits / 8);
    $return = '';
    for ($i = 0; $i < $bytes; $i++) {
        $return .= chr(mt_rand(0, 255));
    }
    return $return;
}

protected function hmacsha1($key, $data) 
{
    return base64_encode(hash_hmac('sha1', $data, $key, true));
}

protected function getBaseString($method, $url, $authParams, $scope)
{
    $authString = '';       
    foreach($authParams as $key => $value)
        $authString .= $key . "=" . urlencode($value) . "&";

    $authString = rtrim($authString, '&');

    $baseString = $method . '&' . urlencode($scope) . '&' . $authString;
    return $baseString;
}

Rest/Request function:

public function OAuthHttpGetRequest($url, $authParams, $scope)
{
    $oAuthHeaders = '';
    $oAuthHttpGetResponse;
    foreach($authParams as $key=>$value)
    {
        $oAuthHeaders .= $key . '="' . urlencode($value) . '", ';
    }

    $oAuthHeaders = rtrim($oAuthHeaders, ', ');
    $authString = "OAuth " . $oAuthHeaders;
    echo "<br/>" . $authString;
    $urlWithScope = $url . '?scope=' . urlencode($scope);

    if($curlHandle = curl_init())
    {
        curl_setopt($curlHandle, CURLOPT_URL, $urlWithScope);

        curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curlHandle, CURLOPT_HTTPHEADER,开发者_高级运维 array("Authorization: " . $authString));
        //curl_setopt($curlHandle, CURLOPT_POST, TRUE);
        //curl_setopt($curlHandle, CURLOPT_POSTFIELDS, );
        curl_setopt($curlHandle, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt($curlHandle, CURLOPT_SSL_VERIFYHOST, 0);

        $oAuthHttpGetResponse = curl_exec($curlHandle);
        echo curl_errno($curlHandle);
        echo curl_error($curlHandle);

        curl_close($curlHandle);
    }
    else
        die("Could not instance cURL, is the module enabled?");

    return $oAuthHttpGetResponse;
}


on first read I think your problem is in the getBaseString function:

$baseString = $method . '&' . urlencode($scope) . '&' . $authString;

I think that you should use the REQUEST TOKEN ENDPOINT here instead of the scope...

Scopes are requested with additional parameter, because generally the OAuth protocol does not specify the existence of scopes - they are extension needed to better tune API access, but they are not mandatory for the protocol to work.

And when creating the base signature string, the URL that is included after the $method, is always the URL which is going to receive the request...

In your case I think it should be:

$baseString = $method . '&' . urlencode($url) . '&' . $authString;

--- ADDON ---

To be more clear: when first requesting REQUEST token, the base string should contain the URL of the REQUET TOKEN endpoing...

When later requesting ACCESS token, the base string should contain the URL of the ACCESS TOKEN endpoint

When finally, after getting ACCESS token you are accessing a resource (scope) then the base string should contain the URL of the resource (aka scope in your example)...

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜