【问题标题】:python-fitbit API update tokenspython-fitbit API 更新令牌
【发布时间】:2017-10-10 19:48:06
【问题描述】:

python-fitbit API 的The docs 建议将“refresh_cb”函数作为参数传递,这样我们就不必在每次想要访问 Fitbit API 时手动检索访问令牌、刷新令牌和 expires_at 变量。我已将这些值放入环境变量中,每次手动检索这些值时,我都可以成功访问我的 Fitbit 信息。但是,我不明白 refresh_cb 函数应该做什么或返回什么。我知道这意味着我要保存新令牌,但我只是尝试将环境变量更改为新值,当我尝试执行除此之外的任何操作时,它仍然会引发 (Invalid grant) 错误。到目前为止,这是我的代码:

from fitbit import Fitbit
import os

CLIENT_ID = os.environ['client_id']
SECRET = os.environ['secret']
ACCESS_TOKEN = os.environ['access_token']
EXPIRES_AT = os.environ['expires_in']
REFRESH_TOKEN = os.environ['refresh_token']
USER_ID = os.environ['user_id']


def refresh_cb(token_dict):
    """Function for refreshing access_token, refresh_token, and expires_at."""
    os.environ['access_token'] = token_dict['access_token']
    os.environ['expires_at'] = str(token_dict['expires_at'])
    os.environ['refresh_token'] = token_dict['refresh_token']

    return token_dict

kurt = Fitbit(
    CLIENT_ID,
    SECRET,
    access_token=ACCESS_TOKEN,
    refresh_token=REFRESH_TOKEN,
    expires_at=EXPIRES_AT,
    refresh_cb=refresh_cb
)

文档是这样说的:

我们还强烈建议传入一个 refresh_cb 关键字参数, 这应该是一个接受一个参数的函数:一个令牌字典。什么时候 该参数存在,我们将自动刷新访问 需要时令牌并调用此函数,以便您可以保存 更新的令牌数据。如果您不保存更新的信息,那么 您最终可能会得到无效的访问和刷新令牌,并且唯一的 从中恢复的方法是重新授权用户。如果你有一个 工作示例或可以为我指明正确的方向,我真的 欣赏它。

编辑:

这是我得到的完整回溯:

TokenExpiredError                         Traceback (most recent call last)
~/Projects/kurt_data/ENV/lib/python3.6/site-packages/requests_oauthlib/oauth2_session.py in request(self, method, url, data, headers, withhold_token, client_id, client_secret, **kwargs)
    329                 url, headers, data = self._client.add_token(url,
--> 330                         http_method=method, body=data, headers=headers)
    331             # Attempt to retrieve and save new access token if expired

~/Projects/kurt_data/ENV/lib/python3.6/site-packages/oauthlib/oauth2/rfc6749/clients/base.py in add_token(self, uri, http_method, body, headers, token_placement, **kwargs)
    192         if self._expires_at and self._expires_at < time.time():
--> 193             raise TokenExpiredError()
    194 

TokenExpiredError: (token_expired) 

During handling of the above exception, another exception occurred:

InvalidGrantError                         Traceback (most recent call last)
<ipython-input-3-c92ce9c67530> in <module>()
----> 1 sleep = kurt.sleep()

~/Projects/kurt_data/ENV/lib/python3.6/site-packages/fitbit/utils.py in _curried(*moreargs, **morekwargs)
     36 def curry(_curried_func, *args, **kwargs):
     37     def _curried(*moreargs, **morekwargs):
---> 38         return _curried_func(*(args+moreargs), **dict(kwargs, **morekwargs))
     39     return _curried

~/Projects/kurt_data/ENV/lib/python3.6/site-packages/fitbit/api.py in _COLLECTION_RESOURCE(self, resource, date, user_id, data)
    313             base_url = "{0}/{1}/user/{2}/{resource}.json"
    314         url = base_url.format(*self._get_common_args(user_id), **kwargs)
--> 315         return self.make_request(url, data)
    316 
    317     def _DELETE_COLLECTION_RESOURCE(self, resource, log_id):

~/Projects/kurt_data/ENV/lib/python3.6/site-packages/fitbit/api.py in make_request(self, *args, **kwargs)
    221 
    222         method = kwargs.get('method', 'POST' if 'data' in kwargs else 'GET')
