I'm using the following code (excerpt) in my backend to create a presigned URL to an mp3 file within an AWS S3 bucket:
const s3Client = new S3Client({
credentials: {
accessKeyId: "AAAAAAAAAAAAAAAAAAAA",
secretAccessKey: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
}
});
const getObjectCommand = new GetObjectCommand({
Bucket: "my-bucket-name",
Key: "file-to-be-used"
});
// Generate a signed URL for the GET request
const url = await getSignedUrl(s3Client, getObjectCommand, { expiresIn: 300 }).then(data => {
...
do some stuff and return the url
...
});
Postman
Calling this code in Postman works as expected and the presigned URL returned from my backend works immediately after getting the response in Postman (e.g. by just clicking on it).
Browser
In my browser, however, I get 403 - Access forbidden
errors when using the URL, e.g. for either setting it as the source for an HTMLAudioElement
or getting it via a fetch
request.
Confusing behaviour (in the browser)
When I wait for about 15 seconds before using/accessing the returned URL, then it works as expected (just clicking on it opens in the browser, setting it as source for the HTMLAudioElement
also works).
Screen Recording
The screen recording from the browser shows how the request returns a presigned URL. It also shows the 403 errors (one when trying to set the URL as source for an HTMLAudioElement
, the second when trying to fetch the presigned URL from S3).
You can also see that clicking on the URL at first leads to 403 errors (in the new browser tab that opens) twice. When clicking on the same URL for the third time it works (also works when just waiting for about 15 seconds as described above).
- I do not get any CORS related errors (and I've set up CORS with
AllowedHeaders
andAllowedOrigins
set to*
each) - In Postman the returned URL works immediately
- The URL I try to access is exactly the same (as I'm using my own backend) for Postman and within the browser
Any ideas what might be wrong?
Update
As suggested in the comments, I've tried with another bucket in the standard region (us-east-1), same results:
The request and headers in Postman
As it was sent by Postman
https://presigned-url-test-tim.s3.us-east-1.amazonaws.com/4f65f31b-7d63-4be0-a289-1c3a8e056ea4.mp3?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIASAQ3L4XYIZI4YD73%2F20230311%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20230311T220846Z&X-Amz-Expires=300&X-Amz-Signature=b3c081018ea7e9f7979a65267f66bfdcf2f185d2f824bd86fa9ae9141e8ba627&X-Amz-SignedHeaders=host&x-id=GetObject
and again for better readability
https://presigned-url-test-tim.s3.us-east-1.amazonaws.com/4f65f31b-7d63-4be0-a289-1c3a8e056ea4.mp3?
X-Amz-Algorithm=AWS4-HMAC-SHA256&
X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&
X-Amz-Credential=AKIASAQ3L4XYIZI4YD73%2F20230311%2Fus-east-1%2Fs3%2Faws4_request&
X-Amz-Date=20230311T220846Z&
X-Amz-Expires=300&
X-Amz-Signature=b3c081018ea7e9f7979a65267f66bfdcf2f185d2f824bd86fa9ae9141e8ba627&
X-Amz-SignedHeaders=host&
x-id=GetObject
Additionally, Postman shows the following info under Request headers
in the Console log:
User-Agent: PostmanRuntime/7.31.1
Accept: */*
Postman-Token: 4364aac9-1334-4434-b9a9-0b792dbde7b5
Host: presigned-url-test-tim.s3.us-east-1.amazonaws.com
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
The request headers in the browser
As it was sent by the browser
https://presigned-url-test-tim.s3.us-east-1.amazonaws.com/4f65f31b-7d63-4be0-a289-1c3a8e056ea4.mp3?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIASAQ3L4XYIZI4YD73/20230311/us-east-1/s3/aws4_request&X-Amz-Date=20230311T220557Z&X-Amz-Expires=300&X-Amz-Signature=e58bdbb1af3d4d47e1ec7c2aeaab3f77dd3a1fd7987831f1d0e6367a359637ef&X-Amz-SignedHeaders=host&x-id=GetObject
and again for better readability
https://presigned-url-test-tim.s3.us-east-1.amazonaws.com/4f65f31b-7d63-4be0-a289-1c3a8e056ea4.mp3?
X-Amz-Algorithm=AWS4-HMAC-SHA256&
X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&
X-Amz-Credential=AKIASAQ3L4XYIZI4YD73/20230311/us-east-1/s3/aws4_request&
X-Amz-Date=20230311T220557Z&
X-Amz-Expires=300&
X-Amz-Signature=e58bdbb1af3d4d47e1ec7c2aeaab3f77dd3a1fd7987831f1d0e6367a359637ef&
X-Amz-SignedHeaders=host&
x-id=GetObject