0
votes

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.

So far I have tried creating an access token on the server using the service account credentials like so:

    credential = GoogleCredential.fromStream(this.getClass().getResourceAsStream("/serviceaccount.json"));
    LinkedList<String> list = new LinkedList<String>();
    list.add("https://www.googleapis.com/auth/devstorage.read_only");
    credential = credential.createScoped(list);
    credential.refreshToken();

Then I passed the "access_token" returned form credential.getAccessToken() to the client and used it in XmlHttpRequest like so:

    var xhr = new XMLHttpRequest();
    xhr.open('GET', "https://storage.googleapis.com/....." true);
    xhr.responseType = 'arraybuffer';
    xhr.setRequestHeader('Authorization', 'Bearer ' + access_token);

This causes chrome to produce the following error.

"Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource."

Cors on the bucket is

[{"maxAgeSeconds": 3600, "method": ["GET", "HEAD", "DELETE"], "origin": ["http://www.voxxlr.com"], "responseHeader": ["O rigin", "Content-Type", "Content-Length"]},{"maxAgeSeconds": 3600, "method": ["GET", "HEAD", "DELETE"], "origin": ["http ://voxxlr.com"], "responseHeader": ["Origin", "Content-Type", "Content-Length"]}]

Next I tried to use an API key as follow:

    var xhr = new XMLHttpRequest();
    xhr.open('GET', "https://storage.googleapis.com/....?KEY=...." true);
    xhr.responseType = 'arraybuffer';

That produced the following error:

AccessDenied Anonymous users does not have storage.objects.get access to voxxlr/1511465797269/n.bin.

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.

Any help would be appreciated... This has been eating up a lot of time, but it seems there should be an easy solution.

1

1 Answers

0
votes

API keys are not an authentication mechanism. They provide a mechanism for indicating which project your request is associated with (which is used for a variety of purposes, notably quota and billing for unauthenticated requests), but successfully using one does not associate your request with any specific account or permissions.

Your CORS issue could be a variety of things. I notice there's a space in your specified O rigin header and in http ://voxx. Is that an artifact of copying to SO or is it how the real policy is? Also, origins need to be really specific; are you using HTTPS? If so, you'll need to include it. Also it might be a good idea to include the preflight request itself (OPTIONS) as one of the allowed methods.

Finally, you very likely do not want to be passing an access token to the client. An access token is only good for a few minutes, but it can be used to do anything the creator of the token can do (within its declared scope). That's probably something you really don't want. Signed URLs are a much safer idea.