7

i am trying to upload images into buckets on Google Cloud Storage using the JSON API, using the Javascript sample: Api Javascript Sample

I am able to upload pictures but it asks me to log in on my google account.

Tthe sample has an Authorization button, which I understand manages the OAuth credentials.

    function checkAuth() {
  gapi.auth.authorize({
    client_id: clientId,
    scope: scopes,
    immediate: true
  }, handleAuthResult);
}

The problem is:

I want to authenticate without having the pop up screen, that means without login in with Google. Because my client doesn't know the email or password, I want it to be automatically.

How can I achieve this?

Thanks!

-----------------------------UPDATE--------------------

So following Brandon's answer i have done the following:

I have created my policy document and signed it like this:

var http = require('http');
var fs = require('fs');
var crypto = require('crypto');
var express = require('express');
var app = express();
var p12ToPem = require("./node_modules/p12-to-pem/p12ToPem.js");
var p12File = fs.readFileSync("./KEY.p12");
var pemKey = p12ToPem(p12File, "notasecret");
 var policyJson={"expiration": "2050-06-16T11:11:11Z",
"conditions": [["starts-with", "$key", "" ],
{"acl": "bucket-owner-read" },
{"bucket": "my-bucket'name"},
{"success_action_redirect":"http://www.example.com/success_notification.html" },
 ["eq", "$Content-Type", "image/jpeg" ],
 ["content-length-range", 0, 1000000]
 ]
};
var policyJson64 = new Buffer(''+policyJson).toString('base64');
var sign = crypto.createSign('RSA-SHA256');
sign.update(policyJson64);
var sig = sign.sign(pemKey, 'base64')
console.log("policyJson64:"+policyJson64);
console.log("sig:"+sig);

And my post form is the following:

  <form action="http://my-bucket-name.storage.googleapis.com" method="post" enctype="multipart/form-data">
<input type="text" name="key" value="">
<input type="hidden" name="bucket" value="my-bucket-name">
<input type="hidden" name="Content-Type" value="image/jpeg">
<input type="hidden" name="GoogleAccessId" value="884257827820-so77htet9tafrcjjp83m7api9lh12qsn@developer.gserviceaccount.com">
<input type="hidden" name="acl" value="bucket-owner-read">
<input type="hidden" name="success_action_redirect" value="http://www.example.com/success_notification.html">
<input type="hidden" name="policy" value="DONT KNOW WHAT TO PUT HERE">
<input type="hidden" name="signature" value="NEITHER HERE">
<input name="file" type="file">
<input type="submit" value="Upload">

No matter the combinations obtained in the javascrypt I cant seem to figure out what goes into policy and what into signature,and YES! I have read the API but it is not clear on what goes in those 2 inputs.. I have tried putting on the policy input the value of PolicyJson64 and sig as well. And I have tried putting on the signature input the value of sig and pemKey too.

I get this error:

<Error>
<Code>SignatureDoesNotMatch</Code>
<Message>
The request signature we calculated does not match the signature you provided. Check your Google secret key and signing method.
</Message>
<StringToSign>
a/vDHoeJ1jIZibjgLnS/ZfMftmyz8IaISJiVt1b2wDNbDjnSR+0HyEDW9/Lew7ufMjU9xdtX/Uld06IJbeYz3OWGHnH4osJNS614RoDVd7lq2qft+bSCqYPtkagJiUWs9SNOPvuQzISthqloPQOwJ1LLXHYmV52c73OpexAnSR4=
</StringToSign>
</Error>

What should I put?

------UPDATE------

Please do not copy paste documentation that is not helping. Bounty Added

chelo_c
  • 1,739
  • 3
  • 21
  • 34

2 Answers2

0

