Identity-Aware Proxy (IAP): Ditching the VPN for Application Access
The traditional model for internal application access is a network perimeter: connect to the VPN, and you’re “inside,” trusted by everything behind that perimeter for as long as the connection lasts. This model has a well-documented failure mode — once an attacker (or a compromised laptop) is inside the perimeter, lateral movement to anything else on that network is often trivially easy, because the security model stopped checking identity the moment the VPN handshake succeeded. Identity-Aware Proxy (IAP) is Google’s implementation of a fundamentally different model: instead of trusting the network, check identity and context on every single request, regardless of where it originates.
This is the practical, easy-to-start-with entry point into what Google calls BeyondCorp — the zero-trust architecture Google itself runs internally, productized for customers. IAP is the piece that actually sits in front of your applications enforcing that model, and it’s a much smaller lift to adopt than the phrase “zero trust architecture” might suggest.
How IAP Actually Works
User request │ ▼IAP (sits in front of the load balancer / application) │ ├── 1. Verify user identity (Google sign-in / SSO) ├── 2. Check IAM: is this user authorized for this app? ├── 3. Evaluate context (device compliance, IP, location) │ ▼Allowed? ──Yes──► Forward request to backend, with a signed │ identity header the app can trust No │ ▼403 / redirect to sign-inEvery single request is evaluated, not just the initial connection — this is the meaningful difference from VPN-based access, where authentication happens once and then the network trusts everything on that connection indefinitely. If a user’s access is revoked mid-session, the very next request they make is denied; there’s no lingering trusted-connection window to close out.
IAP forwards a signed JWT identity header (X-Goog-IAP-JWT-Assertion) to your backend application, which your app can verify to know exactly who made the request without implementing its own authentication layer — the identity check happened before the request ever reached your code.
Setting Up IAP for a Web Application
# Enable the IAP APIgcloud services enable iap.googleapis.com
# Grant a user access to the IAP-secured resourcegcloud iap web add-iam-policy-binding \ --resource-type=backend-services \ --service=my-app-backend-service \ --member="user:jane@company.com" \ --role="roles/iap.httpsResourceAccessor"The roles/iap.httpsResourceAccessor role is the key piece — it’s what actually grants “can reach this application through IAP,” separate from any IAM roles the user might have for other GCP resources. A user can have this role and nothing else, meaning they can reach the application but have zero permission to touch any other GCP resource — exactly the narrow scope you want for, say, an external contractor who only needs access to one internal dashboard.
TCP Forwarding: SSH and RDP Without a Bastion Host
Beyond HTTP applications, IAP supports TCP forwarding — tunneling SSH and RDP traffic through the same identity-checked proxy, which eliminates the traditional bastion host pattern entirely.
# SSH into a VM with no public IP, no bastion host, no VPNgcloud compute ssh my-vm \ --zone=us-central1-a \ --tunnel-through-iapThis single command does something that used to require real infrastructure: it establishes an encrypted tunnel through IAP to a VM’s internal IP, using the caller’s IAM identity for authorization, without the VM ever needing a public IP address or an SSH bastion host in front of it. The VM’s attack surface for SSH access shrinks to “nothing exposed to the internet at all,” which is a meaningfully better security posture than even a well-hardened bastion host.
# The equivalent for RDP, tunneling a local portgcloud compute start-iap-tunnel my-windows-vm 3389 \ --local-host-port=localhost:3390 \ --zone=us-central1-aContext-Aware Access: Beyond Just “Who”
IAP’s authorization checks can go beyond identity alone, using Context-Aware Access to factor in device state, IP range, and geographic location:
# Access level requiring a company-managed, compliant devicename: accessPolicies/123456789/accessLevels/corp-managed-devicebasic: conditions: - devicePolicy: requireScreenLock: true requireCorpOwned: true ipSubnetworks: - "203.0.113.0/24"Attaching an access level like this to an IAP-secured resource means “authorized user” alone isn’t sufficient — the request also has to originate from a compliant, corp-owned device. This directly addresses a scenario VPN-based access handles poorly: a valid user’s credentials, phished and used from an attacker’s unmanaged device, would pass a traditional VPN check but fail this context-aware evaluation outright.
IAP vs a Traditional VPN: The Actual Trust Model Difference
It’s worth making the contrast explicit, because “zero trust” is thrown around loosely enough that the concrete difference gets lost.
The VPN model authorizes once, broadly, at the network layer. The IAP model authorizes per application, per request, at the identity layer — a user with access to App A gains nothing toward App B unless explicitly granted. This is the concrete mechanism behind “zero trust” rather than an abstract security philosophy: no request is trusted based on where it came from, only based on who’s making it and whether they’re specifically authorized for that exact resource.
Real-World Use Case: Replacing a Legacy VPN for Internal Tools
A company with a handful of internal admin dashboards, historically reachable only via VPN, is a common IAP migration case. The VPN model meant every internal tool was reachable by anyone with valid VPN credentials, regardless of whether they actually needed access to that specific tool — a flat trust model that’s simple to set up and genuinely risky at scale. Migrating each internal tool behind IAP, with per-application iap.httpsResourceAccessor grants scoped to the specific teams that need each tool, replaces “anyone on the VPN can reach anything” with “each person can reach exactly the tools their role requires” — and removes the VPN client, VPN gateway infrastructure, and VPN-specific incident response playbook entirely as a side benefit.
Best Practices
- Scope
iap.httpsResourceAccessorper application, not organization-wide. Granting it broadly defeats the purpose — the whole value is precise, per-application access control. - Layer Context-Aware Access on top of identity for genuinely sensitive applications, not just public-facing ones — internal admin tools handling customer data deserve device-compliance requirements too.
- Verify the IAP JWT server-side in your application, don’t just trust that traffic reaching your backend has already been checked — defense in depth means your app should still validate the signed assertion rather than assuming network position implies authorization.
- Combine IAP with VPC Service Controls for data resources, since IAP secures application-layer access but doesn’t by itself prevent data exfiltration paths at the API level — they’re complementary, not redundant.
- Roll out IAP one application at a time rather than a big-bang cutover. Migrating internal tools incrementally, starting with lower-risk applications, gives the team time to build confidence in the access-grant workflow before it’s protecting anything genuinely critical.
Common Mistakes
Treating IAP as “set it and forget it” without maintaining access grants. Just like any access control system, iap.httpsResourceAccessor grants accumulate over time and need periodic review — an ex-contractor’s lingering access to an internal tool is exactly the kind of gap IAP is supposed to prevent, not create through neglect.
Not verifying the JWT in application code. Relying purely on “IAP is in front of this, so anything reaching us is safe” removes a layer of defense — if IAP is ever misconfigured or bypassed through a network path nobody accounted for, an application with no independent verification has no fallback check.
Applying IAP only to the web UI while leaving an API backend directly reachable. A common gap: the frontend is nicely secured behind IAP, but the API it calls is also independently reachable on the internet without the same protection, because it was set up separately and nobody connected the two configurations.
Forgetting that Context-Aware Access levels need to be actively maintained. An access level tied to a specific corporate IP range breaks silently the day that range changes — treat access level definitions as configuration that needs the same change-management discipline as any other infrastructure code.
Frequently Asked Questions
Does IAP replace the need for application-level authentication entirely? For internal tools, often yes — IAP’s identity assertion is sufficient. For customer-facing applications with their own user base (not your organization’s employees), IAP isn’t the right tool; it’s designed for securing access by your organization’s identities, not arbitrary public users.
Can IAP work with on-prem applications? Yes, via IAP for on-premises apps, which uses a connector to extend the same identity-aware proxy model to applications that aren’t hosted on GCP — useful during a gradual cloud migration where some internal tools haven’t moved yet.
What happens to an active session if a user’s access is revoked mid-use? Because IAP evaluates authorization per-request rather than per-session, the very next request after revocation is denied — there’s no lingering trusted window like a VPN connection would have.
Is IAP a full replacement for a VPN in every scenario? For application and SSH/RDP access, generally yes. For scenarios requiring genuine network-layer connectivity (accessing a raw database port directly, for instance, rather than through an application), a VPN or Private Service Connect may still be the more appropriate tool.
Does IAP add noticeable latency to requests? The identity and authorization check adds a small, generally imperceptible amount of latency per request — far less overhead than most teams expect, and negligible compared to typical application response times.
Can IAP secure a Cloud Run or GKE-hosted application, or only Compute Engine? IAP works across GCP’s compute options — App Engine, Compute Engine, GKE Ingress, and Cloud Run can all sit behind IAP, provided the traffic is routed through a supported load balancer configuration.
What happens to third-party or partner users who don’t have a company Google account? IAP supports external identities through Cloud Identity’s external user management or federated identity providers, so partner and contractor access doesn’t require issuing them a full internal account just to reach one application.
Summary
IAP’s real contribution is collapsing “are you on the right network” into “are you the right identity, on an acceptable device, right now” — a genuinely stronger security model that also happens to remove a category of infrastructure (VPN gateways, bastion hosts) most teams maintain reluctantly rather than because it’s the best tool for the job. The migration effort is smaller than the “zero trust” framing suggests: identify your internally-facing applications, put them behind IAP with scoped access grants, roll out one application at a time, and layer in device-compliance requirements for anything genuinely sensitive. The VPN model isn’t wrong so much as it’s checking the right question (“who are you”) at the wrong frequency (once, at connection time, then trusting the network indefinitely) — IAP just asks it continuously, on every single request, instead — which is a small reframing with genuinely large security consequences once it’s actually in place.