SignatureDoesNotMatch error when uploading to DigitalOcean Spaces with presigned URL
flyingboy007 opened this issue · comments
I'm working on a Rails application that uses Shrine to upload files directly to DigitalOcean Spaces using presigned URLs. However, I'm encountering a SignatureDoesNotMatch error during the upload process. I've verified my credentials and ensured that the Content-Type
and Content-Disposition
headers match between the presigned URL generation and the actual upload request. Despite this, the error persists.
Here's the relevant part of my code for generating the presigned URL:
require 'shrine/storage/s3'
s3_options = {
endpoint: 'https://blr1.digitaloceanspaces.com',
bucket: 'test-dev',
access_key_id: ENV['DO_SPACES_ACCESS_KEY_ID'],
secret_access_key: ENV['DO_SPACES_SECRET_ACCESS_KEY'],
region: 'blr1',
}
Shrine.storages = {
cache: Shrine::Storage::S3.new(prefix: 'cache', **s3_options),
store: Shrine::Storage::S3.new(prefix: 'store', **s3_options),
}
Shrine.plugin :activerecord
Shrine.plugin :cached_attachment_data
Shrine.plugin :restore_cached_data
Shrine.plugin :backgrounding
Shrine.plugin :derivatives
Shrine.plugin :determine_mime_type
Shrine.plugin :presign_endpoint, presign_options: -> (request) {
filename = 'invoice.pdf'
type = request.params['type'] || 'application/pdf'
{
content_disposition: ContentDisposition.inline(filename),
content_type: type,
method: :put,
}
}
The presigned URL generated looks like this:
{
"fields": {},
"headers": {
"Content-Type": "application/pdf",
"Content-Disposition": "inline; filename=\"invoice.pdf\"; filename*=UTF-8''invoice.pdf"
},
"method": "put",
"url": "https://test-dev.blr1.digitaloceanspaces.com/cache/49d38c38478222056e32ea3bfff5c783?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=DO00RZLGPKJ6JWCCTQLD%2F20240301%2Fblr1%2Fs3%2Faws4_request&X-Amz-Date=20240301T024329Z&X-Amz-Expires=900&X-Amz-SignedHeaders=content-disposition%3Bcontent-type%3Bhost&X-Amz-Signature=0814b01e839daa73312c73ce27b3b18b473bef05bdecff426b1d3c50127dd3dc"
}
And the error response from DigitalOcean Spaces is:
<?xml version="1.0" encoding="UTF-8"?>
<Error>
<Code>SignatureDoesNotMatch</Code>
<Message></Message>
<RequestId>tx000001b5e7e7644078f7a-0065e141a8-e2afaf-blr1a</RequestId>
<HostId>e2afaf-blr1a-blr1-zg01</HostId>
</Error>
Here is the curl from postman
curl --location --request PUT 'https://test-dev.blr1.digitaloceanspaces.com/cache/49d38c38478222056e32ea3bfff5c783?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=DO00RZLGPKJ6JWCCTQLD%2F20240301%2Fblr1%2Fs3%2Faws4_request&X-Amz-Date=20240301T024329Z&X-Amz-Expires=900&X-Amz-SignedHeaders=content-disposition%3Bcontent-type%3Bhost&X-Amz-Signature=0814b01e839daa73312c73ce27b3b18b473bef05bdecff426b1d3c50127dd3dc' \
--header 'Content-Type: application/pdf' \
--header 'Content-Disposition: inline; filename=\"invoice.pdf\"; filename*=UTF-8'\'''\''invoice.pdf' \
--data '@postman-cloud:///1eed75ce-e91a-46f0-9ce6-cac7b50716a0'
Has anyone encountered this issue before or can spot what might be going wrong?
I switched to using post method for presign generation and uploading and it works