Authenticating Developers, Functions, and End-users

By default, only project owners and editors can create, update or delete functions. To grant other users or groups the ability to perform these actions, you can use Identity and Access Management (IAM) to grant roles to different members.

Similarly, you can grant or restrict the ability to invoke a function. This behavior differs for HTTP functions and background functions:

Three common use cases for authentication include:

  • Securing developer access so that only specific users can invoke the function during testing.

  • Securing function-to-function access so that only authorized functions can invoke your function.

  • Securing end-user access to an application from mobile or web clients.


In addition to administrative actions such as creating, updating, and deleting functions, developers often want to test functions privately before releasing them publicly.

When using curl or similar tools, you must treat these as end-user requests and provide a Google OAuth token in the request's Authorization header. For example, you can get a token via gcloud as follows:

curl \
  -H "Authorization: bearer $(gcloud auth print-identity-token)"

In order for this request to work, the role assigned to the developer must contain the cloudfunctions.functions.invoke permission. By default, the Cloud Functions Admin and Cloud Functions Developer roles have this permission. See Cloud Functions IAM Roles for the full list of roles and their associated permissions.

Finally, we recommend that you allocate the minimum set of permissions required to develop and use your functions. Make sure that IAM policies on your functions are limited to the minimum number of users and service accounts.


When building services that connect multiple functions, it's a good idea to ensure that each function is only able to make requests to certain functions. For instance, if you have a login function, it should be able to access the user profiles function, but it probably shouldn't be able to access the search function.

First, you'll need to configure the receiving function to accept requests from the calling function:

  1. Grant the Cloud Functions Invoker (roles/cloudfunctions.invoker) role to the calling function identity on the receiving function. By default, this identity is


  1. Go to the Google Cloud Console:

    Go to Google Cloud Console

  2. Click the checkbox next to the function whose permissions you want to modify.

  3. Click Show Info Panel in the top right corner to show the Permissions tab, which displays the roles assigned to the function.

  4. In the Add members field, enter the runtime identity of the calling function. This should be a service account email.

  5. Select the role Cloud Functions > Cloud Functions Invoker from the Select a role drop-down menu.

  6. Click Save.


Use the gcloud functions add-iam-policy-binding command:

gcloud functions add-iam-policy-binding RECEIVING_FUNCTION \
  --member='serviceAccount:CALLING_FUNCTION_IDENTITY' \

where RECEIVING_FUNCTION is the receiving function, and CALLING_FUNCTION_IDENTITY is the calling function identity.

In the calling function, you'll need to:

  1. Create a Google-signed OAuth ID token with the audience (aud) set to the URL of the receiving function.

  2. Include the ID token in an Authorization: Bearer ID_TOKEN header in the request to the function.


const fetch = require('node-fetch');

// TODO(developer): set these values
const REGION = 'us-central1';
const PROJECT_ID = 'my-project-id';
const RECEIVING_FUNCTION = 'myFunction';

// Constants for setting up metadata server request
// See
const functionURL = `https://${REGION}-${PROJECT_ID}${RECEIVING_FUNCTION}`;
const metadataServerURL =
const tokenUrl = metadataServerURL + functionURL;

