Identity-Aware Proxy (IAP) lets you control access to your cloud applications based on user identity, not just network location, effectively eliminating the need for a traditional VPN for many use cases.

Let’s see how this works with a simple web application running on Google Compute Engine (GCE).

Here’s a basic Flask app that we’ll deploy:

from flask import Flask, request, redirect, url_for, render_template_string
import os

app = Flask(__name__)

# Simple HTML template for the protected page
HTML_TEMPLATE = """
<!doctype html>
<html>
<head><title>Protected Page</title></head>
<body>

  <h1>Welcome, {{ user_email }}!</h1>

  <p>This is a page protected by Identity-Aware Proxy.</p>

  <a href="{{ url_for('logout') }}">Logout</a>

</body>
</html>
"""

@app.route('/')
def index():
    # IAP injects these headers if a user is authenticated
    user_email = request.headers.get('X-Goog-Authenticated-User-Email')
    if user_email:
        # Remove the "accounts.google.com:" prefix
        user_email = user_email.split(':')[1]
        return render_template_string(HTML_TEMPLATE, user_email=user_email)
    else:
        # If IAP is not present or not configured, redirect to a login page (or show an error)
        # For this example, we'll assume IAP is the only auth mechanism.
        return "<h1>Access Denied</h1><p>Please ensure you are accessing this via Identity-Aware Proxy.</p>", 403

@app.route('/logout')
def logout():
    # In a real app, you'd invalidate sessions. For IAP, a logout might redirect to Google's logout.
    # For simplicity, we'll just redirect back to the root, which IAP will re-authenticate.
    return redirect(url_for('index'))

if __name__ == '__main__':
    # For local testing, run on a specific port.
    # In GCE, this app will be run by a web server like Gunicorn.
    app.run(host='0.0.0.0', port=8080)

To deploy this, we’ll create a GCE instance, install Python and Flask, and run the application.

First, create a GCE instance:

gcloud compute instances create my-iap-app \
    --project=your-gcp-project-id \
    --zone=us-central1-a \
    --machine-type=e2-medium \
    --image-family=debian-11 \
    --image-project=debian-cloud \
    --tags=http-server,https-server

SSH into the instance and set up the application:

# Install Python and pip
sudo apt-get update
sudo apt-get install -y python3 python3-pip

# Create a directory for the app and navigate into it
mkdir ~/my-app
cd ~/my-app

# Create the app.py file (paste the Flask code above)
nano app.py

# Install Flask and Gunicorn
pip3 install Flask gunicorn

# Create a systemd service file for Gunicorn
sudo nano /etc/systemd/system/my-app.service

Paste the following into my-app.service:

[Unit]
Description=Gunicorn instance to serve my-app
After=network.target

[Service]
User=your-username  # Replace with your username on the GCE instance
Group=www-data
WorkingDirectory=/home/your-username/my-app # Replace with your username
ExecStart=/usr/bin/gunicorn --workers 4 --bind 0.0.0.0:8080 app:app

[Install]
Service]
WantedBy=multi-user.target

Enable and start the service:

sudo systemctl enable my-app.service
sudo systemctl start my-app.service
sudo systemctl status my-app.service # Verify it's running

