Introduction to Identity-Aware Proxy (IAP)
Identity-Aware Proxy (IAP) is Google Cloud's managed control plane for application-layer access control. Rather than wrapping internal applications inside a corporate VPN perimeter, IAP places a Google-operated reverse proxy in front of each protected resource and decides on every individual HTTPS or TCP request whether the caller's identity and context satisfy your policy. The proxy terminates on the Google Front End (GFE), evaluates IAM bindings plus optional Access Context Manager rules, and only then forwards the request to App Engine, Cloud Run, GKE, Compute Engine VMs, or even on-premises backends.
IAP is the canonical implementation of the BeyondCorp model that Google itself migrated to between 2011 and 2017. The PCD exam reliably tests four scenarios: (1) replacing a VPN concentrator with IAP for SaaS-style web apps, (2) removing public IPs from bastion hosts by using IAP TCP forwarding for SSH/RDP, (3) layering Access Levels (corp network CIDR, OS version, browser version) on top of IAM, and (4) extending IAP to on-prem workloads via the IAP Connector running on GKE.
Identity-Aware Proxy (IAP): A Google Cloud service that authenticates users via Google Sign-In or an external IdP, authorizes them against IAM role roles/iap.httpsResourceAccessor (web apps) or roles/iap.tunnelResourceAccessor (TCP), and forwards approved requests to backends through a Global External Application Load Balancer or a private TCP tunnel — without exposing the backend's IP address.
How IAP Protects HTTPS Web Applications
When IAP is enabled on a backend service of a Global External Application Load Balancer, every HTTP request is intercepted at the GFE. Unauthenticated callers are redirected to accounts.google.com for sign-in; authenticated callers must then satisfy iap.webServiceVersions.accessViaIAP permission, granted through roles/iap.httpsResourceAccessor. If both checks pass, IAP forwards the request to your backend with two signed headers attached.
The Two Critical Signed Headers
x-goog-authenticated-user-email carries the verified user identity in the form accounts.google.com:[email protected]. x-goog-authenticated-user-id carries the stable numeric user ID. Neither header is cryptographically signed on its own — they are convenience headers stripped from any inbound request, so they cannot be spoofed at the GFE. However, if an attacker bypasses the load balancer (for example by hitting the VM's external IP directly), they could inject forged values. That is why IAP also emits x-goog-iap-jwt-assertion, a cryptographically signed JWT that your application must verify on every request.
JWT Audience and Signature Verification
The x-goog-iap-jwt-assertion JWT is signed with the ES256 algorithm using a key from https://www.gstatic.com/iap/verify/public_key-jwk. Your application must (1) verify the ES256 signature, (2) confirm the iss claim equals https://cloud.google.com/iap, and (3) confirm the aud claim matches the resource-specific audience string. For App Engine the audience is /projects/PROJECT_NUMBER/apps/PROJECT_ID; for Compute Engine / GKE it is /projects/PROJECT_NUMBER/global/backendServices/BACKEND_SERVICE_ID. Mismatching the audience is the single most common implementation bug — it silently accepts JWTs minted for a different backend.
Always verify x-goog-iap-jwt-assertion server-side using the resource-specific audience. The user-email signed headers (x-goog-authenticated-user-email) are convenient but not cryptographically tied to your backend — only the JWT assertion is. Treat the email headers as display data and the JWT as the source of truth for authorization decisions.
IAP for TCP Forwarding: SSH and RDP Without a Bastion
IAP's second major mode tunnels arbitrary TCP traffic to a VM's internal IP, eliminating the need for public IP addresses, jump hosts, or a VPN. The user runs gcloud compute ssh INSTANCE --tunnel-through-iap, which opens a WebSocket to tunnel.cloudproxy.app:443, authenticates via the user's gcloud OAuth token, and proxies TCP bytes to the VM through Google's network. RDP works identically using gcloud compute start-iap-tunnel INSTANCE_NAME --local-host-port=localhost:3389 --instance-port=3389.
Firewall Rule for IAP TCP Range
The VM does not need an external IP, but its firewall must allow TCP from the IAP source range 35.235.240.0/20. A typical rule looks like gcloud compute firewall-rules create allow-iap-ssh --direction=INGRESS --action=allow --rules=tcp:22 --source-ranges=35.235.240.0/20. Without this rule the tunnel completes the OAuth dance but the SYN packet is dropped at the VPC firewall.
Required Roles for TCP Tunnels
Tunnel users need roles/iap.tunnelResourceAccessor scoped to the project, a folder, or a specific instance. For least privilege, bind the role with an IAM condition that limits it to a single VM: --condition='expression=resource.name=="projects/PROJECT/zones/ZONE/instances/INSTANCE"'. Users additionally need roles/compute.instanceAdmin.v1 or roles/iam.serviceAccountUser if they want gcloud to generate SSH keys via OS Login.
Combine IAP TCP forwarding with OS Login and 2-Step Verification on the Google account to get a fully audited, MFA-protected SSH path with zero public IPs. Cloud Audit Logs records every tunnel session under audit.googleapis.com/data_access with the user's email, source IP, and target instance — better forensics than a self-managed bastion.
OAuth Consent Screen: The Mandatory Prerequisite
Before IAP for web apps can be enabled, the project must have a configured OAuth Consent Screen in the Google Auth Platform (formerly APIs & Services → OAuth consent screen). IAP uses an internal OAuth client to broker the sign-in flow, and Google refuses to create that client until the consent screen has an application name, support email, and authorized domains.
Internal vs External User Type
For workloads that should only be accessible to your Workspace organization, set the consent screen user type to Internal — only accounts in your cloudidentity.googleapis.com organization can log in, and the app does not require Google's verification review. External user type allows any @gmail.com account or external Workspace and triggers app verification once it exceeds 100 users. Most enterprise PCD scenarios use Internal.
Authorized Domains and Branding
The consent screen must list the apex domain of any redirect URI (e.g. example.com). IAP automatically generates redirect URIs of the form https://iap.googleapis.com/v1/oauth/clientIds/CLIENT_ID:handleRedirect, which Google manages — you do not edit them. Misconfiguring authorized domains causes a redirect_uri_mismatch error on the first sign-in attempt.
IAM Roles and Permissions for IAP
IAP authorization rests on two predefined IAM roles, both of which must be granted on the IAP-secured resource (or any ancestor) rather than on the underlying backend service.
roles/iap.httpsResourceAccessor
This role contains the single permission iap.webServiceVersions.accessViaIAP and is the one role end users need to reach an IAP-protected web app. Grant it on the App Engine service, the backend service of the load balancer, or higher up the hierarchy. Granting roles/owner or roles/editor does not automatically include this permission — IAP roles are deliberately separated from project-level admin roles.
roles/iap.tunnelResourceAccessor
The TCP equivalent. Contains iap.tunnelInstances.accessViaIAP and grants the ability to open IAP tunnels to specific Compute Engine VMs. Like the HTTPS role, it must be granted on the instance, the zone, the project, or an ancestor folder/org.
Administrative Roles
roles/iap.admin allows enabling/disabling IAP and managing settings. roles/iap.settingsAdmin is a narrower role for managing only IAP settings (CORS, access tokens) without granting end-user access. The iap.googleapis.com API itself must be enabled in the project.
Web users need roles/iap.httpsResourceAccessor. SSH/RDP users need roles/iap.tunnelResourceAccessor. Admins need roles/iap.admin. The firewall rule for TCP forwarding allows source range 35.235.240.0/20. The JWT header is x-goog-iap-jwt-assertion signed with ES256. These five facts cover ~80% of IAP exam questions.
Integration with the Global External Application Load Balancer
IAP for Compute Engine and GKE workloads requires a Global External Application Load Balancer (formerly "HTTP(S) Load Balancer"). Regional load balancers and Network Load Balancers do not support IAP — this is a frequent trap. The flow is: client → DNS → anycast VIP → GFE → IAP check → backend service → instance group / NEG.
Enabling IAP on a Backend Service
gcloud compute backend-services update BACKEND_SERVICE --global --iap=enabled,oauth2-client-id=CLIENT_ID,oauth2-client-secret=SECRET. The OAuth client must be a "Web application" type created in the same project. Once enabled, IAP automatically rewrites the load balancer's URL map to inject the proxy.
Firewall and Health Check Considerations
Backend instances must allow ingress from 130.211.0.0/22 and 35.191.0.0/16 (the load balancer health check ranges). The IAP JWT verification step happens at the GFE, but the backend must still respond to health checks unauthenticated — exclude /healthz or /_ah/health paths from IAP by configuring path-based routing or by trusting that health checks come from the LB ranges.
Cloud Armor and IAP Layering
Cloud Armor security policies execute before IAP, so you can block geographies or known-bad ASNs without consuming IAP quota. After Armor allows a request, IAP performs identity and Access Level checks. The two services compose cleanly: Armor for L7 DDoS/geo-blocking, IAP for user identity.
Context-Aware Access with Access Levels
Access Context Manager lets you express conditional access policies — "only allow from corporate CIDRs, only when device OS is patched, only from a managed Chrome browser." Access Levels are then attached to an IAP IAM binding via the accessPolicy and accessLevels fields.
Defining an Access Level
gcloud access-context-manager levels create corp_network --policy=POLICY_ID --title="Corp Network" --basic-level-spec=corp.yaml where corp.yaml declares conditions such as ipSubnetworks: ["203.0.113.0/24"], requiredAccessLevels: [], devicePolicy.requireScreenlock: true, and devicePolicy.osConstraints.osType: DESKTOP_MAC. Multiple conditions combine with AND semantics inside one "basic" block and OR semantics across blocks.
BeyondCorp Enterprise and Endpoint Verification
Device-aware conditions (OS version, screen lock, encryption status) require Endpoint Verification, a Chrome extension or Workspace-managed agent that reports posture to Google. With BeyondCorp Enterprise licensing you also gain Data Loss Prevention controls in the browser, threat protection, and the requireCorpOwned condition that limits access to company-owned devices registered in the Admin Console.
Binding the Access Level to IAP
In Console: IAP → select resource → Access Levels → choose corp_network. Programmatically: gcloud iap web set-iam-policy with a binding that includes condition: { expression: "request.auth.access_levels.contains('accessPolicies/POLICY/accessLevels/corp_network')" }. Users who satisfy IAM but fail the Access Level get a 403 page that explains which condition failed.
Access Levels are evaluated in addition to IAM, not instead of it. A user without roles/iap.httpsResourceAccessor cannot reach the resource even from a perfect device. Conversely, a user with the role but on an unmanaged laptop is blocked. Design policies so that IAM defines "who could possibly access" and Access Levels define "under what conditions."
IAP with Cloud Identity vs External Identity Providers
IAP authenticates against Google identities by default — any account in Cloud Identity, Google Workspace, or @gmail.com if your consent screen allows External. For organizations that already operate Okta, Azure AD, or Ping as their primary IdP, two integration patterns exist.
Pattern A: Workforce Identity Federation
Workforce Identity Federation lets users authenticate with their corporate SAML/OIDC IdP and receive short-lived Google credentials without provisioning shadow Google accounts. The user signs in via https://auth.cloud.google.com/signin/locations/global/workforcePools/POOL_ID/providers/PROVIDER_ID, gets a federated principal of the form principal://iam.googleapis.com/locations/global/workforcePools/POOL_ID/subject/SUBJECT, and IAP treats them as a regular identity for IAM bindings.
Pattern B: Identity Platform (External Identities)
For consumer-facing apps that allow Google, Facebook, GitHub, OIDC, SAML, phone, or password sign-in, enable "External Identities" in IAP settings and back it with Identity Platform (formerly Firebase Authentication). IAP redirects to a customizable sign-in page hosted by Identity Platform; on success it mints the standard JWT assertion with the user's federated identity as the email claim. This is the only way to expose IAP-protected apps to non-Google users without giving them a Workspace account.
When NOT to Use IAP for SSO
If your application already integrates with Okta or Azure AD natively (e.g., a SaaS product), do not add IAP in front of it — you would be performing identity verification twice. IAP shines when the underlying app has weak or no auth and you want to bolt on enterprise SSO without rewriting code.
IAP for On-Premises Applications via IAP Connector
A common misconception is that IAP only works for workloads running in Google Cloud. The IAP Connector is a reference architecture (Terraform-deployable from github.com/GoogleCloudPlatform/iap-connector) that runs Ambassador-based reverse proxies on GKE, terminates IAP, and forwards requests over Cloud Interconnect or Cloud VPN to on-premises web servers.
Architecture
Browser → public DNS → External Application Load Balancer (IAP enabled) → GKE Ingress → Ambassador pod → Cloud VPN tunnel → on-prem app at 10.0.0.5:443. The on-prem app sees the request as coming from the GKE pod's IP and trusts the x-goog-iap-jwt-assertion header (which the Ambassador pod forwards unchanged) for the user identity.
Why This Replaces Legacy VPNs
Before IAP Connector, exposing an on-prem SharePoint or Confluence to remote employees meant terminating a corporate VPN, distributing SSL VPN clients, and managing certificates. IAP Connector replaces all of that with a Google sign-in: the user opens confluence.corp.example.com in a browser, signs in once, and IAP enforces the same Access Level (device posture, geography) that protects cloud-native apps. This is the practical realization of BeyondCorp for hybrid environments.
Do not confuse IAP Connector with Identity-Aware Proxy itself. IAP is the GCP service; IAP Connector is an open-source GKE deployment pattern that uses IAP to front on-prem apps. Exam questions sometimes phrase this as "extending IAP to on-prem" — the answer involves deploying the Connector on GKE, not flipping a switch in the IAP console.
Logging, Monitoring, and Operations
IAP emits two log streams to Cloud Logging. cloudaudit.googleapis.com/data_access captures every authorization decision (allow/deny) with the principal email, source IP, and resource path; you must explicitly enable Data Access logs because they are not on by default for IAP. cloudaudit.googleapis.com/activity captures admin operations like enabling IAP or editing the OAuth client.
Useful Log Queries
To find all denied access attempts: resource.type="iap_web" AND protoPayload.authorizationInfo.granted=false. To audit who accessed a specific backend in the last 24h: resource.type="iap_web" AND resource.labels.service_id="BACKEND_ID". Pipe these via a log sink into BigQuery for long-term analytics or into Pub/Sub for SOC alerting.
Metrics in Cloud Monitoring
The iam.googleapis.com/iap/request_count metric tracks request volume broken down by response_code (200, 401, 403). A spike in 403s usually indicates a misconfigured Access Level or an expired session cookie. Set up an alerting policy on the 403 ratio to catch policy regressions within minutes.
Session Length Tuning
IAP issues a session cookie valid for the duration configured on the consent screen (default 3 hours for Workspace, up to 24 hours). For high-security apps lower this via the Admin Console under Security → Google Cloud session control. The cookie is HttpOnly, Secure, and scoped to .cloud.google.com and your custom domain.
白話文解釋(Plain English Explanation)
Analogy 1: The Bouncer at the Speakeasy
Imagine a Prohibition-era speakeasy hidden behind an unmarked door. There is no big neon sign (no public IP), and the building's address is not in the phone book (the VM has no external IP). To get in, you knock at a small window where a bouncer (IAP) checks two things: the password you whisper (Google OAuth login) and whether you are wearing the right hat (Access Level: device posture, source IP). If both match the guest list (IAM binding roles/iap.httpsResourceAccessor), the bouncer slides the door open and you walk straight to the bar. No tunnel under the building (no VPN), no membership card (no VPN client) — just the bouncer making a decision on every single knock.
Analogy 2: The Hotel Concierge with a Sealed Envelope
When you ask a hotel concierge to deliver a package to room 1207, the concierge writes "Verified: Mr. Chen from Room 1207" on a tamper-evident envelope (the x-goog-iap-jwt-assertion JWT) and signs it with the hotel's seal (ES256 signature). The room service staff (your backend) opens the envelope, checks the seal against the hotel's master stamp (the JWK public key at gstatic.com), and reads who really sent it. If somebody slips a hand-written note under the door claiming to be Mr. Chen (a forged x-goog-authenticated-user-email header from someone bypassing the load balancer), room service ignores it because there is no sealed envelope. That is why audience verification matters — it's the seal that nobody else can forge.
Analogy 3: The Pneumatic Tube System
Old department stores had pneumatic tubes that whisked cash and receipts between counters and the cashier's office. IAP TCP forwarding is the cloud version: instead of walking your SSH packets through the public internet (the front door), you stuff them into a sealed capsule and shoot it through Google's private pneumatic tube straight to the VM's internal IP. The capsule is labeled with your gcloud OAuth token; if your name is on the approved list (roles/iap.tunnelResourceAccessor), the tube delivers. If not, the capsule is incinerated at the entry point — and you never even saw the VM's address, let alone its open port.
Exam Tips, Common Traps, and Cost Considerations
Trap: IAP without a Load Balancer for GCE/GKE
IAP for Compute Engine VMs requires an HTTP(S) Load Balancer in front. There is no way to enable IAP directly on a single VM's external IP for web traffic. For GKE, this means using an Ingress resource with the kubernetes.io/ingress.class: gce annotation, not a Service of type LoadBalancer (which provisions a Network LB).
Trap: Forgetting Firewall Rules for IAP TCP Range
The 35.235.240.0/20 range is required for TCP forwarding. If your default-deny firewall blocks it, gcloud compute ssh --tunnel-through-iap will hang with Connection failed: 4003 'failed to connect to backend'. Allowing this range does not expose the VM to the public internet — only authenticated IAP tunnels originate from it.
Trap: Mistaking IAP for a Firewall
IAP is not a packet filter. It performs application-layer authentication; firewall rules and Cloud Armor handle network-layer filtering. A request that fails IAP authorization is rejected with HTTP 403 after TCP handshake and TLS termination — it does not save network bandwidth the way a denied SYN at the firewall does.
Cost Considerations
IAP itself is free of charge — there is no per-request fee for the proxy. You pay only for the underlying load balancer (forwarding rules, data processing), the OAuth Consent Screen verification (free), and any BeyondCorp Enterprise license if you use advanced device posture conditions. Replacing a $500/month VPN concentrator with IAP typically saves the VPN licensing, the concentrator hardware/VM, and the operational toil of managing client software.
Frequently Asked Questions
Q1: Does IAP replace a firewall or VPC firewall rules?
No. IAP performs application-layer authentication and authorization for HTTPS or TCP-forwarded traffic. You still need VPC firewall rules to (a) allow load balancer health checks from 130.211.0.0/22 and 35.191.0.0/16, and (b) for TCP forwarding, allow source range 35.235.240.0/20. Configure firewalls to deny direct inbound traffic to backends so users cannot bypass IAP by hitting the VM's IP directly.
Q2: Can I use IAP for non-Google users (consumers, partners)?
Yes, through Identity Platform External Identities integration. Enable External Identities in IAP settings, configure providers (Google, Facebook, GitHub, generic OIDC, SAML, email/password, phone), and IAP will redirect unauthenticated users to a customizable Identity Platform sign-in page. The resulting JWT still uses x-goog-iap-jwt-assertion, but the email claim now contains the federated identity.
Q3: What is the difference between x-goog-authenticated-user-email and x-goog-iap-jwt-assertion?
x-goog-authenticated-user-email is a convenience header containing the user's email in clear text. It is reliable only when the request definitely came through IAP (which you cannot guarantee if backends have public IPs). x-goog-iap-jwt-assertion is a cryptographically signed JWT — verifying its ES256 signature and aud claim proves the request transited IAP for your specific backend. Always verify the JWT for any authorization decision; treat the email header as display data only.
Q4: How do I SSH to a VM with no external IP using IAP?
Ensure the VM's project has iap.googleapis.com enabled, your user has roles/iap.tunnelResourceAccessor on the instance, and a firewall rule allows TCP:22 from 35.235.240.0/20. Then run gcloud compute ssh INSTANCE_NAME --tunnel-through-iap --zone=ZONE. The gcloud CLI handles the OAuth flow, opens a WebSocket to tunnel.cloudproxy.app:443, and proxies SSH bytes through Google's network to the VM's internal IP.
Q5: Can IAP enforce device posture (e.g., "only patched laptops")?
Yes, via Access Context Manager Access Levels combined with Endpoint Verification (a Chrome extension or Workspace-managed agent). Define an Access Level with devicePolicy.osConstraints (minimum OS version), devicePolicy.requireScreenlock, or devicePolicy.requireCorpOwned (BeyondCorp Enterprise), then bind it to the IAP IAM policy. Users on non-compliant devices receive a 403 page explaining the failing condition.
Q6: Does IAP work with regional load balancers or only global?
IAP for HTTPS requires the Global External Application Load Balancer. Regional External Application Load Balancers, Internal Application Load Balancers, Network Load Balancers, and TCP Proxy Load Balancers do not support IAP for web app protection. For internal-only workloads, the typical pattern is global LB + IAP + Access Level restricting to your corporate IP range — achieving the same "internal only" outcome with strong identity guarantees.
Q7: How do I extend IAP to applications running on-premises?
Deploy the IAP Connector reference architecture on GKE: it runs Ambassador-based reverse proxies that terminate IAP at the GCP edge and forward authenticated requests over Cloud Interconnect or Cloud VPN to your on-prem web servers. The on-prem app sees the original x-goog-iap-jwt-assertion header and can verify it identically to a cloud-native app. This pattern is the practical implementation of BeyondCorp for hybrid environments and is documented at cloud.google.com/iap/docs/enabling-on-prem-howto.