What you'll learn
- A presigned URL carries a signature made with your credentials; whoever holds it can perform exactly the signed request until it expires.
- Sign the narrowest request: one method, one key, the content type, and a short
expiresIn. - SigV4 URLs last at most 7 days, and never longer than the credentials that signed them.
Section 01
How presigning works
Your server builds a normal S3 request — say, PutObject for uploads/trainer-42/sprite.png — and signs it with its own credentials, but puts the signature in the URL's query string instead of a header. No call to AWS happens while signing.
The browser then sends a plain HTTP PUT to that URL. S3 checks the signature, the expiry and the signer's permissions. The browser never sees your credentials, and the URL is useless for any other key or method.
import { PutObjectCommand } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
const url = await getSignedUrl(
client,
new PutObjectCommand({ Bucket, Key: `uploads/${trainerId}/sprite.png`, ContentType: "image/png" }),
{ expiresIn: 300 } // seconds
);await fetch(url, { method: "PUT", headers: { "Content-Type": "image/png" }, body: file });Section 02
Expiry
expiresIndefaults to 900 seconds (15 minutes). Set it explicitly and keep it short: long enough to finish the upload, no longer.- Signature Version 4 caps it at 604,800 seconds (7 days).
- If the signer used temporary credentials (a Lambda role, for example), the URL stops working when those credentials expire — even if
expiresInis longer.
Section 03
Keep uploads safe
- Write untrusted uploads under their own prefix (
uploads/) and process them before promoting them tosprites/. - A presigned PUT can't limit the file size. When you need that, use a presigned POST (
@aws-sdk/s3-presigned-post) with acontent-length-rangecondition. - Browsers need a CORS rule on the bucket allowing
PUTfrom your site's origin. - Anyone who gets the URL can use it. Don't log it, and don't reuse one URL for many users.
Practice
Your turn
Trainers upload their own sprite PNGs straight from the browser. Your server signs a URL for exactly one upload. This code signs the wrong operation and lets the link live for a day — fix both.
PutObjectCommand with ContentType: "image/png" and expiresIn: 300.Check
Check your understanding
Quick Quiz · one question, as many tries as you need.
expiresIn: 604800. Users report the link stops working after a few hours. Why?Choose one answer.