SignatureDoesNotMatch when using pre-signed URL with AWS-SDK

I’m getting SignatureDoesNotMatch when creating a presigned-url for PUT.

const url = await getSignedUrl(
      s3Client,
      new PutObjectCommand({
        Bucket: config.AWS_BUCKET,
        Key: key,
      }),
      {
        expiresIn: dayjs.duration(10, 'minutes').asSeconds(),
      }
    );

Log output for debugging purposes:

[3:12:26 PM] [DEVELOPMENT S3Service] › ⬤  debug     Creating signed upload URL {
  Bucket: 'poket-development',
  Key: 'user_ntIpGStKjh/upload_IoNt4AS0LV.jpeg'
}

I have also eliminated the possibility of credentials being incorrect, by manually uploading a file via the application code, which worked.

My s3Client provider.

export const s3Client = new S3Client({
  credentials: {
    accessKeyId: config.AWS_ACCESS_KEY_ID,
    secretAccessKey: config.AWS_SECRET_ACCESS_KEY,
  },
  endpoint: config.AWS_ENDPOINT_URL_S3,
  region: config.AWS_REGION,
});

FWIW, this is the response of my endpoint that generates the signed upload url:

{
  "data": {
    "key": "user_ntIpGStKjh/upload_gl6Z773udR.jpeg",
    "url": "https://poket-development.fly.storage.tigris.dev/user_ntIpGStKjh/upload_gl6Z773udR.jpeg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=tid_aVSfDhrskfMKuubfxAnILQWr_g_VGvfvDOrodsXhFZnXGniwCD%2F20250119%2Fauto%2Fs3%2Faws4_request&X-Amz-Date=20250119T071603Z&X-Amz-Expires=600&X-Amz-Signature=d7df6fa0eecb35e2dc079ad117e1c71256ee7c5c9b7067a8b27f6910f7a5b638&X-Amz-SignedHeaders=host&x-amz-checksum-crc32=AAAAAA%3D%3D&x-amz-sdk-checksum-algorithm=CRC32&x-id=PutObject"
  },
  "metadata": {
    "requestID": "9bf01b82-3df5-426c-a6f1-d1f086286a82",
    "resource": "/v1/uploads/",
    "statusCode": 201,
    "timestamp": "2025-01-19T07:16:03Z"
  }
}

What I’ve tried,

  1. Regenerating the credentials
  2. Create another bucket without “-” in the name
  3. Signing the PUT url with an explicit content-type.
  4. Specified content-type in the header when making the PUT request.
  5. Hard-coded a simple key name. e.g. “abc” to eliminate possibility of encoding issues.

None of them worked so far, appreciate if anyone can point out what I’m missing.

Thanks in advance

Solved by adding this configuration:

export const s3Client = new S3Client({
  credentials: {
    accessKeyId: config.AWS_ACCESS_KEY_ID,
    secretAccessKey: config.AWS_SECRET_ACCESS_KEY,
  },
  endpoint: config.AWS_ENDPOINT_URL_S3,
  region: config.AWS_REGION,
  requestChecksumCalculation: 'WHEN_REQUIRED',
  responseChecksumValidation: 'WHEN_REQUIRED',
});

For signed PUT url:
requestChecksumCalculation: 'WHEN_REQUIRED',

For signed GET url
responseChecksumValidation: 'WHEN_REQUIRED',

Credit:
https://community.cloudflare.com/t/aws-sdk-client-s3-v3-729-0-breaks-uploadpart-and-putobject-r2-s3-api-compatibility/758637/16