exports.callingFunction = async (req, res) => {
  // Fetch the token
  const tokenResponse = await fetch(tokenUrl, {
    headers: {
      'Metadata-Flavor': 'Google',
  const token = await tokenResponse.text();

  // Provide the token in the request to the receiving function
  try {
    const functionResponse = await fetch(functionURL, {
      headers: {Authorization: `bearer ${token}`},
    res.status(200).send(await functionResponse.text());
  } catch (err) {
    res.status(500).send('An error occurred! See logs for more details.');


import requests

# TODO<developer>: set these values
REGION = 'us-central1'
PROJECT_ID = 'my-project'
RECEIVING_FUNCTION = 'my-function'

# Constants for setting up metadata server request
# See
function_url = f'https://{REGION}-{PROJECT_ID}{RECEIVING_FUNCTION}'
metadata_server_url = \
token_full_url = metadata_server_url + function_url
token_headers = {'Metadata-Flavor': 'Google'}

def calling_function(request):
    # Fetch the token
    token_response = requests.get(token_full_url, headers=token_headers)
    jwt = token_response.text

    # Provide the token in the request to the receiving function
    function_headers = {'Authorization': f'bearer {jwt}'}
    function_response = requests.get(function_url, headers=function_headers)

    return function_response.text


import (


// makeGetRequest makes a request to the provided targetURL with an authenticated client.
func makeGetRequest(w io.Writer, targetURL string) error {
	// functionURL := "https://TARGET_URL"
	ctx := context.Background()

	// client is a http.Client that automatically adds an "Authorization" header
	// to any requests made.
	client, err := idtoken.NewClient(ctx, targetURL)
	if err != nil {
		return fmt.Errorf("idtoken.NewClient: %v", err)

	resp, err := client.Get(targetURL)
	if err != nil {
		return fmt.Errorf("client.Get: %v", err)
	defer resp.Body.Close()
	if _, err := io.Copy(w, resp.Body); err != nil {
		return fmt.Errorf("io.Copy: %v", err)

	return nil


import java.time.Duration;

public class BearerTokenHttp implements HttpFunction {

  // TODO<developer> specify values for these environment variables
  private static String REGION = System.getenv("TARGET_REGION");
  private static String PROJECT_ID = System.getenv("GCP_PROJECT");
  private static String RECEIVING_FUNCTION_NAME = "myFunction";

  private static String receivingFunctionUrl = String.format(
  private static String metadataTokenEndpoint =

  private static HttpClient client =

  public void service(HttpRequest request, HttpResponse response)
      throws IOException, InterruptedException {

    // Set up metadata server request
    // See tokenRequest =
        .uri(URI.create(metadataTokenEndpoint + receivingFunctionUrl))
        .header("Metadata-Flavor", "Google")

    // Fetch the bearer token<String> tokenReponse =
    String token = tokenReponse.body();

    // Pass the token along to receiving function functionRequest =
        .header("Authorization", "Bearer " + token)
        .build();<String> functionResponse =

    // Write the results to the output:
    BufferedWriter writer = response.getWriter();


If you're invoking a function from a compute instance that doesn't have access to compute metadata (e.g. your own server), you'll have to manually generate the proper token:

  1. Self-sign a service account JWT with the target_audience claim set to the URL of the receiving function.

  2. Exchange the self-signed JWT for a Google-signed ID token, which should have the aud claim set to the above URL.

  3. Include the ID token in an Authorization: Bearer ID_TOKEN header in the request to the function.

The Cloud IAP docs have sample code to demonstrate this functionality.


Most applications handle requests from end-users, and it's a best practice to restrict access to only allowed end users. In order to accomplish this, you can integrate Google Sign-In and grant users the Cloud Functions Invoker IAM role (roles/cloudfunctions.invoker), or implement Firebase Authentication and manually validate their credentials.

Google Sign-In

First, you'll need to enable Google Sign-In in your project:

  1. Create an OAuth 2.0 client ID for your app in the same project as the function you want to secure:
    1. Go to the Credentials page.

      Go to the Credentials page

    2. Select the project with the function you want to secure.
    3. Click Create credentials, then select OAuth Client ID.
      1. You may be required to configure your OAuth consent screen before creating a client ID. If necessary, do so in order to continue.
    4. Select the Application type for which you want to create credentials.
    5. Add a Name and Restrictions if appropriate, then click Create.
  2. Re-deploy the function you want to secure. This will ensure that the correct client ID is set on the function.

If you have multiple OAuth client IDs (for example, one each for Android, iOS, and web), you must re-deploy your function(s) after adding each one to ensure the function picks up the change. Similarly, if you delete a client ID, you must re-deploy your function(s) to remove that client ID and deny requests. All client IDs within a project will be accepted.

In your web or mobile app, you'll need to:

  1. Get an ID token for the OAuth client ID:
  2. Include the ID token in an Authorization: Bearer ID_TOKEN header in the request to the function.

Cloud Functions will validate the auth token and allow the request, or reject the request before the function starts up. If a request is rejected, you won't be billed for that request.

Getting user profile information

If you want to access user profile information, you can pull the token out of the Authorization header, decode the JSON Web Token, and extract the body.

The body of the ID token should contain the following information:

 // These six fields are included in all Google ID Tokens.
 "iss": "",
 "sub": "110169484474386276334",
 "azp": "",
 "aud": "",
 "iat": "1433978353",
 "exp": "1433981953",

 // These seven fields are only included when the user has granted the "profile"
 // and "email" OAuth scopes to the application.
 "email": "",
 "email_verified": "true",
 "name" : "Test User",
 "picture": "",
 "given_name": "Test",
 "family_name": "User",
 "locale": "en"

There is no need to validate the token, as the token has already been validated by IAM.


If user requests are being rejected and you believe they should be allowed, ensure that users have been granted the roles/cloudfunctions.invoker role, or have the cloudfunctions.functions.invoke permission. Learn more about these in the Cloud Functions IAM reference.

Web apps, authentication, and CORS

If you want to build a web app that is secured with Google Sign-in and Cloud Functions IAM, you'll likely have to deal with Cross-Origin Resource Sharing (CORS). CORS preflight requests are sent without an Authorization header, so they will be rejected on all non-public HTTP Functions. Because the preflight requests fail, the main request will also fail.

To work around this, you can host your web app and function(s) on the same domain to avoid CORS preflight requests. Otherwise, you should make your functions public and handle CORS and authentication in the function code.

Alternatively, you can deploy a Cloud Endpoints proxy and enable CORS. If you want authentication capabilities, you can also enable Google ID token validation, which will validate these same authentication tokens.

Firebase Authentication

If you want to authenticate users using email/password, phone number, social providers like Facebook or GitHub, or a custom authentication mechanism, you can use Firebase Authentication.

First you'll need to set up Firebase Authentication in your project and function:

  1. Set up Firebase Authentication in the Firebase Console.

    Go to the Firebase Console

  2. Import the appropriate Firebase Admin SDK and configure it properly.

  3. Add middleware to your code to verify Firebase ID tokens.

  4. Deploy your function publicly.

In your web or mobile app, you need to:

  1. Use the appropriate Firebase Auth client library to get an ID token:
  2. Include the ID token in an Authorization: Bearer ID_TOKEN header in the request to the function.

Alternatively, you can deploy a Cloud Endpoints proxy and enable Firebase ID token validation, which will validate these same authentication tokens.

Getting user profile information

If you want to access user profile information, you can use the Firebase Admin SDK to retrieve user data.

API Keys

API keys identify the client application and GCP project calling your API, allowing you to perform simple authorization as well as quota checks and rate limiting.

API keys aren't as secure as the other authentication methods listed here for the following reasons:

  1. API keys are long lived. This means that if one leaks, it can be used indefinitely (or at least until keys are rotated, which requires all clients updating the key).
  2. API keys are often stored client side, making them vulnerable to being re-used by malicious parties.

If you choose to use API keys for quota and rate limiting, we recommend using them together with authentication tokens.

To configure API key access, deploy a Cloud Endpoints proxy and enable configure your securityDefinitions to enable API key validation.

Next steps

Learn how to manage access to the functions you're authenticating to.