[Python] GCP Python ID Token Authentication with Impersonated Service Account without...

Discussão em 'Python' iniciado por Stack, Julho 24, 2025.

  1. Stack

    Stack Membro Participativo

    As in the question, how can I retrieve an impersonated service account's id token without downloading the service account credentials file from the GCP IAM console. The point is to test a service code on my local machine by authorizing GCP client libs & authenticating external iap services through the impersonated service account such that the very same code must also work on the deployed environment on GCP (whose metadata server is available).

    Retrieving the access token (you can skip reading this part)


    I recently found out the solution, but for the access token; here is the steps:


    1. Grant your user account the Token Creator role on the service account (namely svc@proj.iam.gserviceaccount.com)


    2. Run this on your terminal and login

      gcloud auth application-default login --impersonate-service-account svc@proj.iam.gserviceaccount.com


      Here you can see that the credentials in the path /Users/youruser/.config/gcloud/application_default_credentials.json will now be the impersonated credentials:

      {
      "delegates": [],
      "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/svc@proj.iam.gserviceaccount.com:generateAccessToken",
      "source_credentials": {
      "account": "",
      "client_id": "xxxxxxxxxxxxx.apps.googleusercontent.com",
      "client_secret": "xxxxxxxxxxxxxxxxx",
      "refresh_token": "xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
      "type": "authorized_user",
      "universe_domain": "googleapis.com"
      },
      "type": "impersonated_service_account"
      }


      Instead of the plain old user account credentials like this:

      {
      "account": "",
      "client_id": "xxxxxxxxxxxxx.apps.googleusercontent.com",
      "client_secret": "xxxxxxxxxxxxxxxxx",
      "quota_project_id": "proj",
      "refresh_token": "xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
      "type": "authorized_user",
      "universe_domain": "googleapis.com"
      }

    3. Set the env var GOOGLE_APPLICATION_CREDENTIALS to the recently logged in path (or alternatively using dotenv libs in your project)

      export GOOGLE_APPLICATION_CREDENTIALS=/Users/youruser/.config/gcloud/application_default_credentials.json

    4. This code will now recognized the impersonated service account and retrieve its access token:

      import google.auth
      import google.auth.transport.requests
      from google.auth import credentials

      creds, project_id = google.auth.default(scopes=scopes, **kwargs)
      auth_req = google.auth.transport.requests.Request()
      creds.refresh(auth_req)
      # use `creds` accordingly
    Retrieving the id token (the question)


    Such steps for the access token does not work when retrieving its id token, I'm not really sure if I'm using the right function (google.oauth2.id_token.fetch_id_token) or if I'm missing something. Here is the code:

    import google.auth.transport.requests
    import google.oauth2.id_token


    """
    From https://google-auth.readthedocs.io/en/master/user-guide.html#identity-tokens
    """
    request = google.auth.transport.requests.Request()
    creds = google.oauth2.id_token.fetch_id_token(request, aud)


    Here's the error:

    google.auth.exceptions.DefaultCredentialsError: Neither metadata server or valid service account credentials are found.


    I imagine it might be that the creds file from application-default login only covers for the access token as it sends the request to generateAccessToken endpoint (as seen in the creds json). Moreover, there is no gcloud auth application-default print-identity-token either, only print-access-token.

    Back to the question, is it possible? Or the only way is to download the service account credentials file, which ironically is against Google's recommendation and defeats the purpose of impersonation?

    Continue reading...

Compartilhe esta Página