187

I'm trying to download files from Firebase Storage through a XMLHttpRequest, but Access-Control-Allow-Origin is not set on the resource, so it's not possible. Is there any way to set this header on the storage server?

  (let [xhr (js/XMLHttpRequest.)]
    (.open xhr "GET" url)
    (aset xhr "responseType" "arraybuffer")
    (aset xhr "onload" #(js/console.log "bin" (.-response xhr)))
    (.send xhr)))

Chrome error message:

XMLHttpRequest cannot load https://firebasestorage.googleapis.com/[EDITED] No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3449' is therefore not allowed access.

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
Blacksad
  • 14,906
  • 15
  • 70
  • 81
  • 5
    Not enough rep for a comment, but the above way is still the right way. Just wanted to share the official firebase docs on this one: https://firebase.google.com/docs/storage/web/download-files#cors_configuration – Andrew McOlash May 15 '17 at 22:17
  • youtube.com/watch?v=tvCIEsk4Uas&t=34s An explanation video – Anupam Agnihotri Feb 24 '23 at 04:14

5 Answers5

314

From this post on the firebase-talk group/list:

The easiest way to configure your data for CORS is with the gsutil command line tool. The installation instructions for gsutil are available at https://cloud.google.com/storage/docs/gsutil_install. Once you've installed gsutil and authenticated with it, you can use it to configure CORS.

For example, if you just want to allow object downloads from your custom domain, put this data in a file named cors.json (replacing "https://example.com" with your domain):

[
  {
    "origin": ["https://example.com"],
    "method": ["GET"],
    "maxAgeSeconds": 3600
  }
]

Then, run this command (replacing "exampleproject.appspot.com" with the name of your bucket):

gsutil cors set cors.json gs://exampleproject.appspot.com

and you should be set.

If you need a more complicated CORS configuration, check out the docs at https://cloud.google.com/storage/docs/cross-origin#Configuring-CORS-on-a-Bucket.

The above is now also included in the Firebase documentation on CORS Configuration

undefined
  • 6,208
  • 3
  • 49
  • 59
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • 10
    Is there a way to allow all origins similar to Access-Control-Allow-Origin: * ? – dooderson Nov 17 '16 at 22:06
  • 8
    How can I find the exact name of my firebase bucket? – Jim Dec 21 '16 at 17:39
  • Where can I find the cors.json? – isuru Jan 04 '17 at 12:04
  • 17
    @user1311069 just use `"origin": ["*"],` instead of `"origin": ["https://example.com"],` – rigdonmr Jan 29 '17 at 19:40
  • 1
    also, is there a way to remove this cors.json if I wanted to? – rigdonmr Jan 29 '17 at 19:41
  • For some reason I am getting an error: AccessDeniedException: 403 Caller does not have storage.buckets.get access to bucket and I am logged with the right user using firebase login. Any help, please? – Eusthace Apr 05 '17 at 22:26
  • 3
    @isuru you should create a file localy named *cors.json* then run the command `gsutil cors set cors.json gs://exampleproject.appspot.com`. – bodruk May 23 '17 at 01:13
  • 28
    Firebase really needs to figure out a user friendly way to do this. Setting permissions on an actual Firebase database is not nearly this frustrating nor is setting S3 bucket permissions. Strong preference for S3 at this point in time. – Matt Jensen Jul 27 '17 at 16:16
  • 2
    I agree with @MattJensen Firebase should allow configuration of cors through the console. Another paint point is configuring file versioning which also requires the use of `gsutil`. – Pier Aug 28 '17 at 14:59
  • 2
    I tried this solution but I'm not getting the file that's supposedly going to be downloaded. – Mikebarson Sep 04 '17 at 01:56
  • 64
    If you don't want to install the util, a handy way is to go to https://console.cloud.google.com/home and click “Activate Google Cloud Shell” in the top right. This will open a shell with gsutil already installed, and with access to your firebase storage projects. (in the shell i used pico to create a json, then did the `gsutil cors set myjson.json gs://projectname.appspot.com` as mentioned above) – Eindbaas Dec 12 '17 at 14:59
  • 1
    @Eindbaas Where did you put your json file? – stallingOne Jan 22 '19 at 10:56
  • 2
    How to configure it for localhost ? – Emeric Apr 29 '19 at 20:37
  • https://cloud.google.com/storage/docs/configuring-cors#gsutil – Lekens May 17 '20 at 00:19
  • 3
    For localhost, include "http://locahost:port" in the list of origin e.g ["http://sitename.com", "http://localhost:4200"] – Lekens May 17 '20 at 00:21
  • @Frenk Van Puffelen yet another of your answer saved me. Thank you for being around helping out since a very long time. – Vincenzo Jul 14 '20 at 17:37
  • 1
    Where do i need to add the JSON file, to the bucket itself? – Rob Terrell Dec 18 '20 at 15:43
  • @Jim In your Firebase Console, go to Storage (on the left side panel), and on the first tab (Files) you will see the exact name of your bucket: `gs://YOUR_PROJECT_ID.appspot.com` – maganap Nov 02 '21 at 11:02
  • worked perfectly and nice to know about the Cloud Shell from @Eindbaas – conor909 Oct 28 '22 at 13:31
  • https://www.youtube.com/watch?v=tvCIEsk4Uas&t=34s An explanation video. – Anupam Agnihotri Feb 24 '23 at 04:14
252

Google Cloud now has an inline editor to make this process even easier. No need to install anything on your local system.

  1. Open the GCP console and start a cloud terminal session by clicking the >_ icon button in the top navbar. Or search for "cloud shell editor" in the search bar.
  2. Click the pencil icon to open the editor, then create the cors.json file.
  3. Run gsutil cors set cors.json gs://your-bucket

enter image description here

