Open ghost opened 4 years ago
Arne, with your help I can transition my app from using Firestore REST api to using DynamoDB low level api... Cheers
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
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" }
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
Hi, @github-bianca 👋
I'll look into this right now.
@github-bianca Which version of sigv4 are you on?
4.0.0
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" }
BTW - upgraded to 4.1.0 - was using :any in my pubspec.yaml
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?
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
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
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...
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 ;-)
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 ?
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
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
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
I've added a commit removing the x-amz-content-sha256
header if payload. Could you try it out with dynamodb?
dependencies:
sigv4:
git:
url: https://github.com/arnemolland/sigv4.git
ref: bugfix/invalid-signature
ok, I'll try it out. Will let you know soon... Many thanks
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.
You actually meant to type: headers.remove(_x_amz_content_sha256); I guess ;-)
My bad, fill fix asap.
Change does not work. Thanks anyway.
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'
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!
@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.
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
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
So correcting this manually fixed the bug for me.
signature not yet current: 20231O14T164747Z
Signature not yet current: 2O24O817T223357Z
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); }