storage icon indicating copy to clipboard operation
storage copied to clipboard

SignatureDoesNotMatch Error When Using Uppy Companion with Supabase S3 Endpoint

Open edanweis opened this issue 11 months ago • 11 comments

Bug report

  • [x] I confirm this is a bug with Supabase, not with my own application.
  • [x] I confirm I have searched the Docs, GitHub Discussions, and Discord.

Describe the bug

When using Supabase's S3-compatible storage with Uppy Companion (https://uppy.io/docs/companion), file uploads fail with the following error:

SignatureDoesNotMatch: The request signature we calculated does not match the signature you provided. Check your key and signing method.

This occurs despite correct credentials and endpoint configuration.

When using AWS s3 endpoint, this configuration is working fine. For supabase uploads, I am only updating the access key, secret, path style option and endpoint url.**

To Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

  1. Set up Uppy Companion to use Supabase's S3-compatible storage:
  • S3 endpoint: https://ksdkkjdflkdiqmcvolalksk.supabase.co/storage/v1/s3
  • Bucket name: my-uploads
  • Region: ap-southeast-2
  1. Configure Companion with the following environment variables:
COMPANION_AWS_KEY=xxxx
COMPANION_AWS_SECRET=xxx
COMPANION_AWS_BUCKET=my-uploads
COMPANION_AWS_REGION=ap-southeast-2
COMPANION_SELF_ENDPOINT=https://uploads.example.com/companion
COMPANION_UPLOAD_URLS=https://uploads.example.com
  1. Configure tusd (https://github.com/tus/tusd) as Tus server with resumable uploads:
  • Enter credentials and region information:
export AWS_ACCESS_KEY_ID=xxx
export AWS_SECRET_ACCESS_KEY=xxx
export AWS_REGION=ap-southeast-2
  1. Run tusd:
  • tusd -upload-dir=/home/ec2-user/data -s3-endpoint=https://ksdkkjdflkdiqmcvolalksk.supabase.co/storage/v1/s3 -s3-bucket=uploads -behind-proxy
  1. Start uppy with the following configuration:
  "server": {
    "host": "uploads.example.com",
    "protocol": "https"
  },
  "corsOrigins": ["*"],
  "sendSelfEndpoint": "https://uploads.example.com/companion",
  "uploadUrls": ["*"],
  "filePath": "/home/ec2-user/data",
  "providerOptions": {},
  "s3": {
    "endpoint": "https://ksdkkjdflkdiqmcvolalksk.supabase.co/storage/v1/s3",
    "conditions": [],
    "useAccelerateEndpoint": false,
    "expires": 800,
    "forcePathStyle": true
  },
  "allowLocalUrls": false,
  "logClientVersion": true
}
  1. Attempt to upload a file via Uppy Companion and get the error:
ERR_INTERNAL_SERVER_ERROR: s3store: unable to create multipart upload:
operation error S3: CreateMultipartUpload, https response error StatusCode: 403, RequestID: , HostID: , api error SignatureDoesNotMatch: The request signature we calculated does not match the signature you provided. Check your key and signing method.

Expected behavior

The file upload should succeed with a valid signature calculated for the Supabase S3-compatible endpoint.

System information

  • OS: Amazon Linux 2 on an EC2 instance
  • Browser (if applies): N/A
  • Version of Node.js: 18.x

edanweis avatar Jan 15 '25 03:01 edanweis

Any update to this issue? We're experiencing similar issue with it supabase S3 endpoint:

An error occurred (SignatureDoesNotMatch) when calling the PutObject operation: The request signature we calculated does not match the signature you provided. Check your key and signing method.

kcy1860 avatar Jan 21 '25 04:01 kcy1860

same error on PutObject operations. aws s3 cp ... fails on the above aws s3 ls .... passes correctly (so credentials are valid)

mvrska avatar Jan 23 '25 20:01 mvrska

Hi, I've moved this issue over from the supabase repo as its storage related.

Hallidayo avatar Mar 22 '25 21:03 Hallidayo

Hi, I've moved this issue over from the supabase repo as its storage related.

@Hallidayo Not sure if this is the correct place either though. Seems to be a core/backend storage issue, not specifically related to storage-js (or any other client for that matter). I am experiencing similar issues with the signature using the aws-sdk-s3 gem in a Ruby on Rails project. In my case, I am not able to generate signed urls to link to stored objects. The issue might get less attention here, while this is quite important as it breaks a critical part of the S3 compatibility.

Tashows avatar Apr 07 '25 18:04 Tashows

@w3b6x9 Could you maybe look into this or move it back to main repo please? It looks like it's a backend/core issue, not a supabase-js and/or uppy-specific one.

Tashows avatar Apr 17 '25 10:04 Tashows

@Tashows this is correct, this is not a client lib issue. I moved it over to storage.

itslenny avatar Apr 17 '25 14:04 itslenny

@edanweis can you still repro this issue?

I just followed your repro steps and successfully uploaded a file via uppy companion without issue, but let me know if this is still not working for you.

itslenny avatar Apr 17 '25 14:04 itslenny

@itslenny In my case (and that might be the case for https://github.com/supabase/storage/issues/646 as well), Rails storage library (active_storage) adds some extra parameters to the query string for content-disposition. When I disabled them, the signature worked. The issue I referenced also mentions an extra parameter in the query, that is not s3-specific. Could this be why supabase-s3 breaks (i.e. maybe extra params are filtered out when checking the signature match)? And if so, is it valid for this to be fixed on the supabase-side?

Another relevant issue even more specific: https://github.com/supabase/storage/issues/544

--

For any other Rails developers, you can work around this by creating a new active_storage service that skips adding disposition params:

# /lib/active_storage/service/supabase_s3_service.rb
require "active_storage/service/s3_service"

module ActiveStorage
  class Service::SupabaseS3Service < Service::S3Service
    private
      def private_url(key, expires_in:, filename:, disposition:, content_type:, **client_opts)
        object_for(key).presigned_url :get, expires_in: expires_in.to_i, **client_opts
      end
  end
end

in your storage.yml change service: S3 to service: SupabaseS3

Tashows avatar May 16 '25 18:05 Tashows

import (
  smithymiddleware "github.com/aws/smithy-go/middleware"
)

func removeDisableGzip(stack *smithymiddleware.Stack) error {
	_, err := stack.Finalize.Remove("DisableAcceptEncodingGzip")
	return err
}


...


	client := s3.NewFromConfig(cfg, func(o *s3.Options) {
		o.UsePathStyle = true
		o.BaseEndpoint = aws.String(...)
		o.ClientLogMode = aws.ClientLogMode(0)
		o.APIOptions = append(o.APIOptions, removeDisableGzip)
	})
	return client

Jacke avatar Jun 19 '25 10:06 Jacke

I'm also getting similar issue

axion66 avatar Jun 21 '25 19:06 axion66

i solved my issue..? for my case i got my solution from https://github.com/orgs/supabase/discussions/26806 that supabase is still using AWS SDK v1, so i downgraded some libraries to adapt this. seems some libraries are deprecating v1 support as they use v2.

axion66 avatar Jun 21 '25 19:06 axion66

Closing this as solved

fenos avatar Sep 26 '25 09:09 fenos