'Amazon SP-API String to sign is returning different signed strings

This is interesting. For some reason my request to the Amazon SP-API is perfect EXCEPT for this last bit.

 @string_to_sign=
  "AWS4-HMAC-SHA256\n" +
  "20220512T203920Z\n" +
  "20220512/us-east-1/execute-api/aws4_request\n" +
  "cc00c92bff714c74d9cde1dc0721a18c464665cd01e14cf6ceb18fc8123e3fdb">

When it should have been (FROM AMAZON):

"The String-to-Sign should have been\n" +
"'AWS4-HMAC-SHA256\n" +
"20220512T203920Z\n" +
"20220512/us-east-1/execute-api/aws4_request\n" +
"a29e39c8746a46316676d8b6efff0e6ab5423a72ad93b061aa61ee84fc6bd611'\n" +

You can see that the string in the last line is different. And as a result I'm getting an invalid signature error when making the request.

The thing is, is I'm using the AWS::SigV4::Signer gem to generate the signature. Like this:

signer = Aws::Sigv4::Signer.new(
  service: "execute-api",
  region: "us-east-1",
  access_key_id: @temp_credentials[:access_key_id],
  secret_access_key: @temp_credentials[:secret_access_key],
  session_token: @temp_credentials[:session_token]
)

@signature = signer.sign_request(
  http_method: "POST", 
  url: @destination_url,
  headers: {
    'host' => 'sellingpartnerapi-na.amazon.com',
    'user_agent' => 'Todd (Language=Ruby)'
  }) 

Literally ALL other values in the response from Amazon are exactly the same, its JUST this string-to-sign that's giving me issues.

Any ideas?

EDIT: Even better? I switched to trying faraday with aws_sigv4 to sign the request.. and now? The response is

"Access token is missing in the request header."

Yet when I print the response, I can see the access token, all lower case, in the request header.

    conn = Faraday.new(url: 'https://sellingpartnerapi-na.amazon.com') do |faraday|
    faraday.request :aws_sigv4,
            credentials: Aws::Credentials.new(@temp_credentials[:access_key_id], @temp_credentials[:secret_access_key], @temp_credentials[:session_token]),
            service: 'execute-api',
            region: 'us-east-1'
    faraday.adapter Faraday.default_adapter
  end

  response = conn.post('/notifications/v1/destinations') do |req|
      req.headers["x-amz-access-token"] = @access_token
  end

  pp response

Yep, in that reponse I have:

   request_headers=
    {"User-Agent"=>"Faraday v2.2.0",
     "x-amz-access-token"=>
 "Atc|XXXXXXXXXXXXXXXRO5",
     "host"=>"sellingpartnerapi-na.amazon.com",
     "x-amz-date"=>"20220512T214331Z",

Good stuff



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source