October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsWindows FixRecommendedWindows errors stealing your time? Find the fix fastScan stability, cleanup and performance issues.Fix NowOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
World desk6 min

Let Users Upload Files to S3 Without Giving Them AWS Access (Try It Yourself)

Your server authenticates the user and issues a short-lived presigned S3 URL for one object key. The browser uploads straight to S3 without holding any AWS credentials. Here is the flow, the CORS setup, and how to test it.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

To let users upload files to S3 without giving them AWS access, your application server does the authorizing and S3 does the storing. The server checks who the user is, picks the object key, and generates a short-lived presigned URL for one S3 operation. The browser then sends the file straight to that URL. The browser never receives AWS access keys or any general S3 permission, only a time-limited capability for that single upload.

Who holds what in this flow

A presigned URL is generated with the permissions of the principal that created it. If your backend signs a PUT for a key, the URL can succeed only because the backend’s own identity is allowed to write that key. AWS states the core idea in the Amazon S3 User Guide: the approach “allows an upload without requiring another party to have AWS security credentials or permissions.” The user’s browser is that other party.

As an Amazon Associate I earn from qualifying purchases.

That shifts the trust boundary to three places, and each one needs its own control:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • The application server must authenticate the user, decide whether this user may upload, and choose the object key. Its signing identity should be an IAM role with temporary credentials, not long-term access keys stored in code or on the instance. AWS’s security best practices recommend this pattern for applications that access S3.
  • The presigned URL is the only thing the browser holds. AWS describes presigned URLs as “bearer tokens that grant access to those who possess them.” Anyone who copies the URL can use it until it expires, can use it more than once in that window, and can overwrite the object at that key.
  • The bucket stays private. A presigned upload does not require a publicly writable bucket, and you should not make one to solve this problem.

Build it: server, browser, bucket

1. Issue the URL on the server

The handler should run only for an authenticated session. Take the user ID from the session, never from the request body, and decide the content type and size limits before signing anything. The example below uses Python with boto3 and the generate_presigned_url method for put_object, which AWS’s presigned-upload documentation shows.

#1 Best Overall
Sale
Lexar D40E 128GB Dual USB 3.2 Gen 1 Type-C Jump Drive, Champagne Silver
  • USB-C 2-in-1 storage OTG: The Lexar JumpDrive Dual Drive D40E features USB Type-A and Type-C connectors in a slim, portable form factor for easy device compatibility
  • Transfer speeds up to 100MB/s: Based on internal testing, performance may vary depending upon the host device, interface, and usage conditions. 1MB=1,000,000 bytes
  • Plug and Play: Widely compatible with USB Type-C smartphones, tablets, laptops, Macs, and traditional Type-A devices, no software installation required. The 360° swivel design allows for easy switching between connectors without the hassle of losing a cap
  • Durable & Compact: The Lexar D40E USB memory stick features a metal enclosure, withstands temperatures from 0° to 50° C (32°F to 122°F), and is lightweight at 26g with dimensions of 70.4 x 16.9 x 11.7mm
  • Security & Warranty: Securely protects files using an advanced security software solution with 256-bit AES encryption. Backed by a Lexar 3-year limited warranty
import uuid
import boto3

BUCKET = "example-user-uploads"   # private bucket
s3 = boto3.client("s3", region_name="us-east-1")

def create_upload_url(user_id: str, content_type: str) -> dict:
    # Server-generated key: the client never chooses a path or filename.
    key = f"uploads/{user_id}/{uuid.uuid4()}"
    url = s3.generate_presigned_url(
        ClientMethod="put_object",
        Params={"Bucket": BUCKET, "Key": key, "ContentType": content_type},
        ExpiresIn=300,  # five minutes, enough for one file in a normal flow
    )
    return {"url": url, "key": key, "content_type": content_type}

Store the original filename, size, and owner in your own database, keyed to the generated object key. Do not put the user’s filename into the S3 key.

2. Upload from the browser

Send the file body with an HTTP PUT to the exact URL the server returned. The Content-Type header must match the value you signed. If it differs, S3 rejects the request with a signature error.

