We are using AWS SignatureV4 to make requests to an API Gateway using the IAM authoriser and are finding that signing only works some of the time...
We are signing requests using the AWS SDK.
$credentials = new Credentials(env('AWS_ACCESS_KEY_ID', ''), env('AWS_SECRET_ACCESS_KEY', ''));
$signer = new SignatureV4('execute-api', env('AWS_DEFAULT_REGION', ''));
$request = $signer->signRequest($request, $credentials);
Here are two example requests which are being made. (I have redacted sensitive information. These fields are identical between requests)
https://[redacted].execute-api.eu-west-1.amazonaws.com/dev-ew1/api/v1/users?userId[]=34129&userId[]=2405&userType=student&oktaId=[redacted]
https://[redacted].execute-api.eu-west-1.amazonaws.com/dev-ew1/api/v1/users?userId[]=2405&userId[]=196624&userType=student&oktaId=[redacted]
The top request is signed correctly and is processed. The second request fails with the following message:
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
'GET
/dev-ew1/api/v1/users
oktaId=[redacted]&userId%5B%5D=196624&userId%5B%5D=2405&userType=student
host:[redacted].execute-api.eu-west-1.amazonaws.com
x-amz-date:20231218T101701Z
x-platform:messaging
x-platform-organisation:55
host;x-amz-date;x-platform;x-platform-organisation
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'
The String-to-Sign should have been
'AWS4-HMAC-SHA256
20231218T101701Z
20231218/eu-west-1/execute-api/aws4_request
3400b7c56695b319d050d264522b645bf19346449c2147768fc0ca10b36001cf'
Both the successful and the failing request have the same headers.
{
"Host": [
"[redacted].execute-api.eu-west-1.amazonaws.com"
],
"X-Platform": [
"messaging"
],
"X-Platform-Organisation": [
"55"
],
}
Both use the same AWS credentials. The failure is the same all the time. The only thing that changes is the URL. E.g.
-- Query 2405 - Works
https://[redacted].execute-api.eu-west-1.amazonaws.com/dev-ew1/api/v1/users?userId[]=2405&userType=student&oktaId=[redacted]
-- Query 196624 - Works
https://[redacted].execute-api.eu-west-1.amazonaws.com/dev-ew1/api/v1/users?userId[]=196624&userType=student&oktaId=[redacted]
-- Query 2405 + 196624 at the same time - Signing Error
https://[redacted].execute-api.eu-west-1.amazonaws.com/dev-ew1/api/v1/users?userId[]=2405&userId[]=196624&userType=student&oktaId=[redacted]
-- Query 2405 + 34129 at the same time and this works fine??
https://[redacted].execute-api.eu-west-1.amazonaws.com/dev-ew1/api/v1/users?userId[]=34129&userId[]=2405&userType=student&oktaId=[redacted]
We are using PHP8.1 and aws sdk 3.294.1
Any ideas on how to debug further and figure this out?
I thought ?userId[]=2405&userId[]=196624
was part of the W3C spec. However, it appears to be a PHP thing. As apokryfos suggests in the comments. Replacing this with a different way to pass user ids resolves the issue.