Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

idtoken serverless sample did not work when running in Cloud Functions #1208

Closed
VeryCrazyDog opened this issue Jul 8, 2021 · 4 comments
Closed
Labels
priority: p2 Moderately-important priority. Fix may not be included in next release. samples Issues that are directly related to samples. type: bug Error or flaw in code with unintended results or allowing sub-optimal usage patterns.

Comments

@VeryCrazyDog
Copy link

I have been following the Cloud Functions documentation to invoke a cloud function from another cloud function.

The target URL I used is in the following format:

https://GCP_REGION-PROJECT_ID.cloudfunctions.net/my-function

Based on the sample code:

if (!targetAudience) {
// Use the request URL hostname as the target audience for requests.
const {URL} = require('url');
targetAudience = new URL(url).origin;
}
console.info(`request ${url} with target audience ${targetAudience}`);

The value of the variables will be:

  • url: https://GCP_REGION-PROJECT_ID.cloudfunctions.net/my-function
  • targetAudience: https://GCP_REGION-PROJECT_ID.cloudfunctions.net

When calling the another cloud function, GaxiosError will be returned with HTTP 401 Unauthorized with error message The access token could not be verified.

After comparing with the JWT generated by metadata server, I found that the value of targetAudience should be set equal to the value of url. After doing so, I can call the another cloud function without error.

In conclusion, the sample should have the targetAudience set equal to url. However, I am not sure if the same applies if the target is Cloud Run.

@product-auto-label product-auto-label bot added the samples Issues that are directly related to samples. label Jul 8, 2021
@bcoe bcoe added type: bug Error or flaw in code with unintended results or allowing sub-optimal usage patterns. priority: p2 Moderately-important priority. Fix may not be included in next release. labels Jul 8, 2021
@bcoe
Copy link
Contributor

bcoe commented Jul 8, 2021

@VeryCrazyDog thanks for digging into this, and figuring out how to make things work in Cloud Functions.

Mind providing an example of the code that worked for Cloud Functions, perhaps we can add a blurb specifically for Cloud Functions.

@VeryCrazyDog
Copy link
Author

Below is the tested code that worked on Cloud Functions. Make sure the permission is properly granted to the caller service account. After deploy, invoke the function on Google Cloud Platform Console via the TESTING page with triggering event payload {"data": {}}.

'use strict'

const functions = require('firebase-functions')
const { GoogleAuth } = require('google-auth-library')

// Hardcoded configurations
const CALLER_SERVICE_ACCOUNT = 'CALLER_SERVICE_ACCOUNT_NAME@CALLER_PROJECT_ID.iam.gserviceaccount.com'
const TARGET_URL = 'https://GCP_REGION-TARGET_PROJECT_ID.cloudfunctions.net/FUNCTION_NAME'

// Dependencies initialization
const auth = new GoogleAuth()

// Cloud function implementation
exports.idtokensServerless = functions.runWith({
  serviceAccount: CALLER_SERVICE_ACCOUNT
}).https.onCall(async (data, context) => {
  const url = TARGET_URL
  const targetAudience = TARGET_URL
  console.info(`Request ${url} with target audience ${targetAudience}`)
  const client = await auth.getIdTokenClient(targetAudience)
  const resp = await client.request({ url })
  console.info(resp.data)
})

@chingor13
Copy link
Contributor

The sample was updated in #1218 to no longer use .origin(). Using the full URL for the audience works on both GCF and Cloud Run.

@guibirow
Copy link

I have opened another issue to cover this, because this is a common issue created by the documentation asking people to use the serverless example provided in this repo.

If the example is called serverless, it should provide examples for cloud run and cloud functions explicitly, otherwise people will have this problem, that quite frankly, is too often.

Also, another issue people confuses, is that the audience should be the url (like mentioned by VeryCrazyDong) but it is not quite right.
The audience need to match the trigger in the cloud functions, in some cases people uses query strings or subpaths to represent REST operations, and using the url will also cause authentication issues.

Audience Examples:
valid: https://GCP_REGION-TARGET_PROJECT_ID.cloudfunctions.net/FUNCTION_NAME
invalid: https://GCP_REGION-TARGET_PROJECT_ID.cloudfunctions.net/FUNCTION_NAME?query=string
invalid: https://GCP_REGION-TARGET_PROJECT_ID.cloudfunctions.net/FUNCTION_NAME/resource/id

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
priority: p2 Moderately-important priority. Fix may not be included in next release. samples Issues that are directly related to samples. type: bug Error or flaw in code with unintended results or allowing sub-optimal usage patterns.
Projects
None yet
Development

No branches or pull requests

4 participants