Rank #2
KOOTION USB C Flash Drive 32GB 2 in 1 OTG USB 3.0/Type C Thumb Drive Dual Drive USB C Memory Stick for Smartphone Laptop Tablet PC, Blue
  • 2 in 1: USB C + USB 3.0, 32GB usb c flash drive has dual ports, usb 3.0 port is applied to all devices which have usb 3.0 interface and usb c port is widely used in all Android smartphones with OTG function
  • High Speed USB 3.0: Read speed up to 90 MB/s, Write speed up to 30 MB/s, the speed of USB 3.0 interface is faster than USB 2.0, save time to wait, increases work productivity. Note: Speed will be limited if you use the USB key in the USB 2.0 interface
  • Large Compatibility: The USB 3.0 Connector is compatible with USB 3.0 & USB 2.0 backward USB 1.1 devices, such as Laptop, Desktop, Car Audio, Tablet, TV, Speakers, Projector. USB-C port is compatible with all Android Smartphones
  • Expand Storage: Good performance in storing, transferring and sharing digital data with families, friends, colleagues, customers. It can expand the capacity of smartphone, you can watch movies or share pictures when you go on vacation with your family
  • Note: Make sure your smartphone is equipped with OTG function and need to open OTG function in Settings when you plug memory stick, then you can transfer easily data bewteen different devices
async function uploadFile(uploadUrl, contentType, file) {
  const res = await fetch(uploadUrl, {
    method: "PUT",
    headers: { "Content-Type": contentType },
    body: file,
  });
  if (!res.ok) {
    throw new Error(`Upload failed with status ${res.status}`);
  }
  return res;
}

Do not modify the URL. Changing the query string, host, or path invalidates the signature.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

3. Allow the browser origin in bucket CORS

If your page is served from a different origin than the S3 bucket endpoint, the browser sends a preflight OPTIONS request before the PUT. The bucket must allow that request. CORS controls whether the browser may make the cross-origin call; the signature and IAM permissions still decide whether S3 performs the operation. In the S3 console, open the bucket, choose the Permissions tab, and edit Cross-origin resource sharing (CORS). A rule for a single site looks like this:

Rank #3
Sale
Lexar D40E 64GB Dual USB 3.2 Gen 1 Type-C Jump Drive, Champagne Silver
  • USB-C 2-in-1 storage OTG: The Lexar JumpDrive Dual Drive D40E features USB Type-A and Type-C connectors in a slim, portable form factor for easy device compatibility
  • Transfer speeds up to 100MB/s: Based on internal testing, performance may vary depending upon the host device, interface, and usage conditions. 1MB=1,000,000 bytes
  • Plug and Play: Widely compatible with USB Type-C smartphones, tablets, laptops, Macs, and traditional Type-A devices, no software installation required. The 360° swivel design allows for easy switching between connectors without the hassle of losing a cap
  • Durable & Compact: The Lexar D40E USB memory stick features a metal enclosure, withstands temperatures from 0° to 50° C (32°F to 122°F), and is lightweight at 26g with dimensions of 70.4 x 16.9 x 11.7mm
  • Security & Warranty: Securely protects files using an advanced security software solution with 256-bit AES encryption. Backed by a Lexar 3-year limited warranty
[
  {
    "AllowedOrigins": ["https://app.example.com"],
    "AllowedMethods": ["PUT"],
    "AllowedHeaders": ["Content-Type"],
    "ExposeHeaders": ["ETag"],
    "MaxAgeSeconds": 3000
  }
]

List your exact site origin, including the scheme and any port, rather than a wildcard. Allow only the methods and headers the browser actually sends. The browser’s preflight asks for Content-Type, so the rule must allow it.

Test it from the command line first

Before you debug the browser, confirm that the signed URL works on its own. Save a small file, then run a PUT with the same content type you signed:

Rank #4
2-Pack 128GB USB C Flash Drive Dual Type C + USB A Memory Stick Jump Drive 2-in-1 Thumb Drive for Storage and Backup (128GB*2 Black&Blue)
  • 2-in-1 Dual Design: Features both USB-C and USB-A connectors, making it compatible with phones, tablets, MacBooks, PCs, and laptops-no adapter needed
  • Wide Compatibility: Works seamlessly with USB A and USB C devices, ensuring reliable file transfers across smartphones, computers, and more
  • Ample Storage Options: Available in 16GB/32GB/64GB/128GB providing plenty of space for photos, videos, music, and documents
  • Portable & Lightweight: Compact and durable design for travel, school, or daily use-take your files anywhere
  • Plug-and-Play Convenience: No software or drivers required; simply insert into USB-C or USB-A ports and start transferring files instantly
curl -i -X PUT 
  -H "Content-Type: text/plain" 
  --data-binary @sample.txt 
  "$UPLOAD_URL"

A successful upload returns HTTP/1.1 200 OK with an ETag header. Then confirm the object exists under the key your server generated:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
aws s3api head-object --bucket example-user-uploads --key "uploads/USER_ID/OBJECT_ID"

Replace USER_ID/OBJECT_ID with the key your server returned. If curl succeeds but the browser fails, the problem is almost always CORS, not signing.

