python中的Firestore客户端(作为用户)使用firebase_admin或google.cloud.fire



我正在构建一个使用Firestore的python客户端应用程序。我已经成功地使用Google身份平台注册和登录到Firebase项目,并使用Google .cloud. Firestore . client创建了一个工作的Firebase客户端,该客户端被认证为用户:

import json
import requests
import google.oauth2.credentials
from google.cloud import firestore
request_url = f"https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key={self.__api_key}"
headers = {"Content-Type": "application/json; charset=UTF-8"}
data = json.dumps({"email": self.__email, "password": self.__password, "returnSecureToken": True})
response = requests.post(request_url, headers=headers, data=data)
try:
response.raise_for_status()
except (HTTPError, Exception):
content = response.json()
error = f"error: {content['error']['message']}"
raise AuthError(error)
json_response = response.json()
self.__token = json_response["idToken"]
self.__refresh_token = json_response["refreshToken"]
credentials = google.oauth2.credentials.Credentials(self.__token,
self.__refresh_token,
client_id="",
client_secret="",
token_uri=f"https://securetoken.googleapis.com/v1/token?key={self.__api_key}"
)
self.__db = firestore.Client(self.__project_id, credentials)

我有问题,但是,当令牌过期时,我得到以下错误:

Traceback (most recent call last):
File "/usr/local/lib/python3.7/dist-packages/google/api_core/grpc_helpers.py", line 57, in error_remapped_callable
return callable_(*args, **kwargs)
File "/usr/local/lib/python3.7/dist-packages/grpc/_channel.py", line 826, in __call__
return _end_unary_response_blocking(state, call, False, None)
File "/usr/local/lib/python3.7/dist-packages/grpc/_channel.py", line 729, in _end_unary_response_blocking
raise _InactiveRpcError(state)
grpc._channel._InactiveRpcError: <_InactiveRpcError of RPC that terminated with:
status = StatusCode.UNAUTHENTICATED
details = "Missing or invalid authentication."
debug_error_string = "{"created":"@1613043524.699081937","description":"Error received from peer ipv4:172.217.16.74:443","file":"src/core/lib/surface/call.cc","file_line":1055,"grpc_message":"Missing or invalid authentication.","grpc_status":16}"
>
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/usr/lib/python3.7/threading.py", line 917, in _bootstrap_inner
self.run()
File "/home/my_app/src/controllers/im_alive.py", line 20, in run
self.__device_api.set_last_updated(utils.device_id())
File "/home/my_app/src/api/firestore/firestore_device_api.py", line 21, in set_last_updated
"lastUpdatedTime": self.__firestore.SERVER_TIMESTAMP
File "/home/my_app/src/api/firestore/firestore.py", line 100, in update
ref.update(data)
File "/usr/local/lib/python3.7/dist-packages/google/cloud/firestore_v1/document.py", line 382, in update
write_results = batch.commit()
File "/usr/local/lib/python3.7/dist-packages/google/cloud/firestore_v1/batch.py", line 147, in commit
metadata=self._client._rpc_metadata,
File "/usr/local/lib/python3.7/dist-packages/google/cloud/firestore_v1/gapic/firestore_client.py", line 1121, in commit
request, retry=retry, timeout=timeout, metadata=metadata
File "/usr/local/lib/python3.7/dist-packages/google/api_core/gapic_v1/method.py", line 145, in __call__
return wrapped_func(*args, **kwargs)
File "/usr/local/lib/python3.7/dist-packages/google/api_core/retry.py", line 286, in retry_wrapped_func
on_error=on_error,
File "/usr/local/lib/python3.7/dist-packages/google/api_core/retry.py", line 184, in retry_target
return target()
File "/usr/local/lib/python3.7/dist-packages/google/api_core/timeout.py", line 214, in func_with_timeout
return func(*args, **kwargs)
File "/usr/local/lib/python3.7/dist-packages/google/api_core/grpc_helpers.py", line 59, in error_remapped_callable
six.raise_from(exceptions.from_grpc_error(exc), exc)
File "<string>", line 3, in raise_from
google.api_core.exceptions.Unauthenticated: 401 Missing or invalid authentication.

我尝试省略令牌,只指定刷新令牌,然后调用credentials.refresh(),但https://securetoken.googleapis.com/v1/token端点响应中的expires_in是字符串而不是数字(这里的文档),这使得google.oauth2._client.py:257中的_parse_expiry(response_data)引发异常。

是否有任何方法可以使用firestore.Clientgoogle.cloudfirebase_admin,并让它自动处理刷新令牌,或者我需要切换到手动调用Firestore RPC API和在正确的时间刷新令牌?

注意:没有用户与python应用程序交互,因此解决方案必须不需要用户交互。

你不能直接把字符串转换为整数_parse_expiry(int(float(response_data)))吗?

如果它不工作,您可以尝试在获得错误401后进行调用并刷新令牌,请参阅我对如何处理令牌的一般想法的回答。

正如@Marco所提到的,如果要在没有用户的环境中使用服务帐户,建议您使用该帐户。当您使用服务帐户时,您可以将GOOGLE_APPLICATION_CREDENTIALS环境变量设置为服务帐户json文件的位置,并且只需实例化没有任何凭据的firestore Client(凭据将自动拾取):

import firestore
client = firestore.Client()

并运行它(假设Linux):

$ export GOOGLE_APPLICATION_CREDENTIALS=/path/to/credentials.json
$ python file.py

但是,如果您真的想为脚本使用用户凭据,您可以安装Google Cloud SDK,然后:

$ gcloud auth application-default login

这将打开浏览器,让您选择帐户和登录。登录后,它会创建一个"虚拟"与您的用户帐户对应的服务帐户文件(也将由客户端自动加载)。这里也不需要向客户端传递任何参数。

参见:" gcloud auth application-default login "one_answers" gcloud auth login "的区别

最新更新