Using AWS Pre-Signed URLs for POST Operations (non-S3)
Technically pre-signed URLs can be used for POST operations on other AWS services, but they function very differently than the S3 "Presigned POST" you are likely thinking of.
For most services (like API Gateway, Lambda, or EC2), using a pre-signed URL for a POST request is impractical because the signature requires you to know the exact content (body) of the request before you generate the URL.
Here is the detailed breakdown of why S3 is special and how it works for other services.
1. The S3 Exception: "Presigned POST" (Policy-Based)
S3 is unique because it supports a specific feature called Browser-Based Uploads using POST.
- How it works: Instead of signing the request body (the file), you sign a Policy Document. This document defines rules (e.g., "allow any file smaller than 5MB" or "key must start with /user/uploads/").
- The Result: You generate a signature for that policy and hand it to the client. The client can then upload any file that fits the policy.
- Why it's useful: The server doesn't need to see the file first.
2. Other Services: Standard SigV4 (Hash-Based)
For almost every other AWS service (API Gateway, Lambda Function URLs, etc.), "pre-signing" just means putting the standard AWS Signature Version 4 (SigV4) parameters into the query string.
- The Limitation: Standard SigV4 requires calculating a SHA-256 hash of the entire request body.
- The Problem: To generate the URL, you must know exactly what data the user is going to send. If you generate a pre-signed URL for a POST request to API Gateway, and the user changes even one character in the JSON body, the signature becomes invalid and the request fails.
- UNSIGNED-PAYLOAD: S3 allows you to set the body hash to
UNSIGNED-PAYLOADto skip this check. Most other AWS services (including API Gateway and Lambda) do not supportUNSIGNED-PAYLOAD. They require the exact body hash in the signature.
Summary Comparison
| Feature | Amazon S3 | Other Services (API Gateway, Lambda, etc.) |
|---|---|---|
| Mechanism | Signs a Policy Document (rules) | Signs the Request Hash (exact content) |
| Client Flexibility | High. Client can upload any file that matches the policy rules. | None. Client must send exact payload known at signing time. |
| Primary Use Case | User uploads; HTML Forms. | Single-click actions (GET) or strict machine-to-machine comms. |
| "Unsigned Payload" | Supported (UNSIGNED-PAYLOAD) |
Generally Not Supported (Body must be hashed) |
When would you use a pre-signed POST for non-S3 services?
It is rare, but you might use it if the payload is fixed and known in advance.
- Example: You want to send a user a "Vote Yes" link that triggers a POST request to a Lambda function. Since the body is always
{"vote": "yes"}, you can pre-calculate the hash, sign the URL, and email it to them.
The Standard Workaround
If you need a user to POST arbitrary data to a non-S3 service (like submitting a form to API Gateway) without them having AWS credentials:
- Don't use pre-signed URLs.
- Instead, leave the API endpoint public (unauthenticated).
- Secure it with a standard API Key or a custom Lambda Authorizer (e.g., validating a JWT token) rather than AWS IAM/SigV4.