Best Value
Samsung Type-C USB Flash Drive 256GB, USB 3.2 Gen 1, Up to 400MB/s | Transfer 4GB Files in 15 Secs, Compatible w/ USB 3.0/2.0, Waterproof, Storage for Computers & Mobile, Blue (MUF-256DA/AM)
  • USB-C STORAGE ON THE GO: This sleek drive is supported by Samsung NAND flash and is incredibly compact to fit in the palm of your hand; Count on reliable performance and fast transfer speeds while staying compact
  • PERFORMANCE WITH SPEED: No need to choose between performance and reliability; Experience a fast, powerful flash drive that transfers 4GB files in just 11 seconds with up to 400MB/s USB 3.2 Gen 1 read speeds and is backward compatible with USB 3.0/2.0
  • MODERN MEETS ICONIC: The ultra-sleek USB-C drive looks as good as it performs; Featuring a reversible plug, the Type-C inserts into your devices seamlessly every time; Transfer large files with style and ease
  • ALWAYS CONNECTED: USB-C is compatible across devices, including laptops, tablets, phones and cameras, with enough space for 63,730 photos or maximum 12 hours of 4K video; With up to 256GB of storage space, this pocket-sized thumb drive comes in handy wherever you go
  • TOUGH & TRUSTED: Files stay secure, no matter the terrain; Samsung's flash memory technology makes the Type-C a trustworthy drive to store your valuable data; It's waterproof, shock-proof, magnet-proof, temperature-proof, and X-ray-proof body, plus it's backed by a 5-year limited warranty
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Presigned PUT or signed browser POST

S3 offers a second browser path: an HTML form that POSTs multipart data with a signed policy. Both approaches rely on the same foundations (private bucket, server-side authorization, safe keys), so neither is inherently more secure. Choose based on the shape of your upload.

Axis Presigned PUT Signed browser POST
Browser request The client sends an HTTP PUT with the file body to the signed URL. The browser submits a multipart/form-data HTML form to the bucket endpoint.
Authorization The URL is generated for one S3 action and is limited by the signing principal’s permissions. The form includes a signed policy and SigV4 fields that authenticate and constrain the request.
Constraints The documented example signs the bucket, key, content type, and expiry. The policy states the permitted conditions, so it fits when your upload needs form-level rules.
Browser cross-origin setup Configure bucket CORS for your site origin, the PUT method, and the headers you send. CORS rules are matched against the actual browser request’s origin, method, and headers, so verify them for the form submission you use.

For most application uploads where your server already creates a single object, presigned PUT is the simpler path. Use signed POST when a native form workflow or policy conditions are the real requirement.

Security rules that decide whether this is safe

  • Scope the signing identity. A presigned URL can do no more than the signing principal could do. Give the backend role only s3:PutObject on the upload prefix it needs, and nothing broader.
  • Keep keys unpredictable and server-generated. S3 replaces an existing object when you upload to the same key, so never reuse a key where replacement is not intended.
  • Match the expiry to the flow. S3 checks the URL’s expiry when a request begins. If the signing credentials are temporary, the URL can stop working when those credentials expire, which may be earlier than the duration you requested. The CLI and SDKs can generate URLs valid for up to seven days, but that ceiling is not a sensible default for an end-user upload.
  • Treat the URL as a secret. Keep it out of application logs, analytics events, and public error messages. Anyone holding it has the capability until it expires.
  • Enforce HTTPS. AWS recommends enforcing TLS in bucket policies with the aws:SecureTransport condition.
  • Verify the object after upload. A valid signature proves only that the request was authorized to write that key. It does not check file size, true content type, malware, or whether the file belongs to the user. Your application must verify the object (for example, with a HEAD request for size and type, plus a scan if your threat model requires one) before treating it as accepted content. Neither CORS rules nor a file extension validates content.
  • Consider recovery controls. Default server-side encryption for new objects and S3 Versioning let you preserve earlier object versions and recover from unintended overwrites. These are bucket settings you choose, not requirements for presigning.

Troubleshooting

SignatureDoesNotMatch

AWS lists five checks for this error:

  • Synchronize the server’s and client’s system clocks.
  • Use the generated URL without modifying it.
  • Confirm the URL has not expired.
  • Send a Content-Type header that matches the signed value.
  • Use the bucket’s correct region in the client and the URL.

Browser upload fails but curl works

Open the browser’s developer tools and find the OPTIONS preflight request for the PUT. Check that the origin matches your CORS AllowedOrigins exactly, that PUT appears in AllowedMethods, and that every header the browser requests appears in AllowedHeaders. A mismatch in any one of these blocks the request before it reaches S3’s signature check.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

“

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
Outdated Drivers Are Slowing You DownFree scan - exact matches
Windows Errors? Fix Them Before They SpreadFree repair scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.