S3 presigned URLs provide temporary access to an Amazon S3 operation without handing the recipient the signing account’s credentials. They are useful for downloads and direct uploads, but anyone who possesses a valid URL can generally exercise its permitted operation. Treat the complete URL as a bearer capability, not an ordinary public link.
A secure design starts before signing. The application must decide who may request access, which object and operation are allowed, and how long that access should remain useful. Expiration narrows exposure; it does not replace authorization or safe handling of the resulting link.
Authorize the request before signing
Authenticate the caller and check access to the specific object or upload destination. A signer with permission to many objects must not sign whichever key an untrusted user supplies. The application’s authorization boundary determines which of the signer’s capabilities it is willing to delegate.
Use server-controlled object selection when possible. For a download, map an approved record to its storage key. For an upload, allocate a destination within the user’s authorized workflow. Predictable keys and path prefixes are organizational conveniences, not sufficient proof of ownership.
Keep tenant and role checks explicit. A signed URL can bypass the application’s normal download route, so the decision made during issuance must be correct. Test cross-account requests using synthetic records and verify that unauthorized callers never receive a valid capability.
Limit the signer’s own permissions
A presigned URL’s capabilities depend on the permissions of the identity that created it and the applicable S3 policies. Use a signing role with only the operations and resources required by the product. Broad account access creates unnecessary risk even when the application currently signs narrow requests.
Separate download and upload needs where that improves clarity. A workflow that only reads approved objects should not require general deletion authority. Review bucket policies, access-point policies, encryption requirements, and any other controls that affect the actual request.
Do not describe a private bucket as making a leaked URL harmless. The URL is the mechanism intentionally granting access despite the absence of the recipient’s own AWS credentials. Protect both the signing service and the capability it issues.
Choose a useful expiration window
Set a lifetime based on the user’s task and the sensitivity of the object. Avoid long defaults chosen only to prevent support questions. A short lifetime reduces the period during which a copied link can be reused, but must allow legitimate clients to begin the intended request.
Temporary signing credentials can cause a URL to expire earlier than its requested lifetime. Other policy restrictions can also deny it. Test the real role and credential source, not just the duration argument passed to the SDK.
S3 checks expiration at the relevant request boundary. AWS documents that a download begun before expiration can continue, while restarting it afterward can fail. Expiration therefore does not mean that an already-running transfer is instantly interrupted at a wall-clock deadline.
Deliver links without unnecessary disclosure
Use HTTPS and return the URL only to the authorized client through the intended application response. Do not place it into public analytics, support screenshots, search indexes, or broadly shared chat messages. Query parameters can contain sensitive authorization material even when the object path looks ordinary.
Review application and proxy logging. A system that records every complete response or request URL can retain the capability in a place with wider access than the object itself. Redact the relevant query information and keep enough nonsecret context to diagnose issuance failures.
Consider referrer behavior and embedded third-party resources in download workflows. Do not assume browser defaults and every intermediary will protect the link exactly as required. Keep sensitive downloads on a deliberately reviewed path rather than attaching capability URLs to unrelated tracking events.
Design uploads as a separate trust boundary
A permitted upload is not proof that the uploaded content is safe. Use a controlled object key and prevent unintentional replacement of an existing business object. AWS documents that an upload to an existing key can replace its object, so destination allocation matters.
Choose the upload mechanism and its supported conditions deliberately. Presigned PUT requests and presigned POST workflows have different interfaces and constraints. Bind the expected request details using the SDK and validate the completed object against the application’s requirements.
Keep new uploads out of public serving paths until the product’s validation or scanning process approves them. Verify size, content handling, ownership, and any required checksum behavior. A claimed Content-Type is not a complete file-safety assessment.
Understand reuse and revocation limits
A presigned URL is not inherently a one-time-use token. If the application needs single-use behavior, design and verify an additional mechanism that actually enforces it. A database flag saying a link was issued does not prevent someone from reusing the already-issued capability directly against S3.
Plan emergency response for a leaked URL. Applicable credential or policy changes may affect validity, but their scope and operational consequences need review. Do not promise a universal per-link revocation button unless your architecture provides one.
Record the expected behavior when the source object changes or access policies are updated. Object versioning and version-specific access can influence which content is served. Choose whether the capability refers to a particular version or the current key according to the business requirement.
Verify the complete workflow
Use synthetic objects to test authorized issuance, denied cross-tenant access, expired requests, credential expiration, and required upload headers. Confirm that an invalid or modified request fails without exposing secrets in the error path.
Test a retry after expiration separately from a transfer started before expiration. Include slow clients and interrupted uploads where those are part of the product. The application should obtain a newly authorized capability when appropriate, not extend an old link without checking current permissions.
A practical example is a private report export. The user asks for an approved report, the backend checks ownership, and a narrow role signs a short-lived download. Logs record the report identifier and issuance outcome, not the complete signed query string. A later request repeats authorization rather than assuming yesterday’s access remains valid.
Frequently asked questions
Are presigned URLs safe to share publicly?
No, not for private objects. Possession generally grants the permitted operation while the URL remains valid under applicable credentials and policies.
Are they automatically single-use?
No. Design a separate enforced workflow if single-use behavior is a requirement.
Where should I verify exact limits?
Read AWS’s presigned URL documentation. For handling untrusted upload content after delivery, see our file upload security guide.