title: Accessing objects in google cloud storage bucket via API key
body: <p>I am trying to access content in a google cloud bucket via a Javascript running in a web browser. So far I have created signed urls on the server using the service account credentials and passed them to the client during REST calls. The only reason I am doing this is because I attempted to solve this problem before and then just gave up and opted for signed urls. Now I need to get this to work. </p>
  
  <p>So far I have tried creating an access token on the server using the service account credentials like so:</p>
  
  <pre><code>    credential = GoogleCredential.fromStream(this.getClass().getResourceAsStream("/serviceaccount.json"));
      LinkedList&lt;String&gt; list = new LinkedList&lt;String&gt;();
      list.add("https://www.googleapis.com/auth/devstorage.read_only");
      credential = credential.createScoped(list);
      credential.refreshToken();
  </code></pre>
  
  <p>Then I passed the "access_token" returned form credential.getAccessToken() to the client and used it in XmlHttpRequest like so:</p>
  
  <pre><code>    var xhr = new XMLHttpRequest();
      xhr.open('GET', "https://storage.googleapis.com/....." true);
      xhr.responseType = 'arraybuffer';
      xhr.setRequestHeader('Authorization', 'Bearer ' + access_token);
  </code></pre>
  
  <p>This causes chrome to produce the following error. </p>
  
  <p>"Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource."</p>
  
  <p>Cors on the bucket is </p>
  
  <p>[{"maxAgeSeconds": 3600, "method": ["GET", "HEAD", "DELETE"], "origin": ["<a href="http://www.voxxlr.com" rel="nofollow noreferrer">http://www.voxxlr.com</a>"], "responseHeader": ["O
  rigin", "Content-Type", "Content-Length"]},{"maxAgeSeconds": 3600, "method": ["GET", "HEAD", "DELETE"], "origin": ["http
  ://voxxlr.com"], "responseHeader": ["Origin", "Content-Type", "Content-Length"]}]</p>
  
  <p>Next I tried to use an API key as follow:</p>
  
  <pre><code>    var xhr = new XMLHttpRequest();
      xhr.open('GET', "https://storage.googleapis.com/....?KEY=...." true);
      xhr.responseType = 'arraybuffer';
  </code></pre>
  
  <p>That produced the following error:</p>
  
  <blockquote>
    <p>AccessDenied
    Anonymous users does not have storage.objects.get access to voxxlr/1511465797269/n.bin.</p>
  </blockquote>
  
  <p>Shouldn't the API key provide access just like that? I am not really looking for a solution that includes the google/javascript clients since the only operation required is too read the bucket contents. No admin or delete functions are necessary. I am basically just looking for a solution where all html/javascript from my domain can have read access the buckets. </p>
  
  <p>Any help would be appreciated... This has been eating up a lot of time, but it seems there should be an easy solution. </p>