问题
From https://cloud.google.com/translate/docs/basic/setup-basic, there's a need to set the environmental variable:
export GOOGLE_APPLICATION_CREDENTIALS='/path/to/credential.json'
Then a curl request can be made as such:
curl -s -X POST -H "Content-Type: application/json" \
-H "Authorization: Bearer "$(gcloud auth application-default print-access-token) \
--data "{
'q': 'The Great Pyramid of Giza (also known as the Pyramid of Khufu or the
Pyramid of Cheops) is the oldest and largest of the three pyramids in
the Giza pyramid complex.',
'source': 'en',
'target': 'es',
'format': 'text'
}" "https://translation.googleapis.com/language/translate/v2"
Where there is a Bearer
authentication key in the header of the request that comes from the value of the gcloud auth application-default print-access-token
command.
After trying several calls to gcloud auth application-default print-access-token
, every call seems to create a unique token per call.
My questions are ,
How long does the authentication key from
print-access-token
lasts before it expires?Is there a way to create a fix key that isn't dynamically generated from
gcloud auth application-default print-access-token
and without the need to setup the environmental variable?Is there a way to generate the
print-access-token
programmatically without calling thegcloud
command line executable?
There are also seems to be a way to create a static key and use it as described in https://cloud.google.com/docs/authentication/api-keys and e.g. https://github.com/eddiesigner/sketch-translate-me/wiki/Generate-a-Google-API-Key
How can the static key be used in the the curl call in place of the Authorization: Bearer
?
回答1:
How long does the authentication key from print-access-token lasts before it expires?
print-access-token
gives you a Google access token which has a duration of 1 hour. You can check the expiration time using the token info endpoint :
https://www.googleapis.com/oauth2/v3/tokeninfo?access_token=YOUR_ACCESS_TOKEN
Note that the token info works both for checking access_token
and for id_token
Is there a way to create a fix key that isn't dynamically generated from gcloud auth application-default print-access-token and without the need to setup the environmental variable?
The credential file you have downloaded when making request to the translation API is made for service accounts aka server-to-server interactions
It's possible to re-create the flow that is used by the gcloud
CLI using a small script that would :
- build and encode the JWT payload from the data from credentials files (to populate
aud
,iss
,sub
,iat
andexp
) - request an access token using that JWT
- make the request to the API using this access token
The complete guide for this flow is located here: https://developers.google.com/identity/protocols/oauth2/service-account#authorizingrequests
Here is an example in python. You will need to install pycrypto
and pyjwt
to run this script :
import requests
import json
import jwt
import time
#for RS256
from jwt.contrib.algorithms.pycrypto import RSAAlgorithm
jwt.register_algorithm('RS256', RSAAlgorithm(RSAAlgorithm.SHA256))
token_url = "https://oauth2.googleapis.com/token"
credentials_file_path = "./google.json"
#build and sign JWT
def build_jwt(config):
iat = int(time.time())
exp = iat + 3600
payload = {
'iss': config["client_email"],
'sub': config["client_email"],
'aud': token_url,
'iat': iat,
'exp': exp,
'scope': 'https://www.googleapis.com/auth/cloud-platform'
}
jwt_headers = {
'kid': config["private_key_id"],
"alg": 'RS256',
"typ": 'JWT'
}
signed_jwt = jwt.encode(
payload,
config["private_key"],
headers = jwt_headers,
algorithm = 'RS256'
)
return signed_jwt
with open(credentials_file_path) as conf_file:
config = json.load(conf_file)
# 1) build and sign JWT
signed_jwt = build_jwt(config)
# 2) get access token
r = requests.post(token_url, data= {
"grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
"assertion": signed_jwt.decode("utf-8")
})
token = r.json()
print(f'token will expire in {token["expires_in"]} seconds')
at = token["access_token"]
# 3) call translate API
r = requests.post(
"https://translation.googleapis.com/language/translate/v2",
headers = {
"Authorization": f'Bearer {at}'
},
json= {
"q": "The Great Pyramid of Giza (also known as the Pyramid of Khufu or the Pyramid of Cheops) is the oldest and largest of the three pyramids in the Giza pyramid complex.",
"source": "en",
"target": "es",
"format": "text"
})
print(r.json())
Note that in the addendum, it's mentionned that some Google API doesn't need Access token and can work just by using the JWT in the Authorization
header but it doesn't work for this translation API
Also, I guess you would want to use google client library to do the steps above depending on what language you use
How can the static key be used in the the curl call in place of the Authorization: Bearer?
You need to generate an API key in Google console (and have translation API enabled). Then you can use directly :
https://translation.googleapis.com/language/translate/v2?key=YOUR_API_KEY&q=Hello%20world&target=es&alt=json&source=en
Note that using www.googleapis.com
also works :
https://www.googleapis.com/language/translate/v2?key=YOUR_API_KEY&q=Hello%20world&target=es&alt=json&source=en
Using python :
import requests
api_key = "YOUR_API_KEY"
text = "The Great Pyramid of Giza (also known as the Pyramid of Khufu or the Pyramid of Cheops) is the oldest and largest of the three pyramids in the Giza pyramid complex"
r = requests.get(
"https://translation.googleapis.com/language/translate/v2",
params = {
"key": api_key,
"q": text,
"target": "es",
"alt":"json",
"source":"en"
}
)
print(r.json())
Note that you could also use POST
instead of GET
like in the documentation but passing key
as a query parameter :
r = requests.post(
"https://translation.googleapis.com/language/translate/v2",
params = {
"key": api_key
},
json = {
"q": text,
"target": "es",
"alt":"json",
"source":"en"
}
)
print(r.json())
来源:https://stackoverflow.com/questions/62148151/google-translate-api-authentication-key-and-usage