【问题标题】:Invalid JWT when trying to use google cloud Text-to-Speech API尝试使用谷歌云文本转语音 API 时 JWT 无效
【发布时间】:2021-02-10 15:19:20
【问题描述】:

我遵循了这个非常简单的指南:https://cloud.google.com/text-to-speech/docs/quickstart-client-libraries?hl=en

按照python的步骤我没有发现任何问题,但是当我执行示例代码时出现此错误:

/usr/bin/env /usr/bin/python /home/edoelas/.vscode/extensions/ms-python.python-2021.1.502429796/pythonFiles/lib/python/debugpy/launcher 41413 -- /home/edoelas/git/gsdeck/scripts/generateaudio.py 
Traceback (most recent call last):
  File "/home/edoelas/.local/lib/python3.9/site-packages/google/api_core/grpc_helpers.py", line 73, in error_remapped_callable
    return callable_(*args, **kwargs)
  File "/home/edoelas/.local/lib/python3.9/site-packages/grpc/_channel.py", line 923, in __call__
    return _end_unary_response_blocking(state, call, False, None)
  File "/home/edoelas/.local/lib/python3.9/site-packages/grpc/_channel.py", line 826, in _end_unary_response_blocking
    raise _InactiveRpcError(state)
grpc._channel._InactiveRpcError: <_InactiveRpcError of RPC that terminated with:
        status = StatusCode.UNAVAILABLE
        details = "Getting metadata from plugin failed with error: ('invalid_grant: Invalid JWT: Token must be a short-lived token (60 minutes) and in a reasonable timeframe. Check your iat and exp values in the JWT claim.', '{"error":"invalid_grant","error_description":"Invalid JWT: Token must be a short-lived token (60 minutes) and in a reasonable timeframe. Check your iat and exp values in the JWT claim."}')"
        debug_error_string = "{"created":"@1612972534.048677552","description":"Getting metadata from plugin failed with error: ('invalid_grant: Invalid JWT: Token must be a short-lived token (60 minutes) and in a reasonable timeframe. Check your iat and exp values in the JWT claim.', '{"error":"invalid_grant","error_description":"Invalid JWT: Token must be a short-lived token (60 minutes) and in a reasonable timeframe. Check your iat and exp values in the JWT claim."}')","file":"src/core/lib/security/credentials/plugin/plugin_credentials.cc","file_line":90,"grpc_status":14}"
