This tutorial shows how to create a voting service, consisting of:
A browser-based client that:
A Cloud Run server that:
A PostgreSQL database that stores the votes.
For simplicity, this tutorial uses Google as a provider: users must authenticate using their user account in order to acquire their ID token. However, you can use other providers or authentication methods to sign in users.
When this document uses the term user account, it refers to a Google Account, or a user account managed by your identity provider and federated with Workforce Identity Federation.
You use the credentials provided by your user account to sign in to the tool.
This service minimizes security risks by using Secret Manager to protect sensitive data used to connect to the Cloud SQL instance. It also uses a least-privilege service identity to secure access to the database.
Write, build, and deploy a service to Cloud Run that shows how to:
Use Identity Platform to authenticate an end-user to the Cloud Run service backend.
Create a least-privilege identity for the service to grant minimal access to Google Cloud resources.
Use Secret Manager to handle sensitive data when connecting
the Cloud Run service to a postgreSQL database.
In this document, you use the following billable components of Google Cloud:
To generate a cost estimate based on your projected usage,
use the pricing calculator.
In the Google Cloud console, on the project selector page,
select or create a Google Cloud project. Roles required to select or create a project
Verify that billing is enabled for your Google Cloud project.
In the Google Cloud console, on the project selector page,
select or create a Google Cloud project. Roles required to select or create a project
Verify that billing is enabled for your Google Cloud project.
Enable the Cloud Run, Secret Manager, Cloud SQL, Artifact Registry, and Cloud Build APIs.
Roles required to enable APIs
To enable APIs, you need the Service Usage Admin IAM
role (
To get the permissions that
you need to complete the tutorial,
ask your administrator to grant you the
following IAM roles on your project:
For more information about granting roles, see Manage access to projects, folders, and organizations.
You might also be able to get
the required permissions through custom
roles or other predefined
roles.
Costs
Before you begin
roles/resourcemanager.projectCreator), which contains the
resourcemanager.projects.create permission. Learn how to grant
roles.
roles/resourcemanager.projectCreator), which contains the
resourcemanager.projects.create permission. Learn how to grant
roles.
roles/serviceusage.serviceUsageAdmin), which
contains the serviceusage.services.enable permission. Learn how to grant
roles.
Required roles
roles/artifactregistry.repoAdmin)roles/cloudbuild.builds.editor)roles/run.admin)roles/cloudsql.admin)roles/iam.serviceAccountCreator)roles/identityplatform.admin)roles/oauthconfig.editor)roles/resourcemanager.projectIamAdmin)roles/secretmanager.admin)roles/iam.serviceAccountUser)roles/serviceusage.serviceUsageConsumer)roles/storage.admin)
gcloud defaultsTo configure gcloud with defaults for your Cloud Run service:
Set your default project:
gcloud config set project PROJECT_ID
Replace PROJECT_ID with the name of the project you created for this tutorial.
Configure gcloud for your chosen region:
gcloud config set run/region REGION
Replace REGION with the supported Cloud Run region of your choice.
Cloud Run is regional, which means the infrastructure that
runs your Cloud Run services is located in a specific region and is
managed by Google to be redundantly available across
all the zones within that region.
Meeting your latency, availability, or durability requirements are primary
factors for selecting the region where your Cloud Run services are run.
You can generally select the region nearest to your users but you should consider
the location of the other Google Cloud
products that are used by your Cloud Run service.
Using Google Cloud products together across multiple locations can affect
your service's latency as well as cost.
Cloud Run is available in the following regions:
asia-east1 (Taiwan)
asia-northeast1 (Tokyo)
asia-northeast2 (Osaka)
asia-south1 (Mumbai, India)
asia-southeast3 (Bangkok)
europe-north1 (Finland)
europe-north2 (Stockholm)
europe-southwest1 (Madrid)
europe-west1 (Belgium)
europe-west4 (Netherlands)
europe-west8 (Milan)
europe-west9 (Paris)
me-west1 (Tel Aviv)
northamerica-south1 (Mexico)
us-central1 (Iowa)
us-east1 (South Carolina)
us-east4 (Northern Virginia)
us-east5 (Columbus)
us-south1 (Dallas)
us-west1 (Oregon)
africa-south1 (Johannesburg)
asia-east2 (Hong Kong)
asia-northeast3 (Seoul, South Korea)
asia-southeast1 (Singapore)
asia-southeast2 (Jakarta)
asia-south2 (Delhi, India)
australia-southeast1 (Sydney)
australia-southeast2 (Melbourne)
europe-central2 (Warsaw, Poland)
europe-west10 (Berlin)
europe-west12 (Turin)
europe-west2 (London, UK)
europe-west3 (Frankfurt, Germany)
europe-west6 (Zurich, Switzerland)
me-central1 (Doha)
me-central2 (Dammam)
northamerica-northeast1 (Montreal)
northamerica-northeast2 (Toronto)
southamerica-east1 (Sao Paulo, Brazil)
southamerica-west1 (Santiago, Chile)
us-west2 (Los Angeles)
us-west3 (Salt Lake City)
us-west4 (Las Vegas)
If you already created a Cloud Run service, you can view the region in the Cloud Run dashboard in the Google Cloud console.
To retrieve the code sample for use:
Clone the sample app repository to your local machine:
git clone https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git
Alternatively, you can download the sample as a zip file and extract it.
git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git
Alternatively, you can download the sample as a zip file and extract it.
git clone https://github.com/GoogleCloudPlatform/java-docs-samples.git
Alternatively, you can download the sample as a zip file and extract it.
Change to the directory that contains the Cloud Run sample code:
cd nodejs-docs-samples/run/idp-sql/
cd python-docs-samples/run/idp-sql/
cd java-docs-samples/run/idp-sql/
An end-user makes the first request to the Cloud Run server.
The client loads in the browser.
The user provides login credentials through the Google sign-in dialog from Identity Platform. An alert welcomes the signed-in user.
Control is redirected back to the server. The end-user votes using the client, which fetches an ID token from Identity Platform and adds it to the vote request header.
When the server receives the request, it verifies the Identity Platform ID token, confirming that the end-user is appropriately authenticated. Then server sends the vote to Cloud SQL, using its own credentials.
The sample is implemented as client and server, as described next.
This sample uses Firebase SDKs to integrate with Identity Platform in order to sign-in and manage users. To connect to Identity Platform, the client-side JavaScript holds the reference to the project's credentials as a config object and imports the necessary Firebase JavaScript SDKs:
The Firebase JavaScript SDK handles the sign-in flow by prompting the end-user to sign-in to their Google Account via a popup window. It then redirects them back to the service.
When a user successfully signs in, the client uses Firebase methods to mint an
ID token. The client adds the ID token to the Authorization header of its request
to the server.
The server uses the Firebase Admin SDK
to verify the user ID token sent from the client. If the provided
ID token has the correct format, is not expired, and is properly signed, the
method returns the decoded ID token. The server extracts the Identity Platform uid
for that user.
The server connects to the Cloud SQL instance Unix domain socket using
the format: /cloudsql/CLOUD_SQL_CONNECTION_NAME.
DataSource bean, which, coupled with Spring JDBC, provides a JdbcTemplate object bean that allows for operations such as querying and modifying a database.
Secret Manager provides centralized and secure storage of sensitive data such as Cloud SQL configuration. The server injects the Cloud SQL credentials from Secret Manager at runtime via an environment variable. Learn more about Using secrets with Cloud Run.
Identity Platform requires manual setup in the Google Cloud console.
In the Google Cloud console, enable the Identity Platform API:
Configure your project:
In a new window, go to the Google Auth Platform > Overview page.
Click Get Started and follow the project configuration setup.
In the App information dialog:
In the Audience dialog, select External.
In the Contact information dialog, enter a contact email.
Agree to the user data policy, then click Create.
Create and obtain your OAuth Client ID and Secret:
In the Google Cloud console, go to the APIs & Services > Credentials page.
At the top of the page, click Create Credentials and select OAuth client ID.
From Application Type, select Web Application and supply the name.
Click Create
The client_id and client_secret values will be used in the next step.
Configure Google as a provider:
In the Google Cloud console, go to the Identity Providers page.
Click Add A Provider.
Select Google from the list.
In the Web SDK Configuration settings, enter the client_id and client_secret values from the
previous step.
Under Configure your application, click Setup Details.
Copy the configuration to your application:
apiKey and authDomain values into the sample's static/config.js to initialize the Identity Platform Client SDK.Follow the steps to complete infrastructure provisioning and deployment:
Create a Cloud SQL instance with postgreSQL database using the console or CLI:
gcloud sql instances create CLOUD_SQL_INSTANCE_NAME \ --database-version=POSTGRES_16 \ --region=CLOUD_SQL_REGION \ --cpu=2 \ --memory=7680MB \ --root-password=DB_PASSWORD
Add your Cloud SQL credential values to postgres-secrets.json:
Create a versioned secret using the console or CLI:
gcloud secrets create idp-sql-secrets \ --replication-policy="automatic" \ --data-file=postgres-secrets.json
Create a service account for the server using the console or CLI:
gcloud iam service-accounts create idp-sql-identity
Grant roles for Secret Manager and Cloud SQL access using the console or CLI:
Allow the service account associated with the server to access the created secret:
gcloud secrets add-iam-policy-binding idp-sql-secrets \ --member serviceAccount:idp-sql-identity@PROJECT_ID.iam.gserviceaccount.com \ --role roles/secretmanager.secretAccessor
Allow the service account associated with the server to access Cloud SQL:
gcloud projects add-iam-policy-binding PROJECT_ID \ --member serviceAccount:idp-sql-identity@PROJECT_ID.iam.gserviceaccount.com \ --role roles/cloudsql.client
Create an Artifact Registry:
gcloud artifacts repositories create REPOSITORY \ --repository-format docker \ --location REGION
REPOSITORY is the name of the repository. For each repository location in a project, repository names must be unique.Build the container image using Cloud Build:
gcloud builds submit --tag REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/idp-sql
gcloud builds submit --tag REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/idp-sql
This sample uses Jib to build Docker images using common Java tools. Jib optimizes container builds without the need for a Dockerfile or having Docker installed. Learn more about building Java containers with Jib.
Use the gcloud credential helper to authorize Docker to push to your Artifact Registry.
gcloud auth configure-docker
Use the Jib Maven Plugin to build and push the container to Artifact Registry.
mvn compile jib:build -Dimage=REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/idp-sql
Deploy the container image to Cloud Run using the console or CLI. Note that the server is deployed to allow unauthenticated access. This is so that the user can load the client and begin the process. The server verifies the ID token added to the vote request manually, authenticating the end-user.
gcloud run deploy idp-sql \ --image REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/idp-sql \ --allow-unauthenticated \ --service-account idp-sql-identity@PROJECT_ID.iam.gserviceaccount.com \ --add-cloudsql-instances PROJECT_ID:REGION:CLOUD_SQL_INSTANCE_NAME \ --update-secrets CLOUD_SQL_CREDENTIALS_SECRET=idp-sql-secrets:latest
Also note the flags, --service-account, --add-cloudsql-instances, and
--update-secrets, which specify the service identity, the Cloud SQL
instance connection, and the secret name with version as an environment
variable, respectively.
Identity Platform requires that you authorize the Cloud Run service URL as an allowed redirect after it has signed in the user:
Edit the Google provider by clicking the pen icon in the Identity Providers page.
Click Add Domain under Authorized Domains on the right panel, and enter the Cloud Run service URL.
You can locate the service URL in the logs after the build or deployment or you can find it anytime using:
gcloud run services describe idp-sql --format 'value(status.url)'
Go to the APIs & Services > Credentials page
Click the pencil icon beside your OAuth Client ID to edit it and under the Authorized redirect URIs click the Add URI button.
In the field copy and paste the following URL and click the Save button at the bottom of the page.
https://PROJECT_ID.firebaseapp.com/__/auth/handler
To try out the complete service:
Navigate your browser to the URL provided by the deployment step above.
Click the Sign in with Google button and go through the authentication flow.
Add your vote!
It should look like this:
If you choose to continue developing these services, remember that they have restricted Identity and Access Management (IAM) access to the rest of Google Cloud and will need to be given additional IAM roles to access many other services.
To avoid additional charges to your Google Cloud account, delete all the resources you deployed with this tutorial.
If you created a new project for this tutorial, delete the project. If you used an existing project and need to keep it without the changes you added in this tutorial, delete resources that you created for the tutorial.
The easiest way to eliminate billing is to delete the project that you created for the tutorial.
To delete the project:
Delete the Cloud Run service you deployed in this tutorial. Cloud Run services don't incur costs until they receive requests.
To delete your Cloud Run service, run the following command:
gcloud run services delete SERVICE-NAME
Replace SERVICE-NAME with the name of your service.
You can also delete Cloud Run services from the Google Cloud console.
Remove the gcloud default region configuration you added during tutorial
setup:
gcloud config unset run/region
Remove the project configuration:
gcloud config unset project
Delete other Google Cloud resources created in this tutorial:
Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License. For details, see the Google Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.
Last updated 2026-06-09 UTC.