Free — no signup required

Presigned URLs: The Temporary Guest Pass

2 min read

The Problem: Private Buckets, Public Downloads

By default, S3 buckets should be private. Making a bucket public to share a file is a security anti-pattern — it exposes every object in the bucket to anyone on the internet. But how do you let a specific authenticated user download a premium video, or let a customer upload their own document, without making the bucket public?

How Presigned URLs Work

A Presigned URL is a time-limited URL generated by your application using the AWS SDK. The URL cryptographically encodes the identity of the IAM principal that generated it, the specific S3 object it grants access to, the HTTP method allowed (GET for download, PUT for upload), and an expiration timestamp.

When a user makes a request with this URL, S3 validates the embedded signature and expiration. If valid, S3 serves the request as if the generating IAM principal made it directly. The user needs no AWS credentials of their own.

User  App Server: "I want to download invoice_2024_01.pdf"
App Server  AWS SDK: generate_presigned_url(bucket, key, expiry=900)
AWS SDK  App Server: "https://bucket.s3.amazonaws.com/invoice_2024_01.pdf?X-Amz-Signature=..."
App Server  User: [presigned URL]
User  S3: GET https://bucket.s3.amazonaws.com/invoice_2024_01.pdf?X-Amz-Signature=...
S3  User: [file contents, directly]

Benefits

  • Security: The bucket remains private. The URL is scoped to a single object and expires automatically.
  • Performance: The user downloads the file directly from S3, not through your application server. This offloads bandwidth and CPU from your app tier.
  • Upload use case: Presigned PUT URLs allow users to upload files directly to S3 without your server acting as a proxy. Your server generates the URL, the user uploads directly, and you receive an event notification (via S3 Event Notifications or EventBridge) when the upload completes.

Expiration considerations: The maximum expiration for a presigned URL generated with IAM role credentials (the most common case) is 12 hours (the maximum session duration of the role). For IAM user credentials, the maximum is 7 days. Design your application to generate URLs on demand rather than caching them.

This is one of 18 chapters

Get every chapter — Kubernetes, Terraform, SRE, distributed systems, and more — with fast daily review built in.

See pricing