Get hands-on experience with 20+ free Google Cloud products and $300 in free credit for new customers.

Authenticating Cloud Run Service Requests with (Long lived) Access Token

Hello Team, 

I hope you are doing well.

Show More
TL;DR: I want a JWT token with a long lifespan (e.g., 1 week or 1 month) to access a private Cloud Run service (https://<region>-<project-id>.cloudfunctions.net/<example-name>) from an external app outside GCP. The token generated by gcloud auth print-identity-token expires in 1 hour, which is too short. I tried creating a custom JWT using a service account key, but it was unauthorized. The external app can only send API requests with bearer tokens, and the service account has Cloud Run Invoker, Service Account Token Creator, and Owner roles.


I am trying to access a Cloud Run Private Service i.e. https://<region>-<project-id>.cloudfunctions.net/<example-name>, privately, from outside GCP with a JWT token 

Now, when I generated a JWT token with this gcloud command: 

 

gcloud auth print-identity-token

 

 I accessed the Cloud Run service (example-name), but the token expires after approximately 1 hour.

I want to generate a token that lives longer than 1 hour (1 week/ 1 month,... etc) and give it to the consumer of the Cloud Run service; some services outside GCP don't have access to it. So, it can only send API requests with bearer tokens.

I tried to create a custom JWT token but it has no access to the Cloud Run service (unauthorized user) . As follows:

 

 

import time
import jwt  # Install with `pip install PyJWT`
import requests

SERVICE_ACCOUNT_KEY = "....."

# Service account details
SERVICE_ACCOUNT_EMAIL = SERVICE_ACCOUNT_KEY['client_email']
PRIVATE_KEY = SERVICE_ACCOUNT_KEY['private_key']
PRIVATE_KEY_ID = SERVICE_ACCOUNT_KEY['private_key_id']
CLOUD_FUNCTION_URL = "https://<region>-<project-id>.cloudfunctions.net/<EXAMPLE>"

# Create the JWT payload
iat = int(time.time())
exp = iat + 3600  # Token valid for 1 hour
payload = {
    "iss": SERVICE_ACCOUNT_EMAIL,
    "sub": SERVICE_ACCOUNT_EMAIL,
    "aud": CLOUD_FUNCTION_URL,
    "iat": iat,
    "exp": exp,
}

# Create the JWT header
headers = {
    "kid": PRIVATE_KEY_ID,
    "alg": "RS256",
    "typ": "JWT",
}

# Sign the JWT
signed_jwt = jwt.encode(payload, PRIVATE_KEY, algorithm="RS256", headers=headers)

 

 

The service key is frensh and valid, the service aaccount itself has these roles:

 

Cloud Functions Invoker
Cloud Run Invoker
Owner # for testing purposes
Service Account Token Creator

 

Example how I would access the cloud run service:

 

curl -X POST "https://<region>-<project-id>.cloudfunctions.net/<example-name>" -H "Authorization: Bearer {signed_jwt}" -H "Content-Type: application/json"'

 

 
Best regards, 

Abdullah

1 2 845
2 REPLIES 2

Hi @sqoor,

Identity tokens (like those generated with gcloud auth print-identity-token) are short-lived by design, typically expiring after 1 hour. These tokens are meant for temporary authentication and aren't suitable for long-term access.

If you need a longer-lasting token (e.g., 1 week or 1 month), you can consider using OAuth 2.0 instead of relying on identity tokens. OAuth 2.0 allows you to use refresh tokens, which let you obtain new access tokens once the old ones expire. This method is commonly used for external applications that need persistent access to Google Cloud resources, like Cloud Run services.

For a more detailed explanation, check out the Authentication methods at Google. This guide will help you understand how to set up OAuth2 with service accounts, manage token lifespans, and authenticate external applications securely.

Was this helpful? If so, please accept this answer as “Solution”. If you need additional assistance, reply here within 2 business days and I’ll be happy to help.

Hello @mcbsalceda , 

Thank you for your response. 


With OAuth, you must let the end users log in with their Google account

In my case, the consumer is a SaaS, I want to programmatically allow all users to access the cloud run service via HTTPS request, under the hood, without bothering the end users to log in.

So, the JWT token fit my case, except that it expires after 1 hour.

Regards,