I want to access a websites REST APIs that is deployed on GCP and is behind Identity-Aware-Proxy (IAP). I only need to be able to access from my local computer, and I can't use Service Account key to achieve that.
I've tried to use gcloud auth login
and gcloud auth application-default login
to get application_default_credentials set, and then call Oauth2 endpoint to get the id_token.
No matter what I try I keep getting back an error "The audience client and the client need to be in the same project".
The client_id I have in default credentials (74XXXXXXX) and the client_id for IAP (73XXXXXXX) don't match, but they are both using the same GCP project.
Been using Python example from this (How to authenticate programmatically to a Cloud Identity-Aware Proxy (Cloud IAP)-secured resource using user default credentials?) question:
import google.auth
import requests
import json
def id_token_from_default_creds(audience):
cred, proj = google.auth.default()
# data necessary for ID token
client_id = cred.client_id
client_secret= cred.client_secret
refresh_token = str(cred.refresh_token)
return id_token_from_refresh_token(client_id, client_secret, refresh_token, audience)
def id_token_from_refresh_token(client_id, client_secret, refresh_token, audience):
oauth_token_base_URL = "https://www.googleapis.com/oauth2/v4/token"
payload = {"client_id": client_id, "client_secret": client_secret,
"refresh_token": refresh_token, "grant_type": "refresh_token",
"audience": audience}
res = requests.post(oauth_token_base_URL, data=payload)
return (str(json.loads(res.text)[u"id_token"]))
print("ID token from \"default\" credentials: %s" % id_token_from_default_creds("<IAP Client ID>"))
Any ideas how to pass IAP with local user credentials?
The audience client and the client need to be in the same project. This means that default credentials client ID and IAP client ID do not have matching project numbers. Using default credentials generated from gcloud auth application-default login gives the mismatch Client_ID for default credentials because the Client_ID should start with a project number. The project for Client ID used to obtain refresh token should match the project for IAP Client ID. Gcloud uses Client ID and secret defined in path_to/google-cloud-sdk/lib/googlecloudsdk/api_lib/auth/util.py for default credentials (DEFAULT_CREDENTIALS_DEFAULT_CLIENT_ID and DEFAULT_CREDENTIALS_DEFAULT_CLIENT_SECRET). Because of that, we can't use the refresh token from google.auth.default() without util.py change.
I ended up following Johns comment (Access website behind IAP programatically?), and created a desktop app in GCP Credentials. I'm using client_id and client_secret from the desktop app to first get auth_code
, then refresh_token
, and then id_token
trough the Oauth2 API. This token then can be used in the header to pass IAP.
The code now opens a browser tab where the user needs to login, but that is fine for my use case. See https://stackoverflow.com/a/49129038/1411088 for the code example.