Reputation: 379
I am creating a signedURL in an app engine endpoint and then serving it to the client. But when the client tries to upload using the signed URL, the cloud storage throws the following error
Access denied. Anonymous users does not have storage.objects.create access to bucket
The app engine code to generate signed URL is as follows:
private String getSignedUrl() {
String encodedUrl = null;
String httpVerb = "PUT";
String contentMD5 = "";
String contentType = "image/rgb";
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.MINUTE, 10);
long expiration = calendar.getTimeInMillis() / 1000L;
String canonicalizedExtensionHeaders = "";
String canonicalizedResource =
"/<bucket_name>/<folder_name>/";
String stringToSign =
httpVerb + "\n" + contentMD5 + "\n" + contentType + "\n"
+ expiration + "\n" + canonicalizedExtensionHeaders
+ canonicalizedResource;
AppIdentityService service =
AppIdentityServiceFactory.getAppIdentityService();
String googleAccessId = service.getServiceAccountName();
String baseURL =
"http://storage.googleapis.com/<bucket_name>/<folder-name>/";
SigningResult signingResult =
service.signForApp(stringToSign.getBytes());
String encodedSignature = null;
try {
encodedSignature =
URLEncoder.encode(
new String(Base64.encodeBase64(
signingResult.getSignature(), false),
"UTF-8"), "UTF-8").toString();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
encodedUrl =
baseURL + "?GoogleAccessId=" + googleAccessId + "&Expires="
+ expiration + "&Signature=" + encodedSignature;
return encodedUrl;
}
And after obtaining the signed URL, I am using cURL to test the upload. I use the following command to upload the file
curl -X PUT -H "Content-Type: multipart/form" -F file=@"<file_path>";type=image/rgb <signed_url>
I have tried both POST and PUT in the cURL with the same result. Am I missing something here?
Upvotes: 1
Views: 2321
Reputation: 455
You also have to URL encode googleAccessId
and encodedSignature
because of the @
sign in the service account email and a base64 encoded string may have the +
character which is decoded as a space by the server.
Upvotes: 1
Reputation: 41089
Writing from memory here, but I think you need to provide the object name. Plus, you included folder name in the baseURL - only bucket name should be included. "folder" name is part of the object name.
Upvotes: 1