Uploading an object requires some form of authorization (you could also create a bucket that allowed truly anonymous writes, but that's seldom a good idea). There are a few ways to acquire authorization.

One way, as you found, is to have a user sign in to their Google account and use that as authorization. That's a good option if the app is for a small number of known individuals.

Another way to upload images is to use signed URL or signed form policy documents. This allows your users to use a standard HTML form to select and upload an image that has been pre-authorized by your app. The policy document is a small bit of text that describes what the user is allowed to do and has been signed by the appropriate credentials.

Here's an example of a policy document:

{"expiration": "2010-06-16T11:11:11Z",
 "conditions": [
    ["starts-with", "$key", "" ],
    {"acl": "bucket-owner-read" },
    {"bucket": "travel-maps"},
    {"success_action_redirect": "http://www.example.com/success_notification.html" },
    ["eq", "$Content-Type", "image/jpeg" ],
    ["content-length-range", 0, 1000000]
  ]
}

This document specifies that users can only use it to upload objects with the bucket-owner-read ACL, only for uploads to the bucket "travel-maps", may only upload objects up to 1 megabyte in size, and so on. The server would then sign this document using their secret key. The document (in base 64) and its signature would then be included in the HTML form, like so:

<form action="http://travel-maps.storage.googleapis.com" method="post" enctype="multipart/form-data">
  <input type="text" name="key" value="">
  <input type="hidden" name="bucket" value="travel-maps">
  <input type="hidden" name="Content-Type" value="image/jpeg">
  <input type="hidden" name="GoogleAccessId" value="1234567890123@developer.gserviceaccount.com">
  <input type="hidden" name="acl" value="bucket-owner-read">
  <input type="hidden" name="success_action_redirect" value="http://www.example.com/success_notification.html">
  <input type="hidden" name="policy" value="eyJleHBpcmF0aW9uIjogIjIwMTAtMDYtMTZUMTE6MTE6MTFaIiwNCiAiY29uZGl0aW9ucyI6IFsNCiAgWyJzdGFydHMtd2l0aCIsICJrZXkiLCAiIiBdLA0KICB7ImFjbCI6ICJidWNrZXQtb3duZXItcmVhZCIgfSwNCiAgeyJidWNrZXQiOiAidHJhdmVsLW1hcHMifSwNCiAgeyJzdWNjZXNzX2FjdGlvbl9yZWRpcmVjdCI6ICJodHRwOi8vd3d3LmV4YW1wbGUuY29tL3N1Y2Nlc3Nfbm90aWZpY2F0aW9uLmh0bWwiIH0sDQogIFsiZXEiLCAiQ29udGVudC1UeXBlIiwgImltYWdlL2pwZWciIF0sDQogIFsiY29udGVudC1sZW5ndGgtcmFuZ2UiLCAwLCAxMDAwMDAwXQ0KICBdDQp9">
  <input type="hidden" name="signature" value="BSAMPLEaASAMPLE6SAMPLE+SAMPPLEqSAMPLEPSAMPLE+SAMPLEgSAMPLEzCPlgWREeF7oPGowkeKk7J4WApzkzxERdOQmAdrvshKSzUHg8Jqp1lw9tbiJfE2ExdOOIoJVmGLoDeAGnfzCd4fTsWcLbal9sFpqXsQI8IQi1493mw=">
  <input name="file" type="file">
  <input type="submit" value="Upload">
</form>

There's a lot more documentation on how this works here:

https://cloud.google.com/storage/docs/reference-methods#policydocument

Keep in mind that a signed URL is different than a signed form. "Signed URLs" are very specific, arbitrary commands that can be executed exactly as stated. You could use them for uploads, but they're less versatile than signed policy documents.

Brandon Yarbrough
  • 37,021
  • 23
  • 116
  • 145
  • How did you manage to do this step: Sign your policy document using RSA with SHA-256 using the secret key provided to you in the Google Developers Console. ???? What libraries did you use, im using JavaScrypt. @Brandon Yarbrough – chelo_c Mar 31 '15 at 09:11
  • cant find the way to do it in JavaScrypt – chelo_c Mar 31 '15 at 19:08
  • Are your HTML/Javascript files statically hosted, or do you have a web server component running in some language? – Brandon Yarbrough Mar 31 '15 at 19:56
  • im using node js server – chelo_c Mar 31 '15 at 20:03
  • Ah, great. node.js has a few crypto libraries. There's an example in this question: http://stackoverflow.com/questions/12683189/how-to-use-nodejs-crypto-to-sign-a-file – Brandon Yarbrough Mar 31 '15 at 20:35
-4

As Google Cloud Storage doesnt have a simple way to upload an image (2014), I ended up using Amazon Web Services which even comes with a NodeJS Sample Code. Easy and simple to use.

http://aws.amazon.com/es/developers/getting-started/nodejs/

Clone the sample:

git clone https://github.com/awslabs/aws-nodejs-sample.git

Install:

npm install

Run:

node sample.js

The Sample comes with bucket usage and they even store a file in the bucket. So that will make it. Make sure to change your credentials:

aws_access_key_id = YOUR_ACCESS_KEY_ID
aws_secret_access_key = YOUR_SECRET_ACCESS_KEY

Cheers!

chelo_c
  • 1,739
  • 3
  • 21
  • 34