SignatureDoesNotMatch ☁️ AWS

AWS: SignatureDoesNotMatch / InvalidClientTokenId — the request signature we calculated does not match

AWS rejected the request signature — wrong secret key, wrong region, clock skew, or a presigned URL used differently from how it was signed.

Seen on: AWS JavaScript

Meaning

Every AWS request is signed with your secret key (SigV4) over the method, path, headers and timestamp. A wrong secret, an extra/changed header, the wrong region or a clock more than ~5 minutes off all break the signature. InvalidClientTokenId means the access key ID itself isn’t recognised.

Common causes

  • Secret key copied with extra spaces/characters
  • Access key and secret from different pairs / accounts
  • System clock skew
  • Wrong region for the endpoint
  • Presigned S3 URL used with different method or Content-Type than signed
  • Special characters in object keys not encoded consistently

⚡ Quick fix

  1. Re-copy or rotate the key pair
  2. Sync time (NTP)
  3. Use the bucket’s actual region
  4. For presigned PUTs, send exactly the Content-Type you signed

Detailed fix by platform

AWS

  1. Presigned PUT must match the signed Content-Type:
    javascript
    const url = await getSignedUrl(s3, new PutObjectCommand({ Bucket: 'uploads', Key: key, ContentType: 'image/png' }), { expiresIn: 300 });
    await fetch(url, { method: 'PUT', headers: { 'Content-Type': 'image/png' }, body: file });

How to diagnose

  1. Key pair — ID and secret from the same pair?
  2. Clock — Server time correct?
  3. Region — Signing region = resource region?
  4. Presigned — Same method/headers as signed?

🧠 Still stuck? Analyze your error

Paste the full message, response headers or stack trace — we'll detect the platform and point to the most likely cause.