allAuthenticatedUsers on IAP: when authentication is not authorization
Identity-Aware Proxy gates internal apps with IAM, not network. One over-broad binding to allAuthenticatedUsers lets any signed-in Google account reach the app.
Identity-Aware Proxy replaces the VPN as the gate to internal apps, and that gate is IAM, not network. Blocking an IP does nothing when the binding admits anyone signed in.
How the attack works
An internal application is published behind IAP so only a specific group should reach it. But an over-broad IAM binding grants roles/iap.httpsResourceAccessor to allAuthenticatedUsers, so any signed-in Google identity passes the IAP check. An attacker with any authenticated account browses straight to the app, exercises its functionality, and reaches admin or data views that assumed only trusted users could arrive, including using an in-app export to pull records. IAP and load-balancer logs show a successful authenticated access from an identity outside the intended audience. In ATT&CK terms this is T1190, Exploit Public-Facing Application, paired with T1078.004, Valid Accounts: Cloud Accounts.
Why it works
IAP authenticates the caller, but authentication is not authorization when the binding is over-broad. A binding to allAuthenticatedUsers admits any signed-in Google account, and that public member sails past the access reviews that look only at named users.
How to fix it
An IP block is trivially evaded by any other authenticated user. Edit the IAP IAM policy to grant iap.httpsResourceAccessor only to the intended users or group and remove allAuthenticatedUsers, then confirm the backend verifies IAP enforcement rather than blindly trusting a forwarded identity header. For the root cause, audit every IAP-protected resource for allUsers, allAuthenticatedUsers, and over-broad groups, enforce least-privilege accessor bindings, and add an org-policy or IAM check that flags public members on IAP resources. Scope what was reached by correlating IAP and load-balancer logs with the application’s own logs, and treat any exercised export as confirmed access to that data.
Practice it
We built this as a GraphLattice Range scenario so administrators can rehearse fixing an over-broad IAP binding, verifying the backend does not blindly trust a forwarded header, and scoping the access, instead of just blocking an IP.