>

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/edoelas/git/gsdeck/scripts/generateaudio.py", line 27, in <module>
    response = client.synthesize_speech(
  File "/home/edoelas/.local/lib/python3.9/site-packages/google/cloud/texttospeech_v1/services/text_to_speech/client.py", line 374, in synthesize_speech
    response = rpc(request, retry=retry, timeout=timeout, metadata=metadata,)
  File "/home/edoelas/.local/lib/python3.9/site-packages/google/api_core/gapic_v1/method.py", line 145, in __call__
    return wrapped_func(*args, **kwargs)
  File "/home/edoelas/.local/lib/python3.9/site-packages/google/api_core/grpc_helpers.py", line 75, in error_remapped_callable
    six.raise_from(exceptions.from_grpc_error(exc), exc)
  File "<string>", line 3, in raise_from
google.api_core.exceptions.ServiceUnavailable: 503 Getting metadata from plugin failed with error: ('invalid_grant: Invalid JWT: Token must be a short-lived token (60 minutes) and in a reasonable timeframe. Check your iat and exp values in the JWT claim.', '{"error":"invalid_grant","error_description":"Invalid JWT: Token must be a short-lived token (60 minutes) and in a reasonable timeframe. Check your iat and exp values in the JWT claim."}')

我对谷歌云 API 没有任何经验。我不知道 JWT 何时生成或是否存在问题。我还检查了我的系统的时间,它看起来很好,除非我必须设置一个不同的时间来匹配谷歌云控制台中的时间或类似的东西。

编辑: 我没有使用服务帐户在任何地方手动进行身份验证,我只是按照指南中的说明设置了环境变量 GOOGLE_APPLICATION_CREDENTIALS。

我认为我可能会做一些奇怪的事情是在初始化 Cloud SDK 时。我只是去终端,写gcloud init创建一个新的配置,选择我创建这个服务帐户的google帐户,选择服务帐户所在的项目就可以了。

我没有设置 venv,因为据我所知,这对隔离 python 库很有用。

代码与指南中使用的代码相同:

"""Synthesizes speech from the input string of text or ssml.

Note: ssml must be well-formed according to:
    https://www.w3.org/TR/speech-synthesis/
"""
from google.cloud import texttospeech

# Instantiates a client
client = texttospeech.TextToSpeechClient()

# Set the text input to be synthesized
synthesis_input = texttospeech.SynthesisInput(text="Hello, World!")

# Build the voice request, select the language code ("en-US") and the ssml
# voice gender ("neutral")
voice = texttospeech.VoiceSelectionParams(
    language_code="en-US", ssml_gender=texttospeech.SsmlVoiceGender.NEUTRAL
)

# Select the type of audio file you want returned
audio_config = texttospeech.AudioConfig(
    audio_encoding=texttospeech.AudioEncoding.MP3
)

# Perform the text-to-speech request on the text input with the selected
# voice parameters and audio file type
response = client.synthesize_speech(
    input=synthesis_input, voice=voice, audio_config=audio_config
)

# The response's audio_content is binary.
with open("output.mp3", "wb") as out:
    # Write the response to the output file.
    out.write(response.audio_content)
    print('Audio content written to file "output.mp3"')

编辑 2:

当我按照 CLI 快速入门指南运行命令时:

curl -X POST \
-H "Authorization: Bearer "$(gcloud auth application-default print-access-token) \
-H "Content-Type: application/json; charset=utf-8" \
-d @request.json \
https://texttospeech.googleapis.com/v1/text:synthesize

我明白了:

ERROR: (gcloud.auth.application-default.print-access-token) There was a problem refreshing your current auth tokens: ('invalid_grant: Invalid JWT: Token must be a short-lived token (60 minutes) and in a reasonable timeframe. Check your iat and exp values in the JWT claim.', '{"error":"invalid_grant","error_description":"Invalid JWT: Token must be a short-lived token (60 minutes) and in a reasonable timeframe. Check your iat and exp values in the JWT claim."}')
Please run:

  $ gcloud auth application-default login

to obtain new credentials.
{
  "error": {
    "code": 403,
    "message": "The request is missing a valid API key.",
    "status": "PERMISSION_DENIED"
  }
}

当运行gcloud auth application-default login 时,会显示:

The environment variable [GOOGLE_APPLICATION_CREDENTIALS] is set to:
  [/home/edoelas/git/gsdeck/credentials/service_account.json]
Credentials will still be generated to the default location:
  [/home/edoelas/.config/gcloud/application_default_credentials.json]
To use these credentials, unset this environment variable before
running your application.

Do you want to continue (Y/n)?  Y    

Your browser has been opened to visit:

    https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=764086051850-6qr4p6gpi6hn506pt8ejuq83di341hur.apps.googleusercontent.com&redirect_uri=http%3A%2F%2Flocalhost%3A8085%2F&scope=openid+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-platform+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Faccounts.reauth&state=jAxmGRv50BQxjUy1acQvcs6Pyp2jNM&access_type=offline&code_challenge=gjZ5y5t3T7b2M0lhvL5Eqwhfag6i7c91oEjcc2Tw5CA&code_challenge_method=S256

Opening in existing browser session.

Credentials saved to file: [/home/edoelas/.config/gcloud/application_default_credentials.json]

These credentials will be used by any library that requests Application Default Credentials (ADC).
/opt/google-cloud-sdk/lib/third_party/google/auth/_default.py:69: UserWarning: Your application has authenticated using end user credentials from Google Cloud SDK without a quota project. You might receive a "quota exceeded" or "API not enabled" error. We recommend you rerun `gcloud auth application-default login` and make sure a quota project is added. Or you can use service accounts instead. For more information about service accounts, see https://cloud.google.com/docs/authentication/
  warnings.warn(_CLOUD_SDK_CREDENTIALS_WARNING)

Quota project "gsdeck" was added to ADC which can be used by Google client libraries for billing and quota. Note that some services may still bill the project owning the resource.

【问题讨论】:

  • 您是否使用service account 进行身份验证?在运行示例之前,您是否设置了 thisdocumentation 中提到的 Python 开发环境?请分享您正在使用的代码。
  • 另外我建议您尝试使用command line quick-start 并在此处分享结果。
  • 根据您的建议编辑了主帖。
  • 通常“缺少有效的 API 密钥”表示您没有为用于进行 API 调用的服务帐户设置身份验证。如果您完全按照提到的所有步骤进行操作,那么您应该在第 4 步结束时下载了一个 JSON 文件,选择您正在使用的正确操作系统并检查第 5 步以将环境变量 GOOGLE_APPLICATION_CREDENTIALS 设置为文件路径包含您的服务帐户密钥的 JSON 文件。打开新会话而不重新设置变量或输入错误的路径可能会导致您遇到的错误。
  • 看看这个post你可以试试那里提供的解决方法

标签: python google-cloud-platform


【解决方案1】:

我在 JWT 令牌中看到的主要原因之一是生成令牌的服务器与它尝试与之通信的客户端不同步。

您能否确保您的系统时间同步并且配置为保持自身更新to a NTP server?

【讨论】:

  • 可能是因为我的系统区域设置为 LC_TIME="en_GB.UTF-8" 但我不住在那里,我将系统时间调整为与我住的地方相同?
  • 因此,如果您不在系统上设置的时区并且您已手动将其更新为您的时间,那么这实际上不是正确的方法,因为时区会仍然是 UTC -8。当要生成 JWT 令牌时,它们会生成带有纪元的令牌,即UTC+0,这会导致您配置的时间与实际当前 UTC 时间发生偏差。这将导致令牌来自未来或过去。我建议您更改时区,然后更正您的时间。如果您需要有关配置的帮助,请告诉我基本操作系统。
  • 我正在使用 Arch linux。我已将 LC_TIME 变量更改为 es_ES.UTF-8(我的国家),但问题仍然存在。
  • wiki.archlinux.org/index.php/System_time 应该可以帮助您了解时间配置。
  • 天哪,是时候了,我的系统中有很多与时间有关的事情搞砸了。谢谢,我会将您的问题标记为解决方案。我最终更改了系统时区并使用了这个问题的答案:unix.stackexchange.com/questions/60772/… 与我所在地区的确切时间进行同步。
猜你喜欢
  • 1970-01-01
  • 2019-03-13
  • 1970-01-01
  • 2018-02-14
  • 2023-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-08
相关资源
最近更新 更多