HMAC SHA-256 signed URLs prevent unauthorised transformations, hotlinking, and bandwidth abuse. Add expiration timestamps for time-limited access. Constant-time verification stops timing attacks.
Without signing, anyone can request arbitrary transformations — running up your compute bill with width/10000 requests.
Only URLs generated by your application are valid. Third-party sites can't embed your images without permission.
Add a Unix timestamp to make URLs valid for a limited time — perfect for user-uploaded content or premium access.
Constant-time comparison (crypto.timingSafeEqual) prevents attackers from guessing tokens character by character.
Token = hex(HMAC-SHA256(secret, path))
URL = path + "?token=" + token
# With expiration:
Token = hex(HMAC-SHA256(secret, path + "?expires=" + timestamp))
URL = path + "?expires=" + timestamp + "&token=" + token
Add a secret to any source — that's it:
# sources.yml
my-images:
type: s3
bucket: my-bucket
region: us-east-1
secret: "a1b2c3d4e5f6...32-char-random-secret"
Sources without a secret remain open. Signing is opt-in per source.
# Node.js
const crypto = require('crypto');
const token = crypto.createHmac('sha256', secret).update(path).digest('hex');
const signedUrl = path + '?token=' + token;
# Python
import hmac, hashlib
token = hmac.new(secret.encode(), path.encode(), hashlib.sha256).hexdigest()
# PHP
$token = hash_hmac('sha256', $path, $secret);
# Ruby
token = OpenSSL::HMAC.hexdigest('sha256', secret, path)
# Go
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(path))
token := hex.EncodeToString(mac.Sum(nil))
Image Foundry accepts tokens via three query parameter names for cross-provider compatibility:
| Parameter | Compatible With |
|---|---|
?token= | Image Foundry native |
?bossToken= | ImageBoss format |
?s= | Imgix format |
Add a secret to your source config. Generate tokens server-side. Done.