Search code examples
google-cloud-functionsserverless

Generate bearer token for google cloud function - Java


I'm trying to connect to cloud function such as https://us-west1-<>.cloudfunctions.net from java, and I'm trying to generate the bearer token for this function using a code as follows:

String audience = https://<projectname>-<region>-<projectid>.cloudfunctions.net/<myFunction>;

GoogleCredentials credentials = GoogleCredentials
                .getApplicationDefault()
                .createScoped(Arrays.asList("https://www.googleapis.com/auth/cloud-platform"));

IdTokenCredentials tokenCredential =
                IdTokenCredentials.newBuilder()
                    .setIdTokenProvider((IdTokenProvider) credentials)
                    .setTargetAudience(audience)
                    .build();
        
tokenCredential.refresh();
        
String token = tokenCredential.getIdToken().getTokenValue();

When I run the application the token is generated. But if I take the token and put this on postman, the server returns an 401 error: 401 Unauthorized.

if I use the GCP command "gcloud auth print-identity-token" in GCP cloud shell terminal and use this token in postman, the cloud function invocation is successful.

The Json file used to get the credentials is similar to this:

{
  "type": "service_account",
  "project_id": "<project_id>",
  "private_key_id": "<private_key_id>",
  "private_key": "-----BEGIN PRIVATE KEY----------END PRIVATE KEY-----\n",
  "client_email": "aaa@<project_id>.iam.gserviceaccount.com",
  "client_id": "<client_id>",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/<principle>"
}

Please help me in figuring out how to generate a bearer token in java to invoke a google cloud function.

Thanks


Solution

  • This issue got fixed when I used the correct audience value as below.

    https://function-url/projects/project-id/locations/region/functions/function-name

    In the above URI, replace function-url, project-id, region, and function-name with your values.

    Following is the working code.

    public String getAccessToken(String audience) throws IOException {
            
            InputStream resource = new ClassPathResource(
                      "gcp/service-account.json").getInputStream();
            
            GoogleCredentials credentials = GoogleCredentials
                     .fromStream(resource)
                     .createScoped(Arrays.asList("https://www.googleapis.com/auth/cloud-platform"));
            
            credentials.refreshAccessToken();
            
            IdTokenCredentials tokenCredential =
                    IdTokenCredentials.newBuilder()
                        .setIdTokenProvider((IdTokenProvider) credentials)
                        .setTargetAudience(audience)
                        .build();
                    
            tokenCredential.refresh();
            
            return tokenCredential.getIdToken().getTokenValue();
          }
    

    In the above code,

    1. The "gcp/service-account.json" is the path of my service account json file. It is under the src/main/resources folder (i.e. classpath) in my spring-boot project.
    2. The credentials.refreshAccessToken(); and tokenCredential.refresh(); might not be needed. I did not try removing these. Will try when get time.

    Hope it helps guys!! Since I could not find much help on the "audience" value, so it took me some time to figure out the correct value by trial and error.