1
votes

I am trying to perform a document upload using an S3 pre-signed PUT url. I generated the url using java AWS SDK (GeneratePresignedUrlRequest.java). This url generation code sits in a lambda function behind AWS API gateway.

However I am getting the following error when I copy the generated url in Postman & try to perform an upload.

<Error>
<Code>AccessDenied</Code>
<Message>
There were headers present in the request which were not signed
</Message>
<HeadersNotSigned>host</HeadersNotSigned>
<RequestId>6E624EC66091A099</RequestId>
<HostId>
9HnUUZpa9zUWfyzuNrZtRkoN2CYxH8V6rqx5QgsMFC6foTZKuG5qmZL5ThnUXooYPk2reFzKKUg=
</HostId>
</Error>

The generated url is "https://<bucket>.s3.amazonaws.com/<key>?X-Amz-Security-Token=<value>&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20180718T013339Z&X-Amz-SignedHeaders=content-type%253Bhost&X-Amz-Expires=1799&X-Amz-Credential=<value>&X-Amz-Signature=<value>

Any suggestions as to what needs to be corrected here in the generation of url ?

1

1 Answers

0
votes

The error was indeed related to a 'missing header', but not 'host' which was misleading. The value 'content-type' that comes before 'host' in X-Amz-SignedHeaders=content-type%253Bhost , needs to be explicitly provided as a request header when a http client uses the pre-signed url to upload a file to S3.

I had generated the pre-signed url in java as

GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucketName,objectKey).withMethod(HttpMethod.PUT).withContentType("application/pdf").withExpiration(expiration);

So S3 expects content-type with value 'application/pdf' to be part of the pre-signed url request as a header for a signature match as I understand.