arnemolland / sigv4

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

"com.amazon.coral.sCredential should be scoped to correct service #15

Open ghost opened 4 years ago

ghost commented 4 years ago

I get this response: "com.amazon.coral.service#InvalidSignatureException","message":"Credential should be scoped to correct service: 'dynamodb'. "

Here's my code:

var remoteConn = { 'keyId': 'AKIAZOT2IBVFOUX7EEDJ', 'accessKey': 'igENKxhRKap7E9j6/+CpcRzvx1Q1UoEob4o+R4hv', 'region': 'ap-southeast-2', 'serviceName': 'execute-api' }; var remotePath = 'https://dynamodb.ap-southeast-2.amazonaws.com';

void main() async { final client = Sigv4Client( keyId: remoteConn['keyId'], accessKey: remoteConn['accessKey'], region: remoteConn['region'], serviceName: remoteConn['serviceName'], );

/// https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.API.html /// https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Operations_Amazon_DynamoDB.html ///

final request = client.request( remotePath, method: 'POST', headers: { 'Content-Type': 'application/x-amz-json-1.0', 'X-Amz-Target': 'DynamoDB_20120810.ListTables' }, body: json.encode({}) );

Response resp = await post(request.url, headers: request.headers, body: request.body);

print(resp.body); //Map<String,dynamic> bytes = json.decode(response.bodyBytes); }

ghost commented 4 years ago

Arne, with your help I can transition my app from using Firestore REST api to using DynamoDB low level api... Cheers

ghost commented 4 years ago

I changed the serviceName from "execute-api" to "dynamodb", and now I get:

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

ghost commented 4 years ago

When I use the debugger to view the sigv4 header, I see:

AWS4-HMAC-SHA256 Credential=AKIAJF3YGRMQFHMDV4CA/20200602/ap-southeast-2/dynamodb/aws4_request,SignedHeaders=accept;content-length;content-type;host;x-amz-content-sha256;x-amz-date;x-amz-target,Signature=19bab5ee2641bbdf7432ef1e4c492c2cfc421a4f060db3b86d87206fa2f92296

and if I change PostMan's generated AWS header, I get this error:

{ "__type": "com.amazon.coral.service#IncompleteSignatureException", "message": "Authorization header requires existence of either a 'X-Amz-Date' or a 'Date' header. Authorization=AWS4-HMAC-SHA256 Credential=AKIAJF3YGRMQFHMDV4CA/20200602/ap-southeast-2/dynamodb/aws4_request,SignedHeaders=accept;content-length;content-type;host;x-amz-content-sha256;x-amz-date;x-amz-target,Signature=19bab5ee2641bbdf7432ef1e4c492c2cfc421a4f060db3b86d87206fa2f92296" }

ghost commented 4 years ago

The successful Postman generated header looks like this:

Authorization: AWS4-HMAC-SHA256 Credential=AKIAJF3YGRMQFHMDV4CA/20200602/ap-southeast-2/dynamodb/aws4_request, SignedHeaders=content-type;host;x-amz-content-sha256;x-amz-date;x-amz-target, Signature=b18255006e31d51fb6bd2f8b4f493f8dda5736b32046bb6d6976eb48813c0cc4

arnemolland commented 4 years ago

Hi, @github-bianca 👋

I'll look into this right now.

arnemolland commented 4 years ago

@github-bianca Which version of sigv4 are you on?

ghost commented 4 years ago

4.0.0

ghost commented 4 years ago

Is it a bug, or is it just my use of headers ? I tried using the sigv4 functionality of the other dart plugin (amazon_cognito_identity_dart_2), and that generated an auth header which got this postman response:

{ "__type": "com.amazon.coral.service#IncompleteSignatureException", "message": "Authorization header requires existence of either a 'X-Amz-Date' or a 'Date' header. Authorization=AWS4-HMAC-SHA256 Credential=AKIAJF3YGRMQFHMDV4CA/20200602/ap-southeast-2/dynamodb/aws4_request,SignedHeaders=host;x-amz-content-sha256;x-amz-date;x-amz-target,Signature=d140460529c65c8ba3e2260cf5bc3cbd3c89a0034c51e6b133cf93da74a6bf3a" }

ghost commented 4 years ago

BTW - upgraded to 4.1.0 - was using :any in my pubspec.yaml

arnemolland commented 4 years ago

It looks like I have to do some debugging with dynamodb tomorrow. I can't replicate this with s3 buckets or API gateway which I usually test with. Is the signature the only difference between the library generated request and the Postman request?

ghost commented 4 years ago

Your code generates the hash ok: I checked. Postman generates slightly different headers, but I assume the Authorization header is only calculated using the ones named in the SignedHeaders list. I'll dig some more today... Thanks, Ian

ghost commented 4 years ago

BTW the postman-generated list generated when I do a simple table list is:

SignedHeaders=content-type;host;x-amz-content-sha256;x-amz-date;x-amz-target

ghost commented 4 years ago

Your code generates a list that also includes the Accept header:

SignedHeaders=accept;content-type;host;x-amz-content-sha256;x-amz-date;x-amz-target

So I will try to remove Accept from the list that gets passed to sign() and see if I can get a correct calculation...

ghost commented 4 years ago

Even after ensuring that only those headers in the SignedHeaders list are passed to sign(), I still get the error: "The request signature we calculated does not match the signature you provided" Of course, since the current date is part of the auth header calculation, there is no way to unit test. It would be good to be able to see postman's code ;-)

ghost commented 4 years ago

Postman generated X-Amz-Date, and you can't override that by providing that header yourself, so since Postman requests do work, I guess debugging should use the vale generated by postman, and then you could compare your authorization header with postman's, right ?

ghost commented 4 years ago

I just tried your code using the AWS example: https://docs.aws.amazon.com/general/latest/gr/sigv4-add-signature-to-request.html

Your code generates an auth header that does not have a space before SignedHeaders, and one before Signature. (below is yours, then the one showing on the web site):

Authorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/iam/aws4_request,SignedHeaders=content-type;host;x-amz-date,Signature=5d672d79c15b13162d9279b0855cfba6789a8edb4c82c400e06b5924a6f2b5d7

Authorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/iam/aws4_request, SignedHeaders=content-type;host;x-amz-date, Signature=5d672d79c15b13162d9279b0855cfba6789a8edb4c82c400e06b5924a6f2b5d7

ghost commented 4 years ago

Although your code seems to work when following the AWS example pages, that scenario never mentions x-amz-content-sha256 ! So if you try to create the auth header using Sigv4.client(), you get a different result, because now the auth header includes x-amz-content-sha256 in the SignedHeaders list:

Authorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20200603/us-east-1/iam/aws4_request, SignedHeaders=content-type;host;x-amz-content-sha256;x-amz-date, Signature=e076c068d8941753c1cd65c27713c0ba77576c1cdc5929bd4d6b4dd1e9b79485

ghost commented 4 years ago

I really want to make use of dynamodb, so I'm going to change strategy: I will try using the API Gateway as a front-end to dynamodb. If / when you do find a way to sign a dynamodb request, I'll be very happy to hear about it... Thanks, Ian

arnemolland commented 4 years ago

I've added a commit removing the x-amz-content-sha256header if payload. Could you try it out with dynamodb?

dependencies:
  sigv4:
    git:
      url: https://github.com/arnemolland/sigv4.git
      ref: bugfix/invalid-signature
ghost commented 4 years ago

ok, I'll try it out. Will let you know soon... Many thanks

ghost commented 4 years ago

Unhandled Exception: type 'bool' is not a subtype of type 'String'

if (signPayload) {
  headers[_x_amz_content_sha256] = signPayload;
}

headers is a Map<String,String>, so you get the above exception.

ghost commented 4 years ago

You actually meant to type: headers.remove(_x_amz_content_sha256); I guess ;-)

arnemolland commented 4 years ago

My bad, fill fix asap.

ghost commented 4 years ago

Change does not work. Thanks anyway.

ghost commented 4 years ago

BTW - postman does include that header in its generated list:

AWS4-HMAC-SHA256 Credential=AKIAIQ7PGZVTHQR4SYYQ/20200605/ap-southeast-2/dynamodb/aws4_request, SignedHeaders=content-type;host;x-amz-content-sha256;x-amz-date;x-amz-target, Signature=39079d0acb121e47675d59dadbbba5a22370ab096899b59a151b6b10dc68288c

NOTE - the datetime value used here was '20200605T053653Z'

arnemolland commented 4 years ago

I’ve got limited time for the near future — if you’d like to fork this and do some testing I’d appreciate it. Will try to get onto this soon enough!

BartusZak commented 4 years ago

@github-bianca did you resolve that one?

I probably face the same issue here https://github.com/arnemolland/sigv4/issues/17

Will really appreciate to hear back from both of you.

ghost commented 4 years ago

No, I didn't resolve it. I'll have to stay with firestore until I find a way to sigv4 encode requests.

On Fri, Jun 26, 2020 at 2:49 AM BartusZak notifications@github.com wrote:

@github-bianca https://github.com/github-bianca did you resolve that one?

I probably face the same issue here #17 https://github.com/arnemolland/sigv4/issues/17

Will really appreciate to hear back from both of you.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/arnemolland/sigv4/issues/15#issuecomment-649691731, or unsubscribe https://github.com/notifications/unsubscribe-auth/AJPZXUQN4PD4G6WLVSY2QSLRYN5YLANCNFSM4NQM4Z5A .

-- Ian White h: +61 2 9948 9739 m: +61 404 950 122 hangout: biancashouse@gmail.com

mohanadshaban commented 3 years ago

Unhandled Exception: type 'bool' is not a subtype of type 'String'

if (signPayload) {
  headers[_x_amz_content_sha256] = signPayload;
}

headers is a Map<String,String>, so you get the above exception.

this code is bad because AWS says it should be calculated string not a boolean, as noted here image

So correcting this manually fixed the bug for me.

vincentjade commented 10 months ago

signature not yet current: 20231O14T164747Z

Rizabal commented 1 week ago

Signature not yet current: 2O24O817T223357Z