# Presigned URLs

SigV4 and SigV2 presigned URLs stand in for the Authorization header, checked for shape and expiry but never for their signature.

A presigned URL carries its credential in the query string, so a browser or a plain HTTP client can fetch an object with no header. The simulator accepts the URLs an SDK makes. A URL signed with 64 zeros works too, as long as it is well formed and fresh. Fetch an object with a SigV4 URL built by hand:

```bash
now=$(date -u +%Y%m%dT%H%M%SZ)
curl -s "$RYSTIC_URL/acme-demo-site/robots.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIOSFODNN7EXAMPLE%2F${now%T*}%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=$now&X-Amz-Expires=300&X-Amz-SignedHeaders=host&X-Amz-Signature=0000000000000000000000000000000000000000000000000000000000000000"
# -> User-agent: *
# -> Allow: /
```

An SDK presigns offline, against the endpoint it is configured with, so `aws s3 presign s3://acme-demo-site/robots.txt` and boto3's `generate_presigned_url` give URLs the simulator takes the same way.

### What the simulator checks

The URL's parameters stand in for the `Authorization` header and never reach the operation as arguments. The simulator checks the URL's shape and its expiry against the real clock:

| The URL | The simulator returns |
|---|---|
| SigV4 (`X-Amz-Algorithm`, `X-Amz-Credential`, `X-Amz-Date`, `X-Amz-Expires`, `X-Amz-SignedHeaders`, `X-Amz-Signature`) missing or repeating a parameter, an algorithm other than `AWS4-HMAC-SHA256`, a scope day other than `X-Amz-Date`'s, `X-Amz-Expires` above 604800 (seven days), signed headers without `host` or a signature other than 64 lowercase hex digits | `400 AuthorizationQueryParametersError` |
| SigV2 (`AWSAccessKeyId`, `Signature`, `Expires`) missing or repeating a parameter, or `Expires` not a Unix time | `403 AccessDenied` |
| Well-formed, past its expiry | `403 AccessDenied`, `Request has expired` |
| Two mechanisms at once: both forms, or a form beside an `Authorization` header | `400 InvalidArgument`, `Only one auth mechanism allowed` |

**Differs from S3:** the simulator never checks a presigned URL's signature, so a URL signed with the wrong secret is not caught.

A SigV2 URL whose `Expires` is long past returns `Request has expired`:

```bash
curl -s "$RYSTIC_URL/acme-demo-site/robots.txt?AWSAccessKeyId=AKIAIOSFODNN7EXAMPLE&Signature=abc&Expires=1" | grep -oE '<Code>[^<]*|<Message>[^<]*'
# -> <Code>AccessDenied
# -> <Message>Request has expired
```

---

Source: https://www.rystic.ai/docs/simulators/s3/features/presigned-urls · Markdown: https://www.rystic.ai/docs/simulators/s3/features/presigned-urls.md
