Get hands-on experience with 20+ free Google Cloud products and $300 in free credit for new customers.

Connect my frontend to cloud run

I have a React web application hosted on Firebase hosting that utilizes a Python API hosted on Cloud Run. Currently, the API is public, and I would like to restrict access to it so that only calls made from my React application can access it.

I believe the solution involves configuring the networking and security settings in Cloud Run, but as a novice, I am not quite sure how to proceed.

Could someone provide me with a reliable source to learn more about this topic or help me find a solution to this problem?

Thank you and have a great day.

Solved Solved
0 14 4,861
1 ACCEPTED SOLUTION

1) Deploy your Cloud Run service as a private service. As Google documentation says

Private services cannot be directly loaded by a web browser. Instead, use curl or a similar HTTP request CLI tool that allows injecting an Authorization header.

This means the url can't be accessed directly e.g. by typing it in a browser. We have a blog article with step by step instruction for deploying your Cloud Run service as private.

 

2) Now that your Cloud Run service is restricted, you basically need to get an ID token and add it when you're making the call to the Cloud Run service (this means you add it to your code for the React Web application for when it invokes the Cloud Run url).
    - See this example from Google.
    - Also see this documentation from Google which explains service-to-service authentication which is what your Firebase App will be doing to the Cloud Run url.

..... NoCommandLine ......
 https://nocommandline.com
A GUI for Google App Engine

View solution in original post

14 REPLIES 14

We have a guide on private networking on Cloud Run. Please let us know if you have any questions - https://cloud.google.com/run/docs/securing/private-networking

The problem is that firebase hosting does not support VPC. It is therefore impossible to create a VPC between firebase hosting and cloud run.

1) Deploy your Cloud Run service as a private service. As Google documentation says

Private services cannot be directly loaded by a web browser. Instead, use curl or a similar HTTP request CLI tool that allows injecting an Authorization header.

This means the url can't be accessed directly e.g. by typing it in a browser. We have a blog article with step by step instruction for deploying your Cloud Run service as private.

 

2) Now that your Cloud Run service is restricted, you basically need to get an ID token and add it when you're making the call to the Cloud Run service (this means you add it to your code for the React Web application for when it invokes the Cloud Run url).
    - See this example from Google.
    - Also see this documentation from Google which explains service-to-service authentication which is what your Firebase App will be doing to the Cloud Run url.

..... NoCommandLine ......
 https://nocommandline.com
A GUI for Google App Engine

Hi there!
Thanks for your reply, I did indeed do it that way.
I allowed my firebase service account to access cloud run. I then retrieve the tokenID with the following code :

 

async function getIdTokenFromMetadataServer() {
  const googleAuth = new GoogleAuth({
    keyFilename: './compte.json'
  });
  const client = await googleAuth.getClient();

  // Get the ID token.
  // Once you've obtained the ID token, you can use it to make an authenticated call
  // to the target audience.
  let Token = await client.fetchIdToken(url);
  console.log(Token);
  const response = await axios.get(url, {
    headers: {
      'Authorization': `Bearer ${Token}`
    }
  });
  console.log(response);
}

getIdTokenFromMetadataServer();

There is still a security flaw. I need to have the JSON file containing the private key for the firebase service account on the client side.
Do you have any idea how to fix this?

Hi,

If you're running this on Google's servers, I don't believe you need to specify a JSON file containing the key. The system will automatically pick up the 'default' service account (if you look at the example I linked to in my response, there's no service account).

 

..... NoCommandLine ......
 https://nocommandline.com
A GUI for Google App Engine

 

Okk I get it, thanks for your reply and for the time you took.

I'll get back to you once I've managed to deploy the code on firebase hosting. I have one last error with the following line of code: sded

This line creates a large number of errors in my react code and I don't know why. However, with node locally it works very well.

const { GoogleAuth } from 'google-auth-library'; *

I'm not a React person but the above code looks incorrect to me. I think it should be 

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

or

import { GoogleAuth } from 'google-auth-library';

 

..... NoCommandLine ......
 https://nocommandline.com
A GUI for Google App Engine

Former Community Member
Not applicable

@NoCommandLine  You still need to change the ingress setting on cloud run to "allow and internal and LB" or does it really not matter?

No. You don't have to do anything like that. A Cloud Run service that is deployed as Private is automatically not available when you type its url in a browser. You should also take a look at this response

..... NoCommandLine ......
 https://nocommandline.com
A GUI for Google App Engine

Former Community Member
Not applicable

Okay. So in this case "private access" is achieved by enforcing the calling service to generate a access token to be able to call the CR service?

I don't understand your question. Have you taken a look at the linked posts/articles?

My previous response to you includes working code (deploying a cloud run service as private and confirming it isn't accessible when you type the url in a browser. In fact, in Google cloud console, you'll see the entry 'Require authentication' for the deployed service)

 



..... NoCommandLine ......
 https://nocommandline.com
A GUI for Google App Engine

Former Community Member
Not applicable

Yes i have taken a look at the post. What i understand there are several ways to enforce private access one of them is via code using a access token to invoke the service but there is also a ingress setting that can be used (this is an infra side change) by setting to "internal" only but beyond that it is not clear.

Hi@NoCommandLine, I have an Frontend Standard App Engine service which needs to be connected to  backend Cloud Run service through the Serverless VPC connector.  The Cloud Run was able to connect Serverless VPC connector as its direct in UI whereas my App Engine was not able to. I have added the vpc_connector attribute to app.yaml file and using the default Service Account which has Editor role (has excess permissions) and also added " Serverless VPC Access User and Compute Viewer " permissions for my App Engine service account but during the deployment it shows "compute.globalOperations.get" and "vpcaccess.connectors.use" permissions error.