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

"Signature Does Not Match" Error when uploading file with space or special characters in key via S3.upload. #849

Open
aram0112 opened this issue Dec 27, 2021 · 0 comments

Comments

@aram0112
Copy link

aram0112 commented Dec 27, 2021

Environment

Elixir 1.12.1 (compiled with Erlang/OTP 24)
ex_aws: 2.2.9
hackney: 1.18.0

Current behavior

When uploading a file via

"File Path"
|> S3.Upload.stream_file()
|> S3.upload("bucket", "key with space or special character")
|> ExAws.request(config)

A 403 http_error is received with the error message "The request signature we calculated does not match the signature you provided. Check your key and signing method."

Expected behavior

A 200 http response and a successful file upload.

Potential Fix

I pinpointed the issue to the ExAws.Auth module and was able to successfully upload a file after making the following changes.

def headers(http_method, url, service, config, headers, body) do
    with {:ok, config} <- validate_config(config) do
      datetime = :calendar.universal_time()

      # Added this line to the headers method to ensure the properly encoded url is used when generating the headers.
      url = ExAws.Request.Url.sanitize(url, service)

      headers =
        [
          {"host", URI.parse(url).authority},
          {"x-amz-date", amz_date(datetime)}
          | headers
        ]
        |> handle_temp_credentials(config)

      auth_header =
        auth_header(
          http_method,
          url,
          headers,
          body,
          service |> service_override(config) |> service_name,
          datetime,
          config
        )

      {:ok, [{"Authorization", auth_header} | headers]}
    end
  end
defp signature(http_method, url, query, headers, body, service, datetime, config) do
    # Removed the last function call to encode the path as I am guessing the path here needs to match the ultimate S3 key 
    # with spaces and special characters 
    # previously was path = url |> Url.get_path(service) |> Url.uri_encode()
    path = url |> Url.get_path(service)
    request = build_canonical_request(http_method, path, query, headers, body)
    string_to_sign = string_to_sign(request, service, datetime, config)
    Signatures.generate_signature_v4(service, config, datetime, string_to_sign)
  end

I am hoping for any guidance from someone with more experience in the Auth Module on whether this is an actual issue and fix or whether I am approaching the issue incorrectly. Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant