Presigned URLs

Presigned URLs let you share objects or accept uploads without exposing your credentials. The URL is valid for a limited time and includes a cryptographic signature.

Generate a Download URL

Python

url = s3.generate_presigned_url(
    "get_object",
    Params={"Bucket": "photos", "Key": "vacation.jpg"},
    ExpiresIn=3600,  # 1 hour
)
print(url)

AWS CLI

aws --endpoint-url http://localhost:9000 s3 presign s3://photos/vacation.jpg --expires-in 3600

Go

req, _ := svc.GetObjectRequest(&s3.GetObjectInput{
    Bucket: aws.String("photos"),
    Key:    aws.String("vacation.jpg"),
})

url, _ := req.Presign(1 * time.Hour)
fmt.Println(url)

Generate an Upload URL

Allow someone to upload a file without credentials:

Python

url = s3.generate_presigned_url(
    "put_object",
    Params={
        "Bucket": "uploads",
        "Key": "user-file.pdf",
        "ContentType": "application/pdf",
    },
    ExpiresIn=900,  # 15 minutes
)

The recipient uploads with:

curl -X PUT -H "Content-Type: application/pdf" --data-binary @file.pdf "PRESIGNED_URL"

URL Parameters

Presigned URLs include these query parameters:

Parameter Description
X-Amz-Algorithm Always AWS4-HMAC-SHA256
X-Amz-Credential Access key and scope
X-Amz-Date Timestamp of signature
X-Amz-Expires Validity duration in seconds
X-Amz-SignedHeaders Headers included in signature
X-Amz-Signature The HMAC-SHA256 signature

Security Notes

  • Presigned URLs grant access to anyone who has the URL
  • Keep expiration times as short as practical
  • Use HTTPS in production to prevent URL interception
  • Each URL is tied to a specific operation (GET or PUT)