1

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?

Dawiss
  • 65
  • 1
  • 11
  • 1
    The credentials that **google.auth.default()** is grabbing are **user account** credentials. You are then trying to extract the Client ID and Client Secret and use them to generate an OIDC Identity Token, which was not originally requested by **gcloud auth application-default login** as a requested scope. I do not believe that you can successfully do that. Verify that the Identity Token is valid including the signature. The error message might be misleading you. – John Hanley Sep 01 '21 at 05:24
  • Could you elaborate on how to do that? – Dawiss Sep 01 '21 at 05:39
  • Client_ID should start with the project number. In your case which Client_ID is matching with the project number. Is it default credentials Client_ID or IAP Client _ID? – Jyothi Kiranmayi Sep 02 '21 at 06:28
  • Did you update the fields _DEFAULT_CREDENTIALS_DEFAULT_CLIENT_ID_ and _DEFAULT_CREDENTIALS_DEFAULT_CLIENT_SECRET_ in file _path_to/google-cloud-sdk/lib/googlecloudsdk/api_lib/auth/util.py_ – Jyothi Kiranmayi Sep 02 '21 at 09:48
  • I ended up following Johans advice, and created a desktop app in GCP credentials, and Im using client_id and client_secret from that. The code now opens a browser tab to get auth_code, then I use the oauth2 api to get the id_token which passes through IAP. – Dawiss Sep 02 '21 at 10:43

1 Answers1

0

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.

Jyothi Kiranmayi
  • 2,090
  • 5
  • 14
Dawiss
  • 65
  • 1
  • 11