arnemolland / sigv4

Dart library for signing AWS requests with Signature Version 4
MIT License
17 stars 23 forks source link

Signature does not match #13

Closed kleungkw closed 4 years ago

kleungkw commented 4 years ago

I'm trying to use the package to make a call to SageMaker but I'm getting a signature does not match error.

Here's the relevant code snippet:

  final client = Sigv4Client(
    keyId: '<my key id>',
    accessKey: '<my access key>',
    region: '<my-region>',
    serviceName: 'sagemaker',
  );

  final request = client.request(
    'https://runtime.sagemaker.<aws-region>.amazonaws.com/endpoints/<my-service>/invocations',
    method: 'POST',
    body: json.encode({'my': 'payload'}),
  );

  final response = await http.post(request.url,
      headers: request.headers, body: request.body);

and the returned error:

The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.

The Canonical String for this request should have been
'POST
/endpoints/<my-service>/invocations

accept:application/json
host:runtime.<my-service>.<aws-region>.amazonaws.com
x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
x-amz-date:20200424T030559Z

accept;host;x-amz-content-sha256;x-amz-date
82434076aad0553d39836f84119c47b9064c7e160390832cb468009bff7ba3ee'

The String-to-Sign should have been
'AWS4-HMAC-SHA256
20200424T030559Z
20200424/<my-region>/sagemaker/aws4_request
40fba0df7e43d4368b75fe9ebda06006b0ca7eebccea0400bdba10418ecd3cf2''

I've double checked my key id and access key are correct from testing using Postman and on aws-cli.

arnemolland commented 4 years ago

I'll look into this asap.

fauzy6493 commented 4 years ago

Hi @arnemolland any update?

    Map bodyData = {
        // This is where you define the body of the request,
        "data": "abc"
    };
    // A larger request
    final largeRequest = client.request(
      path,
      method: 'POST',
      headers: {'Content-Type': 'application/json'},      
      body: json.encode(bodyData)
    );

    // POST request
    post(
      largeRequest.url,
      headers: largeRequest.headers,
      body: largeRequest.body,
    ).then((res)=>{
      this.setState(() {
        _result = "status code: " + res.statusCode.toString() + " ; body: " + res.body.toString() + "\n\n\n";
        _result += "headers:" + largeRequest.headers.toString();
      })
    });

same issue here, but if i don't attach body inside client.request every think work fine.

fauzy6493 commented 4 years ago

Hi @arnemolland any update?

    Map bodyData = {
        // This is where you define the body of the request,
        "data": "abc"
    };
    // A larger request
    final largeRequest = client.request(
      path,
      method: 'POST',
      headers: {'Content-Type': 'application/json'},      
      body: json.encode(bodyData)
    );

    // POST request
    post(
      largeRequest.url,
      headers: largeRequest.headers,
      body: largeRequest.body,
    ).then((res)=>{
      this.setState(() {
        _result = "status code: " + res.statusCode.toString() + " ; body: " + res.body.toString() + "\n\n\n";
        _result += "headers:" + largeRequest.headers.toString();
      })
    });

same issue here, but if i don't attach body inside client.request every think work fine.

thank you very much @arnemolland

i solved this issue with mark header Content-Length on client.dart line 117 from this:

/// Set the `body`, if any
    if (body == null || method == 'GET') {
      body = '';
    } else {
      headers['Content-Length'] = utf8.encode(body).length.toString();
    }

to this:

    /// Set the `body`, if any
    if (body == null || method == 'GET') {
      body = '';
    } else {
      // headers['Content-Length'] = utf8.encode(body).length.toString();
    }
arnemolland commented 4 years ago

Thanks, @fauzy6493

I’ll do some testing and remove this if it’s not breaking anything else.