Skip to content

Quota project id broken for OAuth2Credentials's async getRequestMetadata() #507

@ejona86

Description

@ejona86

Environment details

  • grpc: 1.35.0-SNAPSHOT (which uses the async API)
  • google-auth-library-java version(s): 0.22.0

Steps to reproduce

  1. Use GoogleCredentials.getApplicationDefault()
  2. Use sync getRequestMetadata(). x-goog-user-project is present
  3. Use async getRequestMetadata(), with the RequestMetadataCallback. x-goog-user-project is missing

Stacktrace

I was trying to do some development with a weird setup. But I encountered:

Status{code=PERMISSION_DENIED, description=Your application has authenticated using end user credentials from the Google Cloud SDK or Google Cloud Shell which are not supported by the trafficdirector.googleapis.com. We recommend configuring the billing/quota_project setting in gcloud or using a service account through the auth/impersonate_service_account setting. For more information about service accounts and how to use them in your application, see https://cloud.google.com/docs/authentication/., cause=null}

Code snippet

Credentials creds = GoogleCredentials.getApplicationDefault();
// I had used "gcloud auth application-default login", so these were UserCredentials
System.out.println("creds: " + creds);
System.out.println("metadata: " + creds.getRequestMetadata());
creds.getRequestMetadata(null, null, new RequestMetadataCallback() {
  public void onSuccess(Map<String, List<String>> metadata) {
    System.out.println("async metadata: " + metadata);
  }

  public void onFailure(Throwable exception) {}
});

What's going on

So it is "obvious" that x-goog-user-project is being added to the metadata. However, that's the slow path. OAuth2Credentials has a cache that it uses when available (requestMetadata), to avoid jumping threads when RequestMetadataCallback is specified. The cache is only set in useAccessToken(AccessToken), which is called in refresh(). So requestMetadata will never be processed by addQuotaProjectIdToRequestMetadata(), and hence the async code lacks the quota project if the cache is already available.

Aside: It's confusing that quota_project_id is the name used in the JSON key file. Normally "project id" is an integer while "project name" is the pretty name.

Metadata

Metadata

Assignees

Labels

🚨This issue needs some love.priority: p1Important issue which blocks shipping the next release. Will be fixed prior to next release.type: bugError or flaw in code with unintended results or allowing sub-optimal usage patterns.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions