How to get a GCP Bearer token programmatically with python

gcloud auth print-identity-token
gcloud log http redact token
google oauth
python gcp authentication
google-auth python example
python get google-auth token
get access token from refresh token google api
log_http_redact_token

gcloud auth print-access-token gives me a Bearer token that I can use later on; however, this is a shell command. How would I obtain one programmatically via the Google Cloud Python API?

I see a prior example using oauth2client, but oauth2client is now deprecated. How would I do this with google.auth and oauthlib?

The answer depends on your environment and how you want to create / obtain credentials.

What are Google Cloud Credentials?

Google Cloud credentials are an OAuth 2.0 token. This token has at a minimum an Access Token and optionally a Refresh Token, Client ID Token, and supporting parameters such as expiration, Service Account Email or Client Email, etc.

The important item in Google Cloud APIs is the Access Token. This token is what authorizes access to the cloud. This token can be used in programs such as curl, software such as python, etc and does not require an SDK. The Access Token is used in the HTTP Authorization header.

What is an Access Token?

An access token is an opaque value generated by Google that is derived from a Signed JWT, more correctly called JWS. A JWT consists of a header and claims (the payload) Json structures. These two Json structures are signed with the Service Account's Private Key. These values are base64 encoded and concatenated to create the Access Key.

The format of an Access Token is: base64(header) + '.' + base64(payload) + '.' + base64(signature).

Here is an example JWT:

Header:

{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "42ba1e234ac91ffca687a5b5b3d0ca2d7ce0fc0a"
}

Payload:

{
  "iss": "myservice@myproject.iam.gserviceaccount.com",
  "iat": 1493833746,
  "aud": "myservice.appspot.com",
  "exp": 1493837346,
  "sub": "myservice@myproject.iam.gserviceaccount.com"
}

Using an Access Token:

Example that will start a VM instance. Replace PROJECT_ID, ZONE and INSTANCE_NAME. This example is for Windows.

curl -v -X GET -H "Authorization: Bearer <access_token_here>" ^
https://www.googleapis.com/compute/v1/projects/%PROJECT_ID%/zones/%ZONE%/instances/%INSTANCE_NAME%/start

Compute Engine Service Account:

Dustin's answer is correct for this case, but I will include for completeness with some additional information.

These credentials are automatically created for you by GCP and are obtained from the VM Instance metadata. Permissions are controlled by Cloud API access scopes in the Google Console.

However, these credentials have some limitations. To modify the credentials you must stop the VM Instance first. Additionally, not all permissions (roles) are supported.

from google.auth import compute_engine

cred = compute_engine.Credentials()

Service Account Credentials:

Until you understand all of the types of credentials and their use cases, these are the credentials that you will use for everything except for gcloud and gsutil. Understanding these credentials will make working with Google Cloud much simpler when writing programs. Obtaining credentials from a Google Service Account Json file is easy. The only item to make note of is that credentials expire (typically 60 minutes) and either need to be refreshed or recreated.

gcloud auth print-access-token is NOT recommended. Service Account Credentials are the recommended method by Google.

These credentials are created by the Console, gcloud or via programs / APIs. Permissions are assigned to the creditials by IAM and function inside Compute Engine, App Engine, Firestore, Kubernetes, etc. as well as other environments outside of Google Cloud. These credentials are downloaded from Google Cloud and stored in a Json file. Notice the scopes parameter. This defines permissions that are granted to the resulting credentials object.

SCOPES = ['https://www.googleapis.com/auth/sqlservice.admin']
SERVICE_ACCOUNT_FILE = 'service-account-credentials.json'

from google.oauth2 import service_account

cred = service_account.Credentials.from_service_account_file(
            SERVICE_ACCOUNT_FILE, scopes=SCOPES)

Google OAuth 2.0 Credentials:

These credentials are derived from a full OAuth 2.0 flow. These credentials are generated when your browser is launched to access Google Accounts for authorizing access. This process is much more complicated and requires a fair amount of code to implement and requires a built-in web server for the callback for authorization.

This method provides additional features such as being able to run everything in a browser, example you can create a Cloud Storage File Browser, but be careful that you understand the security implications. This method is the technique used to support Google Sign-In, etc. I like to use this method to authenticate users before allowing posting on websites, etc. The possibilities are endless with correctly authorized OAuth 2.0 identities and scopes.

Example code using google_auth_oauthlib:

from google_auth_oauthlib.flow import InstalledAppFlow

flow = InstalledAppFlow.from_client_secrets_file(
    'client_secrets.json',
    scopes=scope)

cred = flow.run_local_server(
    host='localhost',
    port=8088,
    authorization_prompt_message='Please visit this URL: {url}',
    success_message='The auth flow is complete; you may close this window.',
    open_browser=True)

Example code using the requests_oauthlib library:

from requests_oauthlib import OAuth2Session

gcp = OAuth2Session(
        app.config['gcp_client_id'],
        scope=scope,
        redirect_uri=redirect_uri)

# print('Requesting authorization url:', authorization_base_url)

authorization_url, state = gcp.authorization_url(
                        authorization_base_url,
                        access_type="offline",
                        prompt="consent",
                        include_granted_scopes='true')

session['oauth_state'] = state

return redirect(authorization_url)


# Next section of code after the browser approves the request

