Sitemap
Chanon Krittapholchai

Chanon Krittapholchai

Data Professional with Operation and SCM Background

Secured & Serverless Streamlit App with Google Cloud Run + IAP

8 min readMar 9, 2025

--

This is a step-by-step guide about creating a secured web application on Google Cloud Run using Identity-Aware Proxy (IAP).
This article will not cover Streamlit or network theories.

Press enter or click to view image in full size
Streamlit, IAP and Cloud Run’s logo

When we are developing an internet facing application.

The most annoying part is sure to be the authentication.

Which could be a risk, and it need to be aligned with organization’s frequently change policies.

However, GCP provide us an authentication tool called Identity-Aware Proxy (IAP). Which give us a secured application authentication by Google.

Press enter or click to view image in full size
Concept overview from GCP : Identity-Aware Proxy overview | Google Cloud

To make sure that we know what we are doing.
This how-to article will use the UI method instead of script.

There are 7 steps + 1 optional to activate application authentication using Identity-Aware Proxy (IAP) on Google Cloud Run.

1. Create Simple Streamlit App

First, we need to create a very simple Streamlit application on Google Cloud Run, without authentication. Skip this step if you already have your own Cloud Run application.

I will use a very simple script as show below.

Streamlit Script

import streamlit as st
st.title('Hello')

Dockerfile

# Use the official lightweight Python image.
# https://hub.docker.com/_/python
FROM python:3.9-slim

# Allow statements and log messages to immediately appear in the Knative logs
ENV PYTHONUNBUFFERED True

# Copy local code to the container image.
ENV APP_HOME /app
WORKDIR $APP_HOME
COPY . ./

# Install Streamlit.
RUN pip install streamlit

# EXPOSE PORT
EXPOSE 8080

# Run the service on container
CMD ["streamlit", "run", "main.py", "--server.port=8080", "--server.address=0.0.0.0"]

Build and Deploy with Cloud Run

# Create Place to hold Docker Image in Artifacts Repo
gcloud artifacts repositories create {repo name} \
--repository-format=docker \
--location={region} \
--description="{DESCRIPTION}"

# Build Docker Image
gcloud builds submit \
--tag {region}-docker.pkg.dev/{project name}/{repo name}/{image name}

# Deploy Docker Image to Cloud Run Service
gcloud run deploy {service name} \
--region {region} \
--image {region}-docker.pkg.dev/{project name}/{repo name}/{image name} \
--allow-unauthenticated # Importan!!

And we will have our simple Streamlit application on Cloud Run.

Press enter or click to view image in full size
Simple Streamlit App on Google Cloud Run

2. Reserve IP Address in IP Address

Next, we will need a static IP Address for our application.

On GCP console, go to the IP Address in VPC Network and click on Reserve External Static IP Address.

Press enter or click to view image in full size
Reserve External IP on GCP Console

Fill in required fields and click Reserve, this will bring us back to the IP Address page.

*For naming conversion, I will use {service_name}-{suffix} from now on.

Press enter or click to view image in full size
Fill in required fields

CHECK POIONT:
Try to ping the IP Address from the IP that we just reserved.

Press enter or click to view image in full size
Test the External IP

3. Register Domain using Cloud Domain

Next, we will need a domain to map theIP address from the 2nd step with a load balancer in the next step.

On GCP console, go to the Cloud Domain in Network Service and click on Register Domain.

Press enter or click to view image in full size
Register Domain on GCP Console

Fill in required fields.

  • Search domain : Search and select domain name you prefer
  • DNS configuration : I suggest using Cloud DNS
  • Privacy Protection : I suggest limiting your info
  • Contact Details : Your contact details
Press enter or click to view image in full size
Fill in require fields

Wait for a few minutes, then check your mailbox and verify the domain.

Press enter or click to view image in full size
Domain regitered after veritied email

4. Mapping name using Cloud DNS

Now, we will create our application domain and map it with the static IP Address from the 2nd step.

On GCP console, go to the Cloud DNS in Network Service and click on your registered domain from the previous section.

Press enter or click to view image in full size
Configure DNS on GCP Console

Then click Add Standard.

Press enter or click to view image in full size
Add a new standard in Domain’s DNS zone

Fill in required information.

  1. DNS name : Your prefer Application’s domain name
  2. Resource Record Type : A
  3. IPv4 Address : The IP that we reserved in the 2nd step
Press enter or click to view image in full size
Create a new standard mapping to the ip from the 2nd step

CHECK POINT:
Try to ping the domain name instead of the IP.
It should be redirected into the IP from the 2nd step.

Press enter or click to view image in full size
Test the application domain

5. Create a load balancer

Now, we will map the Application’s domain to our Cloud Run Application.

On GCP console, go to the Load Balancer in the Network Service and click on Create Load Balancer.

Press enter or click to view image in full size
Create load balancer on GCP console

Fill in required information depended on how application will be used.

Press enter or click to view image in full size
Fill in load balancer’s basic infomation

Next is to configure load balancer’s frontend and backend.

Frontend Configuration

Get Chanon Krittapholchai’s stories in your inbox

Join Medium for free to get updates from this writer.

Fill in required fields, these are what I used.

  • Load Balancer’s name : {Service Name}-lb
  • Frontend’s name : {Service Name}-fe
  • IP version : IPv4
  • IP Address : IP from the 2nd step
  • Certificate : Create A New Certificate -> This will open other window.