Now, let’s set up IAP. IAP acts as a reverse proxy before your application. It intercepts incoming requests, checks the user’s Google identity, and if authorized, forwards the request to your application, injecting headers like X-Goog-Authenticated-User-Email.

  1. Enable the IAP API:

    gcloud services enable iap.googleapis.com --project=your-gcp-project-id
    
  2. Create a Load Balancer: IAP works with Google Cloud Load Balancing. We need an external HTTPS load balancer.

    • First, create a backend service. This points to your GCE instance.

      gcloud compute backend-services create my-iap-backend \
          --project=your-gcp-project-id \
          --protocol=HTTP \
          --port-name=http \
          --timeout=30 \
          --enable-cdn \
          --connection-draining-timeout=300 \
          --health-checks=projects/your-gcp-project-id/global/healthChecks/default-http-health-check # Use a default health check or create one
      

      Note: You might need to create a health check if default-http-health-check doesn’t exist. gcloud compute health-checks create http my-http-health-check --port 80 is a common way.

    • Add your GCE instance to the backend service.

      gcloud compute backend-services add-backend my-iap-backend \
          --project=your-gcp-project-id \
          --instance-group=my-iap-app-instance-group \ # This name is usually auto-generated based on your instance name
          --instance-group-zone=us-central1-a \
          --balancing-mode=UTILIZATION \
          --capacity-scaler=1.0
      

      To find your instance group name: gcloud compute instance-groups list.

    • Create a URL map.

      gcloud compute url-maps create my-iap-url-map \
          --project=your-gcp-project-id \
          --default-service=my-iap-backend
      
    • Create an SSL certificate (for HTTPS). For testing, you can use a self-signed certificate or a Google-managed one. Let’s assume you’ll get a domain name and use Google-managed. For now, we’ll skip the actual certificate creation and assume it’s handled by the load balancer.

    • Create a target HTTPS proxy. This is where IAP configuration happens.

      gcloud compute target-https-proxies create my-iap-https-proxy \
          --project=your-gcp-project-id \
          --url-map=my-iap-url-map \
          --ssl-certificates=YOUR_SSL_CERT_NAME # e.g., my-ssl-cert
      

      If you don’t have an SSL cert yet, you’ll need to create one and associate it.

    • Create a global forwarding rule. This is the public IP address for your app.

      gcloud compute forwarding-rules create my-iap-forwarding-rule \
          --project=your-gcp-project-id \
          --global \
          --target-https-proxy=my-iap-https-proxy \
          --ports=443 \
          --address=YOUR_RESERVED_IP_ADDRESS # Reserve a static IP: gcloud compute addresses create my-iap-ip --global
      
  3. Configure IAP Access: Now, grant users or groups access to the IAP resource.

    • Go to the Google Cloud Console -> Identity-Aware Proxy.
    • Find your application (it might appear under the load balancer’s backend service).
    • Click the checkbox next to your application, then click Add Principal.
    • Enter the Google account email address (e.g., user@example.com) or a Google Group.
    • Assign the role IAP-secured Web App User.
    • Click Save.
  4. Configure Firewall Rules: Ensure your GCE instance allows traffic from the load balancer and IAP’s health check probes.

    gcloud compute firewall-rules create allow-iap-health-checks \
        --project=your-gcp-project-id \
        --network=default \
        --action=ALLOW \
        --direction=INGRESS \
        --source-ranges=35.191.0.0/16,130.211.0.0/22 \
        --target-tags=http-server,https-server \
        --rules=tcp:80,tcp:443,tcp:8080
    
    • The 35.191.0.0/16 and 130.211.0.0/22 ranges are Google’s IP ranges for load balancers and health checks.

Now, if you access the IP address of your load balancer (from the forwarding rule) via HTTPS, you will be presented with a Google sign-in page. After successfully authenticating with a Google account that has been granted IAP access, you’ll see your Flask application’s "Welcome" page. If you try to access the application directly via the GCE instance’s IP, you’ll get an "Access Denied" error because IAP isn’t in the request path.

The core of IAP’s magic lies in how it integrates with Google Cloud Load Balancing and Google Identity. It acts as a sophisticated gatekeeper, performing authentication and authorization before traffic even reaches your application’s network segment. This means your application doesn’t need to handle complex authentication flows or worry about network-level access control; it simply trusts the headers provided by IAP.

A common misconception is that IAP requires a Google Workspace or Cloud Identity account for all users. While that’s the most common setup, IAP can also integrate with external Identity Providers (IdPs) via SAML, allowing users from other identity systems to access your applications.

The next hurdle you’ll likely encounter is managing access for different user groups or requiring specific user attributes for access, which involves more granular IAM policies and potentially custom logic within your application to interpret IAP-provided user context.

Want structured learning?

Take the full Gcp course →