PHP. 如何获得访问令牌。使用OAuth 2.0认证Google API。

3

我找到了这个函数,据说可以获取accessToken,但是我什么也没得到。 我有$_REQUEST['code']和其他必要的信息在这个函数中。 有什么想法吗? 谢谢。

//Oauth 2.0: exchange token for session token so multiple calls can be made to api
if(isset($_REQUEST['code'])){
    $_SESSION['accessToken'] = get_oauth2_token($_REQUEST['code']);
}

//returns session token for calls to API using oauth 2.0
function get_oauth2_token($code) {
    global $client_id;
    global $client_secret;
    global $redirect_uri;

    $oauth2token_url = "https://accounts.google.com/o/oauth2/token";
    $clienttoken_post = array(
    "code" => $code,
    "client_id" => $client_id,
    "client_secret" => $client_secret,
    "redirect_uri" => $redirect_uri,
    "grant_type" => "authorization_code"
    );

    $curl = curl_init($oauth2token_url);

    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_POSTFIELDS, $clienttoken_post);
    curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);

    $json_response = curl_exec($curl);
    curl_close($curl);

    $authObj = json_decode($json_response);

    if (isset($authObj->refresh_token)){
        //refresh token only granted on first authorization for offline access
        //save to db for future use (db saving not included in example)
        global $refreshToken;
        $refreshToken = $authObj->refresh_token;
    }

    $accessToken = $authObj->access_token;
    return $accessToken;
}
5个回答

5
这是我获取访问令牌和刷新令牌的方法。
创建一个包含以下代码的文件:
<?php

if (isset($_GET['code'])) {
    // try to get an access token
    $code = $_GET['code'];
    $url = 'https://accounts.google.com/o/oauth2/token';
    $params = array(
        "code" => $code,
        "client_id" => YOUR_CLIENT_ID,
        "client_secret" => YOUR_CLIENT_SECRET,
        "redirect_uri" => 'http://' . $_SERVER["HTTP_HOST"] . $_SERVER["PHP_SELF"],
        "grant_type" => "authorization_code"
    );

    $ch = curl_init();
    curl_setopt($ch, constant("CURLOPT_" . 'URL'), $url);
    curl_setopt($ch, constant("CURLOPT_" . 'POST'), true);
    curl_setopt($ch, constant("CURLOPT_" . 'POSTFIELDS'), $params);
    $output = curl_exec($ch);
    $info = curl_getinfo($ch);
    curl_close($ch);
    if ($info['http_code'] === 200) {
        header('Content-Type: ' . $info['content_type']);
        return $output;
    } else {
        return 'An error happened';
    }
} else {

    $url = "https://accounts.google.com/o/oauth2/auth";

    $params = array(
        "response_type" => "code",
        "client_id" => YOUR_CLIENT_ID,
        "redirect_uri" => 'http://' . $_SERVER["HTTP_HOST"] . $_SERVER["PHP_SELF"],
        "scope" => "https://www.googleapis.com/auth/plus.me"
    );

    $request_to = $url . '?' . http_build_query($params);

    header("Location: " . $request_to);
}

现在,请将 YOUR_CLIENT_IDYOUR_CLIENT_SECRET 替换为您的客户端ID和客户端密钥。
确保您的范围是正确的。例如,如果您想要访问分析,则应该是https://www.googleapis.com/auth/analytics 如果您运行该文件,您应该会得到一个OAuth2批准屏幕。
如果您现在点击 接受,您应该会得到一个类似于这样的结果:
{
  "access_token" : YOUR_ACCESS_TOKEN,
  "token_type" : "Bearer",
  "expires_in" : 3600,
  "refresh_token" : YOUR_REFRESH_TOKEN
}

结果可能会包含其他字段,具体取决于您申请的范围。

你是怎么运行这个文件的?我把它放到了FileZilla上的一个PHP文件中,并在浏览器中执行了它。但对我来说它不起作用。 - Simone
@John Slegers 除了我没有得到refresh_token之外,我的情况下一切都正常。 - Sachin Sarola
如何只获取access_token而不包含bearer或scope等其他字段? - shivaniverma6991

1
我没有看到您的代码有任何问题,但您可能想尝试刷新客户端密钥,看看是否有所帮助。此外,我建议您确切地查看从curl命令返回的响应,我怀疑它是“invalid_grant”。
更好的方法是使用Google的PHP API客户端:

https://code.google.com/p/google-api-php-client/

它可以为您处理大部分通信。那里的示例非常易于使用。它主要取决于您尝试访问哪个谷歌服务。


1
那段代码看起来很熟悉 - 我正在使用大致相同的代码 - 你可以尝试两件事情。
  1. 使用echo将响应输出到浏览器

    echo $json_response;

  2. 获取Fiddler并在调用curl_exec之前使用以下行

    curl_setopt($curl, CURLOPT_PROXY, '127.0.0.1:8888');

遗憾的是,我也没有使它工作 - 我得到的响应是

{ 
     "error" : "invalid_request" 
}

现在,如果有人知道这个有什么问题的话 ;)

0

来自《OAuth 2.0授权协议草案draft-ietf-oauth-v2-20》第4.4.2节

客户端通过在HTTP请求实体主体中使用“application/x-www-form-urlencoded”格式添加以下参数向令牌端点发出请求:

因此,POST的参数应以字符串形式提交,而不是数组。这也在curl_setopt的PHP手册中提到。

因此,您可能希望发布http_build_query($clienttoken_post,'','&'),而不是发布$clienttoken_post。

这可能无法解决您所有的问题,但这可能是朝着正确方向迈出的一步。


0

我遇到了同样的错误,后来发现需要添加

curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);

允许请求跟随重定向可以快速解决它。希望这能帮助其他人!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接