python - HttpAccessTokenRefreshError : invalid_grant . .. 一小时限制刷新 token

标签 python google-sheets oauth-2.0 google-oauth google-sheets-api

我已经查看了关于此主题的其他问题,它似乎与我的错误不符。运行 Google Sheets APIv4 时出现错误:

引发 HttpAccessTokenRefreshError(error_msg, status=resp.status) HttpAccessTokenRefreshError:invalid_grant

service.spreadsheets().values().get(spreadsheetId=key, range=ranges).execute() 行发生错误

这个错误只是偶尔弹出。如果我什么都不做,只是再次运行代码。它将带我再次完成身份验证流程,然后我得到

验证成功。 将凭据存储到 C:\Users\jason\.credentials\sheets.googleapis.com-python-quickstart.json

之后,我可以运行任何代码一段时间,直到相同的 HttpAccessTokenRefreshError: invalid_grant 再次弹出,我必须再次重新验证。

如何防止这种情况?

我正在使用 developers.google.com/sheets/api/quickstart/python 中的代码。

我尝试使用ntp 来同步时间

import time
import os
try:
    import ntplib
    client = ntplib.NTPClient()
    response = client.request('pool.ntp.org')
    os.system('date ' + time.strftime('%m%d%H%M%Y.%S',time.localtime(response.tx_time)))
except:
    print('Could not sync with time server.')

print('Done.')

但得到:

The system cannot accept the date entered.
Enter the new data: (mm-dd-yy)

在我输入当前日期后,没有任何反应。

我也看过这个页面。 https://blog.timekit.io/google-oauth-invalid-grant-nightmare-and-how-to-fix-it-9f4efaf1da35#.5utz2vcn6

当我运行超过 1 小时才能完成的代码时,也会出现此问题。在刷新 token 上。它总是炸弹。

现在我在想,授予的 token 只持续一个小时,刷新时,它总是炸弹。

我已经发布了连接代码:

class APIv4:
    def __init__(self):
    credentials = get_credentials()
    http = credentials.authorize(httplib2.Http())
    discoveryUrl = ('https://sheets.googleapis.com/$discovery/rest?'
                    'version=v4')
    self.service = discovery.build('sheets', 'v4', http=http,
                              discoveryServiceUrl=discoveryUrl)

def get_credentials():
    """Gets valid user credentials from storage.

    If nothing has been stored, or if the stored credentials are invalid,
    the OAuth2 flow is completed to obtain the new credentials.

    Returns:
        Credentials, the obtained credential.
    """
    home_dir = os.path.expanduser('~')
    credential_dir = os.path.join(home_dir, '.credentials')
    if not os.path.exists(credential_dir):
        os.makedirs(credential_dir)
    credential_path = os.path.join(credential_dir,
                                   'sheets.googleapis.com-python-quickstart.json')

    store = Storage(credential_path)
    credentials = store.get()
    if not credentials or credentials.invalid:
        flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)
        flow.user_agent = APPLICATION_NAME
        if flags:
            credentials = tools.run_flow(flow, store, flags)
        else: # Needed only for compatibility with Python 2.6
            credentials = tools.run(flow, store)
        print('Storing credentials to ' + credential_path)
    return credentials

最佳答案

一般来说,调用之间访问 token 的刷新似乎有问题。

这要么意味着您的某些凭据未正确传递,要么您的本地计算机时间存在问题(尽管似乎比第一个选项可能性小)

我建议研究本期中所述的可能性:https://github.com/google/oauth2client/issues/451 :

  1. (不太可能)您为什么不尝试使用 ntpdate 强制更新时钟。安装 ntp 并尝试一下,因为一位用户表示这对他有用
  2. Ok. After a loong research I guess I found out the problem. In fact, refresh_token was missing from the user credential, but the issue was tricky.

    The refresh token is given for the FIRST time when the application asks the user for permissions. The refresh token is given ONLY IF the flow's step 1 includes the parameters approval_prompt="force"

    For some reason the user (me) hadn't got refresh_token in user's credentials, so I revoked permissions from the application on My Account -> Security -> Applications, and restarted the OAuth dance again. Now I got refresh_token.

#2 选项的更新:

关注此guide以及上述建议,我相信您必须添加到此代码片段(直接取自指南):

# Create a state token to prevent request forgery.
# Store it in the session for later validation.
state = hashlib.sha256(os.urandom(1024)).hexdigest()
session['state'] = state
# Set the client ID, token state, and application name in the HTML while
# serving it.
response = make_response(
    render_template('index.html',
                    CLIENT_ID=CLIENT_ID,
                    STATE=state,
                    APPLICATION_NAME=APPLICATION_NAME))

prompt=consent 行,然后执行上面引用的响应的第三步(选项 2)。

另一种选择是使用 approval_prompt=force 但您必须在两者之间做出选择,因为它们不能很好地协同工作。

祝你好运:)

关于python - HttpAccessTokenRefreshError : invalid_grant . .. 一小时限制刷新 token ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42616050/

相关文章:

javascript - 在 Google Apps 脚本中,无法以编程方式创建触发器以从 onEdit 触发器发送电子邮件

javascript - Google Sheet 脚本显然没有返回数字

oauth-2.0 - OAuth 自定义提供程序 C#

python - 更改Python比较字符串时的默认逻辑

javascript - 自定义编码字符串

spring-security - 升级到 springBootVersion = '1.3.3.RELEASE' 后使用 RestTemplate 出现异常

angular - OAuth2 使用 Angular angular-oauth2-oidc 和 SSO

python - 如果 GIL 存在,Python 中的多线程有什么意义?

python - Python 3.4'无法分配给函数调用

python - 从 Python 调用 CAPL 函数