【问题标题】:OAuth 2.0 not working for server-side web applicationOAuth 2.0 不适用于服务器端 Web 应用程序
【发布时间】:2011-08-14 15:01:48
【问题描述】:

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

  1. 在 google 上注册我的应用程序并获取客户端 ID 和客户端密码,然后向他们注册我的 redirect uri
  2. 现在我首先创建了一个名为sample.php 的文件,如果用户点击get contacts,他将被重定向到谷歌确认页面
  3. 现在 google 要求确认,如果用户同意提供其联系方式,那么他将被重定向到 redirect uri,并带有 code
  4. 现在我提取代码并发出发布请求以获取 OAuth 令牌,如果我得到令牌,我将请求联系人。

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,发现正在发出一个帖子请求,但不是我想要的。正在发出的帖子请求是 this
https://accounts.google.com/o/oauth2/approval?xsrfsign=AC9jObYAAAAATkfm3uvx0sfsW7WVmB_FeRqVPLjDcTLz,状态为 302 moved Temporarily。我不明白发生了什么事。他们在OAuth workflow 中改变了什么吗?需要帮助


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


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

【问题讨论】:

  • 可能是拼写错误,但是 & 和 grant_type 之间有一个空格。
  • @Ikke 谢谢你的工作。现在我可以得到access token 但还没有联系人。让我看看是否也获得联系方式。将其发布为答案,我会将其标记为已接受。再次感谢
  • “无法获取联系人”是什么意思?
  • @ikke 我的意思是我没有得到联系人页面。我没有看到正在建立联系人的 curl 获取请求我收到一条消息,因为 Empty string supplied as input in C:\xampp\htdocs\contacts\redirect.php on line 35 第 35 行指的是 $dom-&gt;loadXML($xml);

标签: php google-api oauth-2.0


【解决方案1】:

&amp;grant_type 之间有一个空格。这可能会导致 google 无法识别该参数。

【讨论】:

  • 谢谢。请参阅我的问题中的编辑。我对firebug中的某事感到困惑
【解决方案2】:

“因为我仍然不明白为什么我无法在 firebug 的'net` 选项卡中看到那些 get 和 post 请求”

我假设由于您使用 curl 请求内容,因此它与 firefox 无关,因为 curl 是服务器端库,因此 curl 发出的 POST 不会通过浏览器并且 firebug 看不到它们。

【讨论】:

    【解决方案3】:

    您正在将一个已编码的字符串传递给 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); 行,看看它是否工作更好

    【讨论】:

      猜你喜欢
      • 2014-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-28
      • 2017-01-07
      • 1970-01-01
      相关资源
      最近更新 更多