Locally test your Cloud Run service code that makes an authenticated call to another Cloud Run…
Previously I blogged about testing a Cloud Run service code locally that calls a Google Sheet. Reading and writing from a Google Sheet uses…
Locally test your Cloud Run service code that makes an authenticated call to another Cloud Run service

Cloud Run product logo
Previously I blogged about testing a Cloud Run service code locally that calls a Google Sheet. Reading and writing from a Google Sheet uses Google APIs, and that requires an OAuth Access Token. Just for the sake of completeness, I wanted to include the scenario where you’d use an ID Token (OIDC).
You’d use an ID Token whenever you’re making an authenticated call to a Cloud Run service that requires authorization.
A couple of points regarding the code below:
- The Google Auth Library automatically generates an ID Token scoped specifically to that TARGET_URL. Remember not to include a slash at the end of the URL!! The Audience claim must match the Cloud Run service URL exactly, which does not include a trailing slash. Ask me how I know this 😅
- The app puts the token in an Auth header and then makes the authenticated request.
requirements.txt
fastapi>=0.100.0
uvicorn>=0.22.0
google-auth>=2.22.0
requests>=2.34.2
main.py
import os
import urllib.request
from fastapi import FastAPI, HTTPException
import google.auth.transport.requests
import google.oauth2.id_token
# 1. FastAPI Application Setup
app = FastAPI()
# 2. Configuration
TARGET_URL = os.environ.get("TARGET_URL")
@app.get("/")
def call_authenticated_service():
# Fail fast if the configuration is missing or incorrectly formatted
if not TARGET_URL:
raise ValueError("TARGET_URL environment variable is not set.")
if TARGET_URL.endswith("/"):
raise ValueError(
f"Invalid TARGET_URL: '{TARGET_URL}'. "
"To match OAuth OIDC rules, the audience URL must not contain a trailing slash."
)
try:
# Create a request object for the Google Auth library
auth_req = google.auth.transport.requests.Request()
# Fetch the OIDC ID token for the specific target audience
target_token = google.oauth2.id_token.fetch_id_token(auth_req, TARGET_URL)
# Build the request and attach the token
req = urllib.request.Request(TARGET_URL)
req.add_header("Authorization", f"Bearer {target_token}")
# Execute the authenticated request
with urllib.request.urlopen(req) as response:
target_response_data = response.read().decode()
return {
"message": "Successfully authenticated and called target service.",
"target_response": target_response_data
}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
Note re Terminology
You may be more familiar with the terms “assuming an identity” or “assuming the same permissions.” In Google Cloud, impersonating a service account lets an authenticated principal access whatever the service account can access. Only authenticated principals with the appropriate permissions can impersonate service accounts. You can read more here https://docs.cloud.google.com/iam/docs/service-account-overview#impersonation
How to configure your local environment
Similar to my previous post, you’ll impersonate the service account. You need to make sure your identity has the appropriate iam.serviceAccountTokenCreator role to generate tokens on behalf of the service account.
# Retrieve your current identity as shown in `gcloud auth list`
YOUR_IDENTITY=$(gcloud config get-value account)
gcloud iam service-accounts add-iam-policy-binding $SERVICE_ACCOUNT_EMAIL \
--member="user:$YOUR_IDENTITY" \
--role="roles/iam.serviceAccountTokenCreator" \
--project=$PROJECT_ID
Now configure ADC…
gcloud auth application-default login \
--impersonate-service-account=<YOUR_SERVICE_ACCOUNT_EMAIL>
and grant your SA the permissions to invoke the Cloud Run service.
gcloud run services add-iam-policy-binding <YOUR_SERVICE> \
--member="serviceAccount:<YOUR_SERVICE_ACCOUNT>" \
--role="roles/run.invoker" \
--region="<YOUR_REGION>"
Let’s try it out locally!
Install your requirements locally, then start the service locally, passing in the URL for your Cloud Run service. For example, you could deploy the hello test image us-docker.pkg.dev/cloudrun/container/hello that requires authentication.
TARGET_URL=<YOUR_HELLO_CLOUD_RUN_SERVICE_URL> ./venv/bin/uvicorn main:app --reload
And now when you curl your endpoint, you will get the HTML for the Hello test container, e.g. <title>Congratulations | Cloud Run</title>
Deployment
Since you ran this locally, you’ll want to create a .gcloudignore file to avoid all your local dependencies being zipped up.
.gcloudignore
venv/
Now you’re ready to deploy with the service account as the identity to your Cloud Run service.
gcloud run deploy <YOUR_SERVICE_NAME> \
--source . \
--set-env-vars TARGET_URL=<YOUR_HELLO_CLOUD_RUN_SERVICE_URL> \
--service-account <YOUR_SERVICE_ACCOUNT>
Now when you curl the Service URL in production, you’ll get the HTML for the hello test container.
메타데이터
- post_id
- 6d56974de544
- slug
- locally-test-your-cloud-run-service-code-that-makes-an-authenticated-call-to-another-cloud-run-6d56974de544
- url
- https://medium.com/google-cloud/locally-test-your-cloud-run-service-code-that-makes-an-authenticated-call-to-another-cloud-run-6d56974de544
- canonical_url
- https://medium.com/google-cloud/locally-test-your-cloud-run-service-code-that-makes-an-authenticated-call-to-another-cloud-run-6d56974de544
- author_url
- https://medium.com/@saraford_5679
- status
- ok
- fetched_at
- 2026-09-21 11:20:12