WSBT
  • 33,033
  • 18
  • 128
  • 133
JeffD23
  • 8,318
  • 2
  • 32
  • 41
  • Stuck at step 1. Please explain "and start a cloud terminal session" I open the console and see no button, or link to "start a cloud terminal session" – fortesl Nov 03 '19 at 12:35
  • 10
    It's the icon in the top right nav that looks like `>_` – JeffD23 Nov 03 '19 at 16:50
  • 1
    Is there a straight forward way to pull the existing cors config first for reversion if necessary? – David Oct 26 '20 at 20:25
  • 3
    Did the trick! thank you. I must say, this could be so much simpler if it was controlled from firebase storage itself, under rules perhaps?! #google #firebase there's an opportunity here to enhance user experience. – Rodrigo Rubio Nov 27 '20 at 12:48
  • I think they intend firebase anonymous sign-in to be how you can ensure that there is a firebase initialized with your project from your domain. @RodrigoRubio Match the request.auth.uid with resource.data.authorId, resource.data.members, etc. (or control calls in client code to non-anonymous uid's), and sign-in every user anonymously, at first. `getUserInfo = async (users) => {firebase.auth().onAuthStateChanged((meAuth) => {if (meAuth) {if (!meAuth.isAnonymous) {//good} else {//anon}} else {firebase.auth().signInAnonymously().then(() => {//no user}).catch((error) => {})})}` – Nick Carducci for Carface Bank Nov 27 '20 at 14:45
  • 1
    @NickCarducci you might be right and i really like the anonymous facility, though it worries that it has a hard limit of 10 million from memory. This could be dangerous when you have a web app for a TV campaign for example where no one is expected to sign in or register. – Rodrigo Rubio Nov 27 '20 at 14:51
  • @RodrigoRubio I am going to call getUserInfo whenever my threadVideos array is longer than 0 upon user-click of a button called _View Media_, that is where I populate my auth prop - where initially it is null. this way `firebase.auth()` isn't ran every time the website is loaded! *facepalm – Nick Carducci for Carface Bank Nov 28 '20 at 16:28
  • This is how you answer a question! Straight to the point. Worked perfectly. – Mulhoon Feb 11 '21 at 12:37
  • 4
    Is there any wait time required? I set origin to "*" and it still complained Access to fetch at 'https://firebasestorage.googleapis.com/...' from origin 'https://....stackblitz.io' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' – Weilies Jun 09 '21 at 16:19
  • @Weilies I am also facing the same issue, does it require any time waiting? – Zujaj Misbah Khan Dec 30 '21 at 16:04
  • The trick worked, thanks for the simple & crisp solution. – Gulshan Aggarwal Jun 17 '22 at 06:57
  • you are the dude from youtube right. – Richardson Apr 28 '23 at 22:09
22

Just want to add to the answer. Just go to your project in google console (console.cloud.google.com/home) and select your project. There open the terminal and just create the cors.json file (touch cors.json) and then follow the answer and edit this file (vim cors.json) as suggested by @frank-van-puffelen

This worked for me. Cheers!

Aakash
  • 1,455
  • 13
  • 16
  • 1
    The web console at console.cloud.google.com/home was giving me an error, but worked fine with the Google Cloud SDK Shell. – FiringBlanks Apr 13 '19 at 20:17
  • 4
    ... There open the terminal and ... How do you open the terminal? I see no "Open terminal" button on link – fortesl Nov 03 '19 at 12:38
  • 2
    Make sure you're on the `cloud` subdomain, not the `firebase` one ("console.cloud.google.com/home") and look for the `>_` icon button in the top right. – Chris Villa Jun 18 '20 at 09:45
8

I am working on a project using firebase storage and the end-user needs a way to download the file they uploaded. I was getting a cors error when the user tried to download the file but after some research, I solved the issue. Here is how I figured it out:

  1. Download Google Cloud CLI
  2. Log in using the CLI
  3. Create cors.json file in the project directory and type the code below.
[
  {
    "origin": ["*"],
    "method": ["GET"],
    "maxAgeSeconds": 3600
  }
]
  1. Navigate to the directory containing cors.json with the Google Cloud CLI
  2. In the CLI type: gsutil cors set cors.json gs://<app_name>.appspot.com
Alex Joslin
  • 131
  • 2
  • 5
2

another approach to do this is using Google JSON API. step 1 : get access token to use with JSON API To get a token use go to : https://developers.google.com/oauthplayground/ Then search for JSON API or Storage Select required options i.e read ,write , full_access (tick those which are required) Follow the process to get Access Token, which will be valid for an hour. Step 2: Use token to hit google JSON API to update CORS

Sample Curl :

    curl -X PATCH \
  'https://www.googleapis.com/storage/v1/b/your_bucket_id?fields=cors' \
  -H 'Accept: application/json' \
  -H 'Accept-Encoding: gzip, deflate' \
  -H 'Authorization: Bearer ya29.GltIB3rTqQ2tJgh0cMj1SEa1UgQNJnTMXUjMlMIRGG-mBCbiUO0wqdDuEpnPD6cbkcr1CuLItuhaNCTJYhv2ZKjK7yqyIHNgkCBup-T8Z1B1RiBrCgcgliHOGFDz' \
  -H 'Content-Type: application/json' \
  -H 'Postman-Token: d19f29ed-2e80-4c34-85ee-c46c9058fac0' \
  -H 'cache-control: no-cache' \
  -d '{
  "location": "us",
  "storageClass": "Standard",
  "cors": [
      {
          "maxAgeSeconds": "360000000",
          "method": [
             "GET",
             "HEAD",
             "DELETE"
          ],
          "origin": [
             "*"
          ],
          "responseHeader":[
            "Content-Type"
         ]
      }
  ]
}'
nimesh makwana
  • 121
  • 1
  • 4