Press enter or click to view image in full size
Fill in frontend’s required fields and create a new certificate

For Create A New Certificate , fill in information like these.

  • Name : {Service Name}-fe-cer
  • Create Mode : Create Google-manged certificate , or upload if you have.
  • Domain : Your Application Domain from the 4th step

Back to the previous window, enable HTTP to HTTPS redirect

Press enter or click to view image in full size
Create a new certificate and create a frontend

Backend Configuration

For backend, click on Create A Backend Service and fill in required fields.

  • Name : {Service Name}-be
  • Backend Type : Serverless network endpoint group

Then click on Create A Serverless Network Endpoint Group.

Press enter or click to view image in full size
Configure a backend

Fill in the required fields.

  • Name : {Service Name}-be-grp
  • Region : Your application’s region
  • Serverless network endpoint group type : Application from the 1st step
Press enter or click to view image in full size
Create a endpoint group

And for the rest of load balancer configurations, we can use the default values. After created, we have to wait ~15 minutes for certificate registration.

Press enter or click to view image in full size
Load balancer pending.

CHECK POINT :
We should be able to access our Streamlit application from the Application domain from the 4th step.

6. Disable Cloud Run Ingress

Now that we can access our application though the load balancer, we don’t want anyone to access the application though the Cloud Run’s default URL. this step will disable accessibility from the default URL.

On GCP console, go to Cloud Run and click on our Streamlit application from the 1st step.

Press enter or click to view image in full size
Cloud Run service on GCP console

On Networking tab, Ingress, select Internal and Allow traffic from external Application Load Balancers.

Press enter or click to view image in full size
Only allow internal ingress and load balancer

This will make our Streamlit application only accessible though the Load Balancer from the 5th step.

CHECK POINT :
When access though the default URL, it should be an Error : Page not Found.

Press enter or click to view image in full size
Cannot access Streamlit application from Cloud Run’s URL anymore

7. Activate IAP

Now, to limit our application accessible only to allowed users, we will set up the Identity-Aware Proxy (IAP).

On GCP console, go to Identity-Aware Proxy in Security. For the first time, GCP will require us to configure the OAuth consent screen.

Press enter or click to view image in full size
IAP on GCP console

Click on Configure Consent Screen, fill in required information.

Press enter or click to view image in full size
Config Google’s OAuth

When we come back to the Identity-Aware Proxy, we will see a list of our backend service with IAP turn off.

Press enter or click to view image in full size
Backend service on IAP

Turn on the IAP, this will make our application only accessible for users with permission, this process will take ~5 minutes.

Press enter or click to view image in full size
Enable IAP for backend serivce

CHECK POINT :
Application will require Google’s authentication when access.
And you will get access denied when logged in.

To add permission to the application, on IAP, select the backend service and click on Add Principal, add users with role IAP-secured Web App User, this process also takes ~5 minutes.

Press enter or click to view image in full size
Add authorized user(s)

And our users will be able to access our Streamlit application!!!

[Optional] Get user’s email

This is an optional step, if we need user’s identification to use for additional logics or logging. We can use IAP’s JWT header to get it.

To get data from IAP’s header, first we need to get the audience from IAP.
On IAP, click on 3 dots and click on Get JWT audience code. This will show an JWT audience code.

Press enter or click to view image in full size
Get JWT audience code from IAP

Then we will need to modify our Streamlit script and the Dockerfile, don’t forget to put the JWT audience code into the Streamlit script.

Streamlit Script

# Main Streamlit
import streamlit as st
st.title('Hello')

# Get User Info
from google.auth.transport import requests
from google.oauth2 import id_token
from streamlit import context

# Get Header for Streamlit, change this part if you use other framework
def get_header() :
headers= context.headers
return headers.get_all('x-goog-iap-jwt-assertion')[0]

# Get
def validate_iap_jwt(iap_jwt, expected_audience):
try:
decoded_jwt = id_token.verify_token(
iap_jwt,
requests.Request(),
audience=expected_audience,
certs_url="https://www.gstatic.com/iap/verify/public_key",
)
return (decoded_jwt["sub"], decoded_jwt["email"], "")
except Exception as e:
return (None, None, f"**ERROR: JWT validation error {e}**")

expected_audience= 'JWT AUDIENCE from pervious step'
email= validate_iap_jwt(get_header(), expected_audience)[1]
st.title(f"User email : {email}")

Dockerfile

# Use the official lightweight Python image.
# https://hub.docker.com/_/python
FROM python:3.9-slim

# Allow statements and log messages to immediately appear in the Knative logs
ENV PYTHONUNBUFFERED True

# Copy local code to the container image.
ENV APP_HOME /app
WORKDIR $APP_HOME
COPY . ./

# Install Streamlit and additional lib.
RUN pip install streamlit
RUN pip install google-auth
RUN pip install cryptography

# EXPOSE PORT
EXPOSE 8080

# Run the service on container
CMD ["streamlit", "run", "main.py", "--server.port=8080", "--server.address=0.0.0.0"]

After re-build and re-deploy, we will be able to get user’s email.

Press enter or click to view image in full size
Now, it will show user’s email

And that’s how we authenticate our Streamlit application on Google Cloud Run with Identity-Aware Proxy (IAP).

Hope this will help, happy IAP!!!

--

--

Chanon Krittapholchai
Chanon Krittapholchai

Written by Chanon Krittapholchai

Data Professional with Operation and SCM Background