Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

storage/file#getSignedUrl example for uploading to signed URL fails #1312

Closed
aknuds1 opened this issue May 13, 2016 · 8 comments
Closed

storage/file#getSignedUrl example for uploading to signed URL fails #1312

aknuds1 opened this issue May 13, 2016 · 8 comments
Assignees
Labels
api: storage Issues related to the Cloud Storage API. type: bug Error or flaw in code with unintended results or allowing sub-optimal usage patterns.

Comments

@aknuds1
Copy link
Contributor

aknuds1 commented May 13, 2016

I cannot upload to signed URLs generated by storage/file#getSignedUrl. I've even tried implementing the official example from the documentation and it fails:

let bucket = gcs.bucket('aBucket')
let cloudFile = bucket.file('aFile')
cloudFile.getSignedUrl({
  action: 'write',
  expires: `03-17-2025`,
}, (error, signedUrl) => {
  if (error == null) {
    // The file is now available to be written to.
    let request = require('request')
    var writeStream = request.post(signedUrl);
    writeStream.end('New data');
    writeStream.on('complete', function(resp) {
      if (resp.statusCode !== 200) {
        console.log('Writing to file failed:', resp.statusCode)
      } else {
        // Confirm the new content was saved.
        cloudFile.download(function(err, fileContents) {
          if (err != null) {
            console.log(`Download failed:`, err.message)
          } else {
            console.log('Contents:', fileContents.toString());
          }
        });
      }
    });
  }
})

The status code from POSTing to the file is 400, with the message <?xml version='1.0' encoding='UTF-8'?><Error><Code>InvalidPolicyDocument</Code><Message>The content of the form does not meet the conditions specified in the policy document.</Message><Details>Missing policy</Details></Error>%.

@stephenplusplus stephenplusplus added api: storage Issues related to the Cloud Storage API. type: bug Error or flaw in code with unintended results or allowing sub-optimal usage patterns. docs labels May 13, 2016
@stephenplusplus
Copy link
Contributor

Bug caught, PR sent: #1313! When action is write, we generate a signed url expecting a PUT request.

Note: The HTTP verb POST is not supported in signed URL strings, except as noted above. You can use POST to define signed policy documents, which specify the characteristics of objects that can be uploaded to a bucket. Learn more in the POST Object documentation

@aknuds1
Copy link
Contributor Author

aknuds1 commented May 13, 2016

Thanks @stephenplusplus! PUT doesn't quite work for me either, although it fails in a different way. If I try curl -X put -d "{}" $SIGNED_URL it fails like this:

<?xml version='1.0' encoding='UTF-8'?><Error><Code>AccessDenied</Code><Message>Access denied.</Message><Details>Anonymous callers do not have storage.objects.create access to bucket arve.muzhack.com.</Details></Error>

If I try to PUT via XMLHttpRequest, it fails differently:

let request = new XMLHttpRequest()
request.onreadystatechange = () => {
  if (request.readyState === XMLHttpRequest.DONE) {
    if (request.status === 200) {
      console.log('Uploaded successfully')
    } else {
      console.log(`Upload was not successful: ${request.status}`)
    }
  }
}

request.open('PUT', signedUrl, true)
request.send(file)

Resulting in the following response:

<?xml version='1.0' encoding='UTF-8'?><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>PUT

image/png
1463260982
/arve.muzhack.com/u%2Faknudsen%2Ftest%2Fpictures%2FIMG_20160511_132145.jpg</StringToSign></Error>

It would be great if you could help me figure out what goes wrong here.

@aknuds1
Copy link
Contributor Author

aknuds1 commented May 13, 2016

I figured out that the reason that XMLHttpRequest fails is that it sends a content-type header, f.ex. image/png, which the call to getSignedUrl fails to match by default. I worked around it by sending a fixed value for content-type, which I also configured getSignedUrl with.

@aknuds1
Copy link
Contributor Author

aknuds1 commented May 13, 2016

@stephenplusplus I have another question though. How do I ensure that a file created through uploading via a signed URL is publicly readable? See my Stack Overflow question on this.

@stephenplusplus
Copy link
Contributor

@aknuds1
Copy link
Contributor Author

aknuds1 commented May 13, 2016

@stephenplusplus How do I set extensionHeaders properly? I've tried, but the signature verification fails.

@aknuds1
Copy link
Contributor Author

aknuds1 commented May 13, 2016

@stephenplusplus I think there is a bug when supplying extensionHeaders actually. You have to add a newline at the end for it to work, due to the implementation of getSignedUrl:

var sign = crypto.createSign('RSA-SHA256');
sign.update([
  options.action,
  (options.contentMd5 || ''),
  (options.contentType || ''),
  expiresInSeconds,
  (options.extensionHeaders || '') + options.resource
].join('\n'));
var signature = sign.sign(credentials.private_key, 'base64');

You'll see that options.extensionHeaders is prepended to options.resource. I don't see any good reason for this, and it means in practice a newline has to be appended to extensionHeaders in order to match the incoming request.

@aknuds1
Copy link
Contributor Author

aknuds1 commented May 14, 2016

@stephenplusplus I created an issue on the matter, with accompanying PR.

sofisl pushed a commit that referenced this issue Sep 27, 2022
Source-Link: googleapis/synthtool@8d2c953
Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-nodejs:latest@sha256:5ed10ba99cd1ea8c3a0f29b4c53e8a2723a101952705baed6b61783111c64c1c
Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api: storage Issues related to the Cloud Storage API. type: bug Error or flaw in code with unintended results or allowing sub-optimal usage patterns.
Projects
None yet
Development

No branches or pull requests

3 participants