0
votes

I have a scenario where I need to do a secure request a Firebase Cloud Function from an external server using a HTTP request. In order to request it I need to send a bearer JWT token on the authorization header. After sometime looking at the Google documents to Firebase/GCP I've found many different ways to authenticate using google different APIs, but I'm kinda lost on it.

I know that I need to use a service account in order to identify the machine that is calling instead a common human-user credentials. I also know that the service account provides a JSON file that contains secure information to identify that service account, like the private key. By looking different docs I found this one that explains how to generate and request a token. After following those steps, I'm facing a 403 status when I try to call the cloud function using the resulting token.

I doubled checked the roles my service account has and I do have the ones the docs have pointed me.

Does anyone knows or have any suggestions how to proceed to have cloud function authorized calls by a machine (not human) interaction.

Edit 1:

As requested here I'm posting my JWT generator code:

const {
  private_key_id,
  private_key,
  client_email,
} = require('./serviceAccount.json');

const jwt = require('jsonwebtoken');

const payload = {
  "kid": private_key_id,
  "iss": client_email,
  "sub": client_email,
  "iat": 1611257400,
  "exp": 1611260940,
  "aud": "https://oauth2.googleapis.com/token",
  "target_audience": "https://<project- region>.cloudfunctions.net/helloWorld"
};

const token = jwt.sign(payload, private_key, { algorithm: 'RS256', header: {"alg":"RS256","typ":"JWT"} });

console.log(token);

With the result token from above I'm sending a POST request to https://oauth2.googleapis.com/token where the token is sent as the assertion field on a form data.

After suggestions here I did some research and found this blog with instructions to generate a Identity token using my service account. So I ran:

# Load the service account identity
gcloud auth activate-service-account --key-file=key.json
# Generate an id token
gcloud auth print-identity-token

The resulting token gave me the same result a 403 - Forbidden error. The interesting part is that using my user credentials and using gcloud to generate an identity token I was able to request the Cloud function with a 200 result.

I'm thinking that I'm missing some sort of role/privilege/scope on my service account configuration.

1
Google OAuth (both user and service accounts) can generate three types of tokens. Access, Identity and Refresh. You are probably generating the first one: Access Token. Google services such as Functions use Identity Tokens to authenticate clients. Which one are you using in your HTTP request header for Authorization: Bearer <TOKEN>? - John Hanley
Agree with John, you should use the wrong one. Can you share your code to help you more? - guillaume blaquiere
Thanks for the responses. I updated the question with new information. - Wesley Fuchter
What are the specific roles and scopes assigned to your service account? Does it have at least the cloudfunctions.functions.invoke permissions assigned? - Daniel Ocando
Thank you all. I was able to solve the problem after adding the cloudfunctions.functions.invoke to the service account. - Wesley Fuchter

1 Answers

0
votes

Make sure that the service account has assigned the cloudfunctions.functions.invoke in order to guarantee that the Cloud Function can be triggered from an external server using an HTTP request.