token = gcp.fetch_token(
            token_url,
            client_secret=app.config['gcp_client_secret'],
            authorization_response=request.url)

How to obtain a GCP Bearer token programatically, How can i obtain such a token without the use of gcloud, preferably through some python code. #!/usr/bin/python from oauth2client.client import  Every Compute Engine instance stores its metadata on a metadata server. You can query this metadata server programmatically from within the instance for information about the instance such as service account information. You can request an access token from the metadata server in Python like so:

While the above answer is quite informative, it misses one important point - credentials object obtained from google.auth.default() or compute_engine.Credentials() will not have token in it. So back to the original question of what is the programmatic alternative to gcloud auth print-access-token, my answer would be:

import google.auth
import google.auth.transport.requests
creds, projects = google.auth.default()

# creds.valid is False, and creds.token is None
# Need to refresh credentials to populate those

auth_req = google.auth.transport.requests.Request()
creds.refresh(auth_req)

# Now you can use creds.token

I'm using the official google-auth package and default credentials, which will get you going both in local dev and on remote GCE/GKE app.

Too bad this is not properly documented and I had to read google-auth code to figure our how to obtain the token.

Programmatic authentication | Identity-Aware Proxy, A IAP-secured application to which you want to programmatically connect using a Include the ID token in an Authorization: Bearer header to make the  I've deployed a simple GCP Cloud Function which returns "Hello World!". I need this function to be under authorization. I unmarked "Allow unauthenticated invocations" checkbox, so only authenticated

I found myself here when looking for a way to use the python SDK without creating a service account. I wanted a way to locally develop a script that would run in the cloud. I was able to achieve this by using an artifact of the gcloud command:

export GOOGLE_APPLICATION_CREDENTIALS=~/.config/gcloud/legacy_credentials/<me>/adc.json

Authenticating users with Cloud Identity-Aware Proxy for Python, Generate an access token. The Realtime Database REST API accepts standard Google OAuth2 access tokens. The access tokens can be generated using a  Apigee then generates an access token of its own, associates the Cloud Healthcare API info and OAuth2 token with that self-generated token, and returns the self-generated token to the requesting application.

This may not be the recommended way but for Rest API in my application this was an easy way to get the token.

from subprocess import PIPE, Popen


def cmdline(command):
    process = Popen(
        args=command,
        stdout=PIPE,
        shell=True
    )
    return process.communicate()[0]


token = cmdline("gcloud auth application-default print-access-token")
print("Token:"+token)

Authenticate REST Requests, You can use the Google Cloud Storage APIs to access files uploaded via Firebase Google Cloud Storage access control options, rather than Firebase Authentication Google Cloud Platform offers high-quality server SDKs for a number of GCP These libraries are available in Node.js, Java, go, Python, PHP​, and Ruby. Get an ID token for the IAP-secured client ID: Android: Use the Google Sign-In API to request an OpenID Connect (OIDC) token. Set the requestIdToken client ID to the client ID for the resource you're connecting to. iOS: Use Google Sign-In to get an ID token. Set serverClientID to the client ID for the resource you're connecting to.

Integrate with Google Cloud Platform, These sample scripts illustrate the interaction necessary to obtain and use OAuth 2.0 access tokens. They utilize the HTTP client library Requests. Requests  There are two steps to acquire an Azure AD access token using the authorization code flow. Obtain the authorization code, which launches a browser window and ask for user login. The authorization code is returned after the user successfully logs in. Use the authorization code to acquire the access token.

OAuth 2.0 Python Sample Code, Any application that uses OAuth 2.0 to access Google APIs must have authorization Applications that use languages and frameworks like PHP, Java, Python, Ruby, and . your app can refresh the access token without user interaction. More. Open the Cloud Storage browser in the Google Cloud Console. Open the Cloud Storage browser. In the list of buckets, click on the name of the bucket that contains the object you want to download. The Bucket details page opens, with the Objects tab selected. Navigate to the object, which may be located in a folder.

Using OAuth 2.0 for Web Server Applications, Google Sheets Python API. Contribute to burnash/gspread development by creating an account on GitHub. OAuth 2.0 uses scopes to determine if an authenticated identity is authorized. Applications use a credential (obtained from a user-centric or server-centric authentication flow) together with one or more scopes to request an access token from a Google authorization server to access protected resources.

Comments
  • Do you want to get this in a GCP environment like Compute Engine, App Engine, Cloud Functions, etc? Or outside GCP, like on your local machine?
  • I'm building an app/script inside a GCP Compute Engine instance with a service account. That's my first preference. I'm also interested to know how it would be like if it was run outside GCP on my local machine too.
  • I additionally came across this github example: github.com/GoogleCloudPlatform/python-docs-samples/blob/master/… How does this relate to your above mentioned discussion?
  • This example obtains the access token from the VM Instance metadata. This would be equivalent to the code in my answer under Compute Engine cred = compute_engine.Credentials(). This example shows how to access the metadata server directly which is also important to know / understand.
  • If you are interested in further reading about Google Cloud Credentials, I have written a bunch of articles on my website: jhanley.com
  • Thanks again for the explanations and link to further readings!
  • This worked for me, although I needed to add the google cloud scope just to do the refresh. So I changed the first line after the imports to: "creds, project = google.auth.default( scopes=['googleapis.com/auth/cloud-platform'])"