OAuth 2.0不适用于服务器端Web应用程序

时间:2011-08-14 15:01:49

标签: php google-api oauth-2.0

我正在尝试使用gmail获取Google contacts api个联系人。为此我使用OAuth 2.0。为此,我在这里阅读了他们使用OAuth 2.0的指南。我广泛地遵循这些步骤

  1. 使用Google注册我的应用并获取客户端ID和客户端密码,并将redirect uri注册到其中
  2. 现在我首先创建了一个名为sample.php的文件,如果用户点击get contacts,则会将其重定向到Google确认页面
  3. 现在谷歌要求确认,如果用户同意提供其联系方式,那么他会被redirect uri重定向到code
  4. 现在我提取代码并发出一个帖子请求来获取OAuth令牌,如果我获得了令牌,我就联系人发出请求。
  5. sample.php的代码如下所示

    <?php
    $client_id="my client id";
    $redirect_uri="http://localhost/htdocs/contacts/redirect.php";
    echo <<<doc
    <html>
    <body>
    <a href="http://accounts.google.com/o/oauth2/auth?client_id=$client_id&redirect_uri=$redirect_uri&scope=https://www.google.com/m8/feeds/&response_type=code">
    get contacts
    </a>
    doc;
    echo <<<doc
    </body>
    </html>
    doc;
    ?>
    

    redirect.php的代码如下所示

    <?php
    $client_id="my client id";
    $client_sec="my client secret ";  
    $redirect_uri="http://localhost/htdocs/contacts/redirect.php";
    $code=$_GET['code'];
    $post="code=$code&client_id=$client_id&client_secret=$client_sec&redirect_uri=$redirect_uri&grant_type=authorization_code";
    $post=urlencode($post);
     //the following curl request is made to get the authorization token
    $ch=curl_init();
    $url="https://accounts.google.com/o/oauth2/token";
    curl_setopt($ch,CURLOPT_URL,$url);
    curl_setopt($ch,CURLOPT_FOLLOWLOCATION,1);
    curl_setopt($ch,CURLOPT_AUTOREFERER,1);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($ch,CURLOPT_POST,1);
    curl_setopt($ch,CURLOPT_POSTFIELDS,$post);
    curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
    $json=curl_exec($ch);
    curl_close($ch);
    echo $json;     // this is showing Required parameter is missing: grant_type Error 400
    $res=json_decode($json,true);
    print_r($res);   // this is just for debugging
    $token=$res['access_token'];
    echo $token;   // this is just for debugging
    $url="https://www.google.com/m8/feeds/contacts/default/full?oauth_token=$token";
      //the following curl request is made to get the contacts
    $ch=curl_init();
    curl_setopt($ch,CURLOPT_URL,$url);
    curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
    curl_setopt($ch,CURLOPT_FOLLOWLOCATION,1);
    curl_setopt($ch,CURLOPT_AUTOREFERER,1);
    $xml=curl_exec($ch);
    echo $xml;
    curl_close($ch);
    $dom= new DOMDocument();
    $dom->loadXML($xml);
    $xpath=new DOMXPath($dom);
    $path='//gd:email';
    $nodes=$xpath->query($path);
    echo $nodes->length."<br />";
    foreach($nodes as $node)
    {
    $email=$node->attributes->getNamedItem('address')->nodeValue;
    echo $email."<br />";
    }
    ?>
    

    现在的问题是第4步失败了。它一直顺利到确认步骤,当我点击Allow access我被重定向到我的redirect uri但它的说法

    缺少必需参数:grant_type错误400

    现在我不明白这一点,因为我提供了grant_type参数。我查看了firebug并发现发布了一个邮件请求但不是我想要的那个。正在发布的帖子请求是这个 https://accounts.google.com/o/oauth2/approval?xsrfsign=AC9jObYAAAAATkfm3uvx0sfsW7WVmB_FeRqVPLjDcTLz,状态为302 moved Temporarily。我不明白最近发生了什么。他们改变了OAuth workflow中的某些内容吗?需要一些帮助


    修改 正如建议的那样, Ikke 我删除了grant_type之前的空格并且它有效。现在我可以获取访问令牌,但仍然无法获取联系人。(我收到Empty string supplied as input in htdocs\contacts\redirect.php on line 35错误而line 35指的是$dom->loadXML($xml);所以似乎get请求没有被发送)此外我无法在firebug中看到发布请求(但肯定是因为我获得了访问令牌作为响应)。我也没有在firebug中看到我在发布请求后发出错误的获取请求?


    更新 问题是请求是在https上,我没有使用适当的https标头。我使用了正确的标题,它工作。问题解决了吗?也许。因为我仍然不明白为什么我无法在firebug's' net`标签中看到这些获取和发布请求

3 个答案:

答案 0 :(得分:2)

&grant_type之间有一个空格。这可能会导致谷歌无法识别参数。

答案 1 :(得分:1)

“因为我仍然不明白为什么我无法在firebug''net`标签中看到那些获取和发布请求”

我假设因为你要求curl的东西,它与firefox无关,因为curl是一个服务器端库,因此curl制作的POST不通过浏览器而且firebug看不到它们。

答案 2 :(得分:0)

您正在将已经urlencoded的字符串传递给PHP的urlencode()

$post="code=$code&client_id=$client_id&client_secret=$client_sec&redirect_uri=$redirect_uri&grant_type=authorization_code";
$post=urlencode($post);

这会弄乱价值,Google的服务器无法正确解析它,因此报告缺少参数。移除$post=urlencode($post);行,看看它是否有效