【问题标题】:Google API PHP offline access, "invalid_grant: Code was already redeemed"Google API PHP 离线访问,“invalid_grant:代码已兑换”
【发布时间】:2018-01-08 21:46:32
【问题描述】:

如何在用户撤销授权之前永久授权 Google 客户端?

我正在尝试制作一个连接到 Google 日历的应用。它必须在 PHP 中运行,因此我使用的是 google 提供的 Google API PHP 客户端。

应用需要离线访问,以便在用户不在会话中时运行。该应用旨在让用户在网站等上公开管理和显示他的日历。

我使用服务方法(使用客户端 ID 和客户端密码)在 Google 控制台中创建了凭据。使用 Google API 客户端,我还请求用户授权。我打开一个新的浏览器窗口,用户授权,谷歌返回一个授权码。我将这段代码存储起来并使用它来授权客户端,该客户端成功连接到 Google 日历并交换数据。

现在,我知道这是一个即将过期的令牌。除非使用我设置的离线访问。但是,几分钟或更短的时间后,我总是会收到错误消息:Error fetching OAuth2 access token, message: 'invalid_grant: Code was already redeemed.

这是我用来连接客户端的代码:

$client = new \Google_Client();
$client->setApplicationName( 'My App' );
$client->setScopes( array( \Google_Service_Calendar::CALENDAR ) );
$client->setClientId( $this->google_client_id );
$client->setClientSecret( $this->google_client_secret );
$client->setRedirectUri( $this->google_client_redirect );
$client->setAccessType( 'offline' );

if ( $code = $this->google_client_auth ) {

    try {

        $client->authenticate( $code );

    } catch( \Exception $e ) {
            var_dump( $e );
    }    

}

return new \Google_Service_Calendar( $client );

这是一个类中的方法。

客户端 ID 和客户端密码存储在应用设置中。

我还将用户返回的代码存储在一个设置中,但我认为这是我做错的地方?我将指向 Google OAuth 窗口的链接放在一个单独的方法中(它也使用相同的客户端 ID 和密码,并设置离线方法)。并且获得授权正在工作。我可以访问日历。它不会持续很长时间......

【问题讨论】:

    标签: php oauth google-api google-oauth google-api-php-client


    【解决方案1】:

    Google 身份验证服务器返回三种类型的代码或令牌。

    1. 验证码
    2. 访问令牌
    3. 刷新令牌。

    验证码

    当用户单击身份验证表单并授予您的应用程序访问权限时。 Google 会向您返回一个验证码。您应该使用此代码并将其交换为访问令牌和刷新令牌。此代码仅使用一次,如果您再次尝试使用,则会收到错误消息。

    invalid_grant:代码已被兑换。

    访问令牌

    访问令牌用于访问 API,此令牌应与您发出的每个请求一起发送。访问令牌是短暂的,它们会工作一个小时,然后就会停止工作

    刷新令牌

    刷新令牌应该保存在您的服务器上的某个地方。访问令牌过期后,您可以使用刷新令牌获取新的访问令牌。

    您的问题是您正在保存对您无用的身份验证代码。您需要找到刷新令牌并保存它。

    【讨论】:

    • 谢谢...但是为什么我需要立即访问令牌和刷新令牌?该api有两个方法getAccessToken和getRefreshToken。但只有一个setter setAccessToken。当我从用户那里获得 Auth 代码时,我可以运行 getAuth()->authenticate 但 API 没有说明它返回的是访问令牌还是刷新令牌。我是否需要将 getAuth->authenticate 的结果传递给 setAccessToken?那么 getAccessToken 有什么用呢?
    • 另外,从 Google PHP API 看来,访问令牌是一个 json 对象,但刷新令牌是一个字符串?那么我是否必须将刷新令牌传递给 getAuth->authenticate() 方法?
    猜你喜欢
    • 2017-12-08
    • 2015-05-17
    • 2013-09-27
    • 2016-09-04
    • 1970-01-01
    • 2016-06-18
    • 1970-01-01
    • 2015-05-25
    • 1970-01-01
    相关资源
    最近更新 更多