9
votes

I'm having a CORS related issue with google cloud run on a service that
requires authentication.

If I try to execute a curl command through the cli, with a Bearer token,
everything works fine. Unfortunately if I try to execute the same call through ajax in javascript,
I receive a 403.

  const http = new XMLHttpRequest();
  const url = 'https://my-app.run.app';

  http.open("GET", url);
  http.withCredentials = true;
  http.setRequestHeader("authorization", 'Bearer ' + id_token);
  http.send();
  http.onreadystatechange = (e) => {
    console.log(http.responseText)
  }

The error in the cloud run logs is this :

The request was not authenticated. Either allow unauthenticated invocations or set the proper Authorization header. Read more at https://cloud.google.com/run/docs/securing/authenticating

The container is never hit.

The issue I'm seeing is that, as I'm making the call using ajax, in a web
browser. The web browser is making a pre flight request ( OPTIONS on the
url ) without sending the Authorization header ( which is an expected
behavior )

The problem seems to be that cloud run tries to authenticate the OPTIONS
request and never makes it to my container, which, as far as I understand,
shouldn't be done. (
https://www.w3.org/TR/cors/#cross-origin-request-with-preflight-0 )

Is that a known issue with cloud run ?

How could I make an ajax request to an authenticated cloud run service ?

1

1 Answers

8
votes

(Cloud Run PM)

This is a known issue. There are a few options:

  1. Allow unauthenticated requests and do CORS/auth yourself
    1. There is a variation of this that uses Cloud Endpoints running on Cloud Run in front of your compute. Have Endpoints do your end-user auth, then forward the request to your backend.
  2. Serve from the same domain (e.g. use the Firebase Hosting proxy)

We've considered implementing Istio CORSPolicy, which would return CORS headers before the auth check, though we're not committed to this as of now.