Presigned PUT Fails With 403

Hi,

I am creating pre-signed PUT urls in my app and running into 403 errors.

When creating URL’s via the tigris dashboard I can see they come out in the shape:

https://files.allaboutholes.vip/import-jobs.csv?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=tid_sIYWNboOecJPzFPmgbOmxsfSqjwbmYmSoGAlrylliULbhiysCJ%2F20251107%2Fauto%2Fs3%2Faws4_request&X-Amz-Date=20251107T020219Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=...

When creating URL’s via the application code below I get the following shape:

const endpoint 'https://fly.storage.tigris.dev';
const bucketName = 'holehub-dev';
const forcePathStyle = false;
const deleteAfter = new Date(new Date().getTime() + (1000 * 60 * 60));

const s3Client = new S3Client({
  region: 'auto',
  endpoint,
  credentials: {
    accessKeyId,
    secretAccessKey,
  },
  forcePathStyle,
  // have tried the following too
  // requestChecksumCalculation: 'WHEN_REQUIRED',
});      

const signedUrl = await getSignedUrl(
  s3Client,
  new PutObjectCommand({
    Bucket: bucketName,
    Key: '/jobs/imports/uploads/01K9E0WRQT8P0DM5GX65NZWXB2.csv',
    Expires: deleteAfter,
    // have tried disabling this too
    ContentLength: fileSize,
}),
  { expiresIn: 3600 },
);
https://holehub-dev.fly.storage.tigris.dev/jobs/imports/uploads/01K9E0WRQT8P0DM5GX65NZWXB2.csv?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=tid_sIYWNboOecJPzFPmgbOmxsfSqjwbmYmSoGAlrylliULbhiysCJ%2F20251107%2Fauto%2Fs3%2Faws4_request&X-Amz-Date=20251107T020358Z&X-Amz-Expires=3600&X-Amz-Signature=...&X-Amz-SignedHeaders=host&x-id=PutObject

The tigris dashboard generated presigned url works fine, the s3 client generated one results in:

`HTTP/1.1 403 Forbidden
Content-Length: 433
Content-Type: application/xml
Server: Tigris OS
Server-Timing: total;dur=163
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
X-Amz-Request-Id: 1762481194277975954
Date: Fri, 07 Nov 2025 02:06:34 GMT
Connection: close

<?xml version="1.0" encoding="UTF-8"?> SignatureDoesNotMatch The request signature we calculated does not match the signature you provided. Check your key and signing method. /jobs/imports/uploads/01K9E0WRQT8P0DM5GX65NZWXB2.csv 1762481194277975954 jobs/imports/uploads/01K9E0WRQT8P0DM5GX65NZWXB2.csv holehub-dev `

What am I doing wrong here? I’m not new to presigned url’s, new to tigris.

Hello @craigmsqrd - I noticed that aws-sdk/s3-request-presigner when you have key prefixed with / it adds double / in the URL generated. Can you try key as jobs/imports/…. instead?

1 Like

This topic was automatically closed 8 days after the last reply. New replies are no longer allowed.