--> 223         response = self.client.make_request(*args, **kwargs)
    224 
    225         if response.status_code == 202:

~/Projects/kurt_data/ENV/lib/python3.6/site-packages/fitbit/api.py in make_request(self, url, data, method, **kwargs)
     94             client_id=self.client_id,
     95             client_secret=self.client_secret,
---> 96             **kwargs
     97         )
     98 

~/Projects/kurt_data/ENV/lib/python3.6/site-packages/fitbit/api.py in _request(self, method, url, **kwargs)
     66 
     67         try:
---> 68             response = self.session.request(method, url, **kwargs)
     69 
     70             # If our current token has no expires_at, or something manages to slip

~/Projects/kurt_data/ENV/lib/python3.6/site-packages/requests_oauthlib/oauth2_session.py in request(self, method, url, data, headers, withhold_token, client_id, client_secret, **kwargs)
    341                         auth = requests.auth.HTTPBasicAuth(client_id, client_secret)
    342                     token = self.refresh_token(
--> 343                         self.auto_refresh_url, auth=auth, **kwargs
    344                     )
    345                     if self.token_updater:

~/Projects/kurt_data/ENV/lib/python3.6/site-packages/requests_oauthlib/oauth2_session.py in refresh_token(self, token_url, refresh_token, body, auth, timeout, headers, verify, proxies, **kwargs)
    307             r = hook(r)
    308 
--> 309         self.token = self._client.parse_request_body_response(r.text, scope=self.scope)
    310         if not 'refresh_token' in self.token:
    311             log.debug('No new refresh token given. Re-using old.')

~/Projects/kurt_data/ENV/lib/python3.6/site-packages/oauthlib/oauth2/rfc6749/clients/base.py in parse_request_body_response(self, body, scope, **kwargs)
    406         .. _`Section 7.1`: http://tools.ietf.org/html/rfc6749#section-7.1
    407         """
--> 408         self.token = parse_token_response(body, scope=scope)
    409         self._populate_attributes(self.token)
    410         return self.token

~/Projects/kurt_data/ENV/lib/python3.6/site-packages/oauthlib/oauth2/rfc6749/parameters.py in parse_token_response(body, scope)
    377 
    378     params = OAuth2Token(params, old_scope=scope)
--> 379     validate_token_parameters(params)
    380     return params
    381 

~/Projects/kurt_data/ENV/lib/python3.6/site-packages/oauthlib/oauth2/rfc6749/parameters.py in validate_token_parameters(params)
    384     """Ensures token precence, token type, expiration and scope in params."""
    385     if 'error' in params:
--> 386         raise_from_error(params.get('error'), params)
    387 
    388     if not 'access_token' in params:

~/Projects/kurt_data/ENV/lib/python3.6/site-packages/oauthlib/oauth2/rfc6749/errors.py in raise_from_error(error, params)
    404     for _, cls in inspect.getmembers(sys.modules[__name__], inspect.isclass):
    405         if cls.error == error:
--> 406             raise cls(**kwargs)

InvalidGrantError: (invalid_grant)

【问题讨论】:

    标签: python python-3.x fitbit


    【解决方案1】:

    据我了解,您需要像这样刷新全局python变量(不是环境变量)

    def refresh_cb(token_dict):
        """Function for refreshing access_token, refresh_token, and expires_at."""
        global ACCESS_TOKEN
        global EXPIRES_AT
        global REFRESH_TOKEN
        ACCESS_TOKEN = token_dict['access_token']
        EXPIRES_AT = str(token_dict['expires_at'])
        REFRESH_TOKEN = token_dict['refresh_token']
    
        return token_dict
    

    【讨论】:

    • 我尝试了您的建议,但仍然收到同样的错误。我基本上只是将Fitbit 类实例化到变量kurt 中,然后尝试获取一些数据。据我了解,如果refresh_cb函数是正确的,那么它将获取新的令牌并使用提供的函数来保存它们。
    【解决方案2】:

    为了后代,这个问题has been discussed在项目的问题跟踪器上。

    【讨论】:

      猜你喜欢
      • 2016-08-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-09
      • 2020-05-12
      • 2018-11-19
      • 2023-04-01
      相关资源
      最近更新 更多