S3 Gateway
Authentication
The gateway uses AWS Signature V4 for every request, in either header or query (presigned URL) form. The signing key is derived from the secret paired with your API token.
How to get an S3-capable token
- Open the dashboard and go to the API tokens page.
- Click Generate token, give it a label, and submit.
- Uploom shows the
accessKeyIdandsecretAccessKeyone time. Copy the secret — it won't be shown again.
Token shape
An S3-capable token is a single record with the fields
accessKeyId, secretAccessKey, userId,
scopes, createdAt, and revokedAt.
The secret is stored encrypted at rest with a per-user data key. Tokens
that predate the gateway feature don't have a stored secret and are
rejected with AccessDenied: Token not S3-capable — mint a
new one if you see that error.
Signing the request
SigV4 normalises the request, builds a string-to-sign, and computes an HMAC-SHA256 signature using a key derived from your secret plus the request date, region, and service. All standard SDKs (AWS CLI, boto3, AWS SDK v3, rclone, …) do this automatically. You only need to point them at the gateway and supply the credentials.
Header form
Authorization: AWS4-HMAC-SHA256 Credential=<accessKeyId>/<date>/<region>/s3/aws4_request,
SignedHeaders=<list>, Signature=<hex>
X-Amz-Date: 20260612T153000Z Query form (presigned URL)
GET /<bucket>/<key>?X-Amz-Algorithm=AWS4-HMAC-SHA256
&X-Amz-Credential=<akid>/<date>/<region>/s3/aws4_request
&X-Amz-Date=<iso8601-basic>
&X-Amz-Expires=300
&X-Amz-SignedHeaders=host
&X-Amz-Signature=<hex> Time-window enforcement
- Header form: the signed time must be within ±5 minutes of gateway time.
- Query form: same ±5 minutes, plus the URL cannot be used after the signed expiry.
Clock drift beyond the window is rejected with
RequestTimeTooSkewed.
Troubleshooting
| Error | Likely cause |
|---|---|
Token not S3-capable | Token was created before the gateway feature and has no stored secret. Generate a new one. |
InvalidAccessKeyId | Wrong key, revoked token, or typo. |
SignatureDoesNotMatch | Wrong region, wrong secret, or a proxy/SDK rewriting the request. |
RequestTimeTooSkewed | Clock drift > 5 minutes. Sync with NTP. |