Reputation: 88
What is the python programmatic alternative to the gcloud command line gcloud auth print-identity-token
?
I am trying to invoke Google Cloud Function by http trigger (only for auth users) and i need to pass the identity token in the Authentication header. I have method which works great when i run the code on GCP app engine. However, i struggle to find a way to get this identity token when i run the program on my own machine (where i can create the token with gcloud command line gcloud auth print-identity-token
)
I found how to create access-token according to this answer but i didn't managed to understand how can i create identity-token.
Thank you in advance!
Upvotes: 4
Views: 6849
Reputation: 2744
Code:
import requests
import google.auth
url = "https://oauth2.googleapis.com/token"
creds = google.auth.default()[0]
refresh_token = creds.refresh_token
client_secret = creds._client_secret
client_id = creds._client_id
params = {
"grant_type": "refresh_token",
"client_id": client_id,
"client_secret": client_secret,
"refresh_token": refresh_token,
}
params = "&".join([f"{key}={value}" for key, value in params.items()])
response = requests.post(url=url, params=params)
print(response.json()["id_token"])
So where does this magic come from? I ran:
gcloud config set core/log_http_redact_token false
gcloud auth print-identity-token --log-http
gcloud config set core/log_http_redact_token true
to see which http requests were being sent to google, and re-wrote calling the endpoint in python
. It's no external library that does everything for you, but at least you don't require an entire gcloud
to be installed.
Upvotes: 1
Reputation: 21
Struggled a bit to find the ideal solution for generating the token programatically, but found it in the official documentation itself eventually.
Sharing the python code snippet from the same
import urllib
import google.auth.transport.requests
import google.oauth2.id_token
def make_authorized_get_request(endpoint, audience):
"""
make_authorized_get_request makes a GET request to the specified HTTP endpoint
by authenticating with the ID token obtained from the google-auth client library
using the specified audience value.
"""
# Cloud Functions uses your function's URL as the `audience` value
# audience = https://project-region-projectid.cloudfunctions.net/myFunction
# For Cloud Functions, `endpoint` and `audience` should be equal
req = urllib.request.Request(endpoint)
auth_req = google.auth.transport.requests.Request()
id_token = google.oauth2.id_token.fetch_id_token(auth_req, audience)
req.add_header("Authorization", f"Bearer {id_token}")
response = urllib.request.urlopen(req)
return response.read()
Here's the link, hope it helps. Worked for me.
Upvotes: 1
Reputation: 815
You can run the shell command via subprocess.check_output
from python and use the returned value as well.
This worked for me:
gcloud_itoken = subprocess.check_output(["gcloud","auth", "print-identity-token"])
gcloud_itoken_str = gcloud_itoken.decode().strip()
do_something(gcloud_itoken_str)
Upvotes: 0
Reputation: 31
If you have a service account you can impersonate this is one way to get an ID token in Python from a local/dev machine.
import google.auth
from google.auth.transport.requests import AuthorizedSession
def impersonated_id_token():
credentials, project = google.auth.default(scopes=['https://www.googleapis.com/auth/cloud-platform'])
authed_session = AuthorizedSession(credentials)
sa_to_impersonate = "<SA_NAME>@<GCP_PROJECT>.iam.gserviceaccount.com"
request_body = {"audience": "<SOME_URL>"}
response = authed_session.post( f'https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/{sa_to_impersonate}:generateIdToken',request_body)
return response
if __name__ == "__main__":
print(impersonated_id_token().json())
Upvotes: 0
Reputation: 75715
Great topic! And it's a long long way, and months of tests and discussion with Google.
TL;DR: you can't generate an identity token with your user credential, you need to have a service account (or to impersonate a service) to generate an identity token.
If you have a service account key file, I can share a piece of code to generate an identity token, but generating and having a service account key file is globally a bad practice.
I released an article on this and 2 merge requests to implement an evolution in the Java Google auth library (I'm more Java developer that python developer even if I also contribute to python OSS project) here and here. You can read them if you want to understand what is missing and how works the gcloud command today.
On the latest merge request, I understood that something is coming from google, internally, but up to now, I didn't see anything...
Upvotes: 6