What is GCP Identity-Aware Proxy (IAP)?
Google Cloud Platform (GCP) offers a product called Identity-Aware Proxy (IAP) that helps guard access to your applications running on App Engine, Cloud Run, Compute Engine, GKE or On-premises (outside GCP in your own data centres or a different cloud provider).
Think OAuth-based authentication right at the load balancer level before a request is able to make it to your application. Once the authentication happens, some authorization mechanisms can be involved too.
What is it?
Let’s say if we were running a bunch of internal apps for our business on multiple Compute Engine VMs (as part of instance groups), using IAP we could easily enable authentication and some form of authorization at the load balancer level for our internal app users. As an example, say we wanted to run a CI/CD software only accessible by our engineering team at https://ci.company.com
. In order to use IAP, we would have to:
- Set up a MIG (managed instance group) to run the CI/CD tool on a group of VMs.
- Put an external HTTP(S) Load Balancer with the instance group as its backend services which would also involve creating a Google-managed (or user-provided) SSL certificate for
ci.company.com
. - Enable IAP on the backend service entity that maps our instance group to the LB.
- At this point, we should also make sure that there are no firewall rules allowing traffic to the MIG VMs, except from the LBs. This is good for security.
- Give
IAP-secured Web App User
role to the IAM principal (users, groups, service accounts, workspace domains, etc.) who will be permitted to access the application (CI/CD software) over HTTP(s) athttps://ci.company.com
after they have successful authentication. You can assign this role to[email protected]
(individual users),[email protected]
(group of users) or evencompany.com
(any email with this domain). You also have the option to assign the role toallUsers
principal to sort of disable IAP or toallAuthenticatedUsers
to allow any Google account authenticated user.
Now when we try to access the application in our browser (at https://ci.company.com
), GCP’s LB infrastructure will read the request headers and cookies that will contain the IAP credentials and forward these information with some additional request details to the IAP authentication server (part of GCP’s internal infrastructure) to check if the incoming request is authenticated or not.
If the request is authenticated then the user will be able to access the application but if not then the user will be redirected to an OAuth 2.0 Google Account sign-in flow where he will have to authenticate himself leading to the generation of the IAP credentials that will get stored in browser cookies.

By default, IAP triggers Google’s default identity authentication flow. If you want to use your own custom authentication implementation or a different OAuth 2.0 provider for instance, then IAP supports external identities by leveraging another product called Identity Platform (IdP). IdP is the same product that backs Firebase Auth too.
Here’s a detailed guide on how external identities can be enabled and configured. Using IdP, a wide range of external identity providers can be used to authenticate our users, like:
- Custom sign-in with Email/password
- OAuth (Github, Microsoft, Facebook, Twitter, Google, etc.)
- SAML
- OIDC
- Phone Number
- Custom Auth Implementations
Benefits
What are the benefits here of doing all of this, i.e., setting up IAP with the load balancer?
- Our applications (behind the LB) are restricted from being accessed by everyone. Only those who are able to authenticate and have permission to access (through IAM) will be able to get through. We don’t have to implement our own authentication module and hence we save time.
- Access to the apps is centralised. You can maintain the list of users (employees) that you want to give access to in the GCP IAM section. This might make it feel like IAP is tied to IAM principals (users, groups, service accounts) but IAP can also be used with external identities as discussed above.
- Although not mentioned, in the 5th step above (previous section of how to set up IAP), we can specify something called access levels to set up “context-aware” access. For this you will have to use a complementary security product called Access Context Manager through which you can restrict users/requests at different levels like IP address, user devices (restrictions on OS versions, whether the mobile device has a lock screen, etc.) and so on and so forth.
- Effectively, a zero-trust access model is implemented (never trust, always verify) which is supposedly better than relying on a perimeter security model (adjusting network firewalls, etc.) where anything outside the network is considered dangerous but everything inside is trusted. Instead regardless of being outside or inside, every request for each user should be verified.
- GCP claims that they’ve relied on this model to let their employees work from untrusted networks and hence gotten rid of VPN gateway/client setups.
User Details
The authenticated user’s details are accessible in your app via various headers. You can primarily focus on the x-goog-iap-jwt-assertion
header that contains a signed JWT from which you can verify and retrieve (the link has code samples) some user details like email, ID, etc. Additional headers are passed containing the email and ID separately – x-goog-authenticated-user-{email,id}
– but verifying the JWT is better for security.

This is what the decoded JWT looks like:
{
"aud": "/projects/xxx/global/backendServices/yyy",
"azp": "/projects/xxx/global/backendServices/yyy",
"email": "securetoken.google.com/PROJECT_ID:[email protected]",
"exp": 1689851376,
"gcip": {
"auth_time": 1689849913,
"email": "[email protected]",
"email_verified": true,
"firebase": {
"identities": {
"email": [
"[email protected]"
],
"google.com": [
"zzz"
]
},
"sign_in_provider": "google.com"
},
"name": "John Doe",
"picture": "<https://lh3.googleusercontent.com/x/y/z>",
"sub": "USER_ID",
"user_id": "USER_ID"
},
"iat": 1689850776,
"iss": "<https://cloud.google.com/iap>",
"sub": "securetoken.google.com/PROJECT_ID:USER_ID"
}
If you are using external identities via Identity Platform instead of using the default Google sign-in flow of IAP, you will have to pass the ID tokens as bearer tokens to authenticate yourself. You can get ID tokens in one of the following two ways:
- Generate them when you implement your external identity using the Firebase/Identity Platform Web SDK (or mobile SDKs) on the client side.
- Or exchange the identity provider tokens (OIDC id tokens or OAuth 2.0 access tokens) for an ID token. Identity provider tokens belong to the third-party provider and you get access to them client-side when using one of the Firebase SDKs (web or mobile).
Although you will pass the ID tokens as bearer tokens in case of external identities, IAP will continue to issue its own JWT token (as shown above for default Google identity). The JWT token will wrap the additional details/claims from the ID token if required, more details here.
Access Control
Although IAP is useful to quickly set up authentication via (default) Google identity or external identity setups, it doesn’t really provide a good way to implement access control (think RBAC) for the application. Like if we wanted to show different UI and have different functionality for different types of users (admin, editor, viewer, etc. types of roles), IAP wouldn’t be of much help.
Some ideas that can be tried to solve this:
- Maintain your own DB of users with roles/permissions mapped to them. You can then fetch the user email from the incoming headers (discussed in the previous section), pull out the role/permission details from the DB and then perform API calls and/or change the UI accordingly.
- Get user’s group memberships using the Directory API and apply access control on group emails.
- Specify host and path conditions when assigning the
IAP-secured Web App User
role. - With external identities, we can use a provider like SAML that can set custom JWT claims in the
sign_in_attributes
field of the incoming JWT header token that can be further used to perform access control.
TCP Forwarding and SSH Access
This section covers additional useful features of IAP which is different from the HTTPS request authentication use cases we covered above.
If you did not already notice, IAP is used by default when you SSH into VMs (gcloud compute ssh instance-name
) that do not have an external IP, but only an internal IP. You can also use the optional --tunnel-through-iap
flag with the gcloud
SSH command.
The way it works is that gcloud
creates an HTTPS connection with the Cloud IAP proxy service in GCP’s infrastructure that wraps the SSH connection and forwards it to the remote instance (without external IP). This is really useful and requires creating a firewall rule to allow the proxy to make SSH connections with the instance.
Another feature of IAP tunnelling is the ability to forward TCP traffic from your local machine to an internal VM via the proxy in an HTTPS stream. So if you had an HTTP server running on port 80
of your internal VM, the following command would allow you to send traffic to it by accessing http://localhost:8080
in your browser (locally):
gcloud compute start-iap-tunnel instance-name 80 \
--local-host-port=localhost:8080
This might remind you of vanilla SSH port forwarding.
Final Thoughts
IAP is a part of or stepping stone towards a bigger product or initiative of GCP called BeyondCorp which you can explore further.
I think in order to secure an internal application for a business or organisation that is also using GCP for their cloud computing needs, IAP does make a lot of sense to quickly implement authentication with some access level restrictions. If you were building a consumer-facing product though, using the Identity Provider product (or Firebase auth) directly would make more sense than choosing IAP.
For SSH access of VMs without external IP or doing port forwarding, IAP is anyway used by default and makes complete sense.