mturk API gives "specified claims are invalid" message about half the time; resubmitting randomly fixes

62 views Asked by At

I'm using a custom PHP script to submit requests to the mturk API, based on the signature functions from the PHP-AWS library. Here's an example of a request:

https://mechanicalturk.amazonaws.com/?Service=AWSMechanicalTurkRequester&AWSAccessKeyId=MYKEY&Version=2012-03-25&Operation=NotifyWorkers&Signature=j+4UTX9x3EKltvWpoxIkp4BM6S4=&Timestamp=2015-06-25T09:37:51Z&Subject=test&MessageText=just+testing+&WorkerId.1=SOMEID

Sometimes a given script will work, and at other times the same script will return an error like this:

AWS.BadClaimsSupplied The specified claims are invalid. Based on your request, your signature should be generated using the following string: AWSMechanicalTurkRequesterNotifyWorkers2015-06-25T09:37:51Z. Check to make sure your system clock and timezone is not incorrect. Our current system time: 2015-06-25T09:37:51Z. (1435225071849)

When I get the AWS.BadClaimsSupplied error, repeatedly rerunning the script will cause it to eventually work. By "work," I mean that either API returns true and the desired action is taken, or it returns an error that's relevant to the action I'm requesting.

I assume that if I were performing the hash incorrectly or with the wrong signature, then it would never work*. The intermittent nature of the problem makes me think it's a timing error. But the example above shows an error message in which the time I used for my signature is the same as their time, so that doesn't seem like the problem either.

*okay, it would work once in every 2^160 tries.

I tried backdating my timestamps by 1 second just in case I was a little ahead of them; that didn't change the results. I can't think of any other way to debug this.

1

There are 1 answers

0
octern On BEST ANSWER

The error message makes it sound like the problem is with the string being hashed, but the actual problem is that some hashed strings include special characters. The characters +, /, and = affect how the URL is parsed and will interfere with reading your signature. Rerunning the request with a different time string will randomly return a hash without those characters, allowing the request to work.

Solution: Simply run urlencode() on the signature before making the API call. If for some reason you don't want to do that, this answer provides some code that encodes those specific characters only, but I think the standard function is more comprehensive and safer.