0

Summary:

I have deployed a very basic React app packaged as a Cloud Run app. I want to call another Cloud Run app (API) via a service account assigned to the service. I have no issue with this in my Express Node Cloud Run apps. Using the same google-auth-lib and example as below. What am I doing wrong with this React App that dont seem to follow through with calling the other API? (Locally with the SA key.json set it works)

My code:

React class beeing rendered:

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

    class Overview extends Component {

        async componentDidMount(){
            console.log("Trying to auth to google");
            const url = "https://myapp.run.app/";
            const targetAudience = "12345.apps.googleusercontent.com";

            // only for locally accessing the service account
            const options = { 
                credentials: require('../key-credentials.json'),
                projectId: 'myprojectid'
            };
            // In the deployed app the "option" parameter is not included
            const auth = new GoogleAuth(options);
  
            const client = await auth.getIdTokenClient(targetAudience);
            const res = await client.request({url});
            console.info(res.data);
        }
    
        render(){
            return (
                <div>
                    <h1>Overview</h1>
                </div>
            )
        }
    }
    
    export default Overview;

Link to the docs with the google-auth-lib example: https://cloud.google.com/run/docs/authenticating/service-to-service#run-service-to-service-example-nodejs

The Error:

Screenshot over the browser console

GET https://metadata.google.internal./computeMetadata/v1/instance net::ERR_NAME_NOT_RESOLVED

This error I understand as the Cloud Run service trying to find the google cloud meta data which holds the service account that has access to the url trying to be called, but the meta data cant be found.

TypeError: Unexpected error determining execution environment

This I beleve is that because the service account meta data cant be found, the environment can be correct to call the requested service.

Any idea what could be wrong?

Flamingow
  • 11
  • 2

1 Answers1

0

React is a client side framework, which means your code isn't running in Cloud Run. It's running on your user's devices. Your users devices don't have access to generate tokens for your service account. It wouldn't be very secure if every computer in the world could just ask a website for an ID token for your service account.

If you want a service to be reachable from React, you'll need to allow unauthenticated calls. If you want to require your users to log in, you'll need to use something like Identity Platform on your server rather than just relying on Cloud Run's built-in auth. The built-in auth works great for service-to-service calls but doesn't support what you need for client authentication.

Ben K
  • 344
  • 2
  • 5
  • Thank you. The app is deployed and running in Cloud Run (with React and nginx). Locally I added the SA key.json credentials and can access my other services that way without any issues at all. But the actual app deployed in Cloud Run described in this thread cant seem to reach the google meta data. And i don't want to push up the key.json credential file, but instead let the google meta data handle it as i do with other Node Run apps – Flamingow Mar 02 '23 at 10:21
  • Your app is deployed in Cloud Run, but that's not where the React code is being executed. React code is executed on the client device (whatever computer or phone is running the website) regardless of where you deploy it. That device cannot access the metadata server and it's not secure to ship a key.json. – Ben K Mar 02 '23 at 15:58
  • Many thanks, I understand. My plan was to secure it with IAP through a load balancer (only coworker accounts allowed) Do you have any suggestion? Would it be allowing unauthenticated calls for the Run app and using Identity Platform on top of that instead? – Flamingow Mar 02 '23 at 18:04
  • Using IAP is a great idea if only your coworkers need to access it. Identity Platform is for if you want people outside your organization to access it. But like Identity Platform, IAP requires you to set "allow unauthenticated" since you want IAP handling the auth and not Cloud Run. Follow the instructions [here](https://cloud.google.com/iap/docs/enabling-cloud-run) to get it to work. – Ben K Mar 02